【问题标题】:PShell script works in ISE, but when running .ps1PShell 脚本在 ISE 中有效,但在运行 .ps1 时
【发布时间】:2021-07-11 12:46:23
【问题描述】:

我编写了一个脚本来映射网络驱动器 (NAS),如果未映射,则取消映射。

# NAS.ps1
If (!(Test-Path N:)) {
    $User = "User"
    # Pwd in script will be removed later
    $Pwd = ConvertTo-SecureString -String "Password" -AsPlainText -Force
    
    $Credential = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $User, $Pwd

    New-PSDrive -Name "N" -PSProvider "FileSystem" -Root "\\192.168.1.100\NAS" -Persist -Credential $Credential
} else {
    Remove-PSDrive -Name "N"
}

我使用 Windows Powershell ISE 对其进行编辑。当我运行它时,我看到驱动器在我的 Windows 资源管理器窗口中出现或消失。太完美了。

使用 Powershell 运行

但是,当我右键单击NAS.ps1 > "Run with Powershell" 时,PS 窗口会迅速出现/消失,并且驱动器既没有映射也没有取消映射(没有任何变化)。

运行 Powershell,然后运行 ​​./NAS.ps1

如果我尝试运行 Powershell,使用我的脚本 cd 到文件夹并手动运行它,它会继续安装驱动器:

PS C:\Users\User\Desktop> .\NAS.ps1

Name           Used (GB)     Free (GB) Provider      Root                                               CurrentLocation
----           ---------     --------- --------      ----                                               ---------------
N                1150.44       3201.81 FileSystem    \\192.168.1.100\NAS

PS C:\Users\User\Desktop> .\NAS.ps1

Name           Used (GB)     Free (GB) Provider      Root                                               CurrentLocation
----           ---------     --------- --------      ----                                               ---------------
N                1150.44       3201.81 FileSystem    \\192.168.1.100\NAS

以管理员身份运行 Powershell,然后运行 ​​./NAS.ps1

如果我以管理员身份启动 Powershell 并运行我的脚本,则不会显示任何内容:

PS C:\Windows\system32> cd C:\Users\User\Desktop
PS C:\Users\User\Desktop> .\NAS.ps1
PS C:\Users\User\Desktop> .\NAS.ps1
PS C:\Users\User\Desktop> .\NAS.ps1

使用Get-PSDrive 它显示为已安装,我可以 cd 进入它,但从 Win 中。资源管理器窗口没有出现

【问题讨论】:

  • 可能是由于您右键单击并运行时系统上设置的执行策略。首先尝试dot sourcing ps1。 . .\NAS.ps1
  • 至于运行提升(以管理员身份):不幸的是,提升时建立的驱动器映射在 not 提升时对同一帐户可见,所以该行为是预期的。

标签: powershell network-drive


【解决方案1】:

解决方法是在映射驱动时使用-Scope Global,并使用net use取消映射。

工作代码:

# NAS
Set-StrictMode -Version 2.0
If (!(Test-Path N:)) {

    $User = "user"
    $Pswd = ConvertTo-SecureString -String "Password" -AsPlainText -Force

    $Credential = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $User, $Pswd

     New-PSDrive -Name "N" -Root "\\192.168.1.100\NAS" -Credential $Credential -PSProvider "FileSystem" -Persist -Scope Global
} else {
    Net Use "N:" /delete
}

【讨论】:

  • 干得好。您无法使用Remove-PSDrive 删除永久驱动器是一个已知的长期存在的错误:请参阅GitHub issue #7829。对我来说,要求 -Persist-Scope Global 结合起来也像一个错误 - 即使行为是 documented: "[...] Persist 参数不会持续创建超出范围的 PSDrive命令正在运行的位置。”
  • 一直认为 PSDrive 仅在 PowerShell 中可见。不知道持久化会在操作系统级别上映射它,很高兴知道!
  • @SantiagoSquarzon,是的,尽管从脚本调用时需要-Scope Global这一事实既违反直觉又在逻辑上无关。我创建了GitHub issue #15752 来提议删除此要求(尽管 Windows PowerShell 永远不会看到这种改进)。
【解决方案2】:

好的,第一个问题是否设置执行策略?

默认情况下,不允许执行脚本。

您可以使用此 cmdlet 来做到这一点。

# To configure execution policy
Set-ExecutionPolicy -ExecutionPolicy Unrestricted

# To check execution policy
Get-ExecutionPolicy -List

看起来很糟糕的第二件事是 $pwd $pwd,定义当前路径的系统默认变量。 更好的用户 $Pass 或 $Pword 或 $Pswd 等。

最后一个问题,你在做这个 New-PSDrive 做什么?

我为什么要问。因为据我所知,PSDrive 仅映射当前 PowerShell 会话。这不会像映射驱动器一样显示您的驱动器。您可以使用它来复制文件或执行操作。但是,当您关闭此 PowerShell 会话时,映射将被删除。

这与“网络使用”不同 你实际上可以这样做

$net = new-object -ComObject WScript.Network
$net.MapNetworkDrive("n:", "\\192.168.1.100\NAS", $false, $User, $password)

或者老式的方式:

$script = 'net use N: \\192.168.1.100\NAS /persistent:yes /u:' + $User + ' ' + $Password
Invoke-Expression $script

【讨论】:

  • 您从哪里听说使用 New-PSDrive 映射驱动器只会在 Powershell 会话关闭之前保持映射状态?这根本不是真的。
  • 好点 re$PWD,但如果执行策略是问题所在,那是否也会影响提升的(以管理员身份运行)会话(OP 声明它在那里工作)? @AbrahamZinala,使用 New-PSDrive 创建的驱动器默认是会话范围的,但确实使用 OP 使用的 -Persist 开关,因此确实没有理由避免 New-PSDrive .
  • P.S.:您不能调用存储在带有 & 的字符串中的整个命令行 - 而且不需要这样的字符串;只需使用net use N: \\192.168.1.100\NAS /persistent:yes /u:$User $Password
  • @mklement0,你需要一个 youtube chanel!
  • 当您在本地范围内(没有点源)命令时,Persist 参数不会持续创建超出您运行命令的范围的 PSDrive。如果您在脚本中运行 New-PSDrive 并希望新驱动器无限期保留,则必须对脚本进行点源。并且要强制新驱动器持久存在,您必须将 Global 指定为 Scope 参数的值并在命令中包含 Persist。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-03-22
  • 2011-05-04
  • 1970-01-01
  • 2011-10-12
  • 1970-01-01
  • 2018-09-08
相关资源
最近更新 更多