powershell - 为什么命令在Windows CMD中而不在PowerShell中起作用?

标签 powershell psexec

我有一个脚本,该脚本将可执行文件和.ps1保存到远程计算机列表中。
然后,它在每台计算机上运行可执行文件。
我必须使用.ps1来调用可执行文件,因为它在静默运行时的设置方式。

我注意到我的命令之一从命令行快速运行,但似乎卡在脚本中。有什么理由会发生这种情况吗?

该命令是:

psexec -s @C:\myscript\computers.txt cmd /c "Powershell Set-ExecutionPolicy -Scope CurrentUser -ExecutionPolicy Bypass && PowerShell -noninteractive -file "C:\Install.ps1""

这是我的整个脚本:
cls #clear screen

function CopyFiles {

    # Get .exe from source and place at destination workstation
    $source2="\\mainserver\program.exe"
    $destination2="\\$line\c$\program.exe"           # place .exe on C:\ directory of worstation
    Copy-Item -Recurse -Filter *.* -path $source2 -destination $destination2 -Force

    # Get .bat from source and place at destination workstation
    $source3="\\fileserver\Install.ps1"
    $destination3="\\$line\c$\Install.ps1"  # place .bat on C:\ directory of worstation
    Copy-Item -Recurse -Filter *.* -path $source3 -destination $destination3 -Force
}

$a = Get-Content "C:\myscript\computers.txt"
foreach($line in $a)
{

  "These options must run in numbered order."
  " "
  " "
  "1. Copy installer to remote computer(s)."
  "2. Remove application from remote computer(s)."
  "3. Install application from remote computer(s)."
  "4. Quit."
  " "
  "Type number and press Enter." 
  $UI = Read-Host -Prompt ' '

  If ($UI -eq 1) {
    CopyFiles
  } ELSEIF ($UI -eq 2) {
  psexec @C:\myscript\computers.txt -c "\\fileserver\Remove.bat"
  } ELSEIF ($UI -eq 3) {
  psexec -s @C:\myscript\computers.txt cmd /c "Powershell Set-ExecutionPolicy -Scope CurrentUser -ExecutionPolicy Bypass && PowerShell -noninteractive -file "C:\Install.ps1""
  } ELSEIF ($UI -eq 4) {
  "Good Bye"
  }
}

最佳答案

根本原因是因为PowerShell has a more standard rule to parse parameters与cmd不同。在PowerShell中,如果参数以引号开头,那么它也将以引号结尾。但是,如果在引号后没有分隔符(例如空格或制表符),则在cmd中该参数将继续。这意味着"powershell someargs "another""在PowerShell中是2个参数,而在cmd中只有1个参数。尝试从PowerShell回显命令,您会立即看到

PS D:\> echo psexec -s @C:\myscript\computers.txt cmd /c "Powershell Set-ExecutionPolicy -Scope CurrentUser -ExecutionPolicy Bypass && PowerShell -noninteractive -file "C:\Install.ps1""
psexec
-s
@C:\myscript\computers.txt
cmd
/c
Powershell Set-ExecutionPolicy -Scope CurrentUser -ExecutionPolicy Bypass && PowerShell -noninteractive -file
C:\Install.ps1

与被识别为cmd的cmd相比,C:\Install.ps1被拆分为不同的参数:
D:\>type testparam.bat
@echo off
:loop
if [%1]==[] exit /b
echo [%1]
shift
goto :loop

D:\>testparam.bat psexec -s @C:\myscript\computers.txt cmd /c "ps -ExecutionPolicy Bypass AND ps -noninteractive -file "C:\Install.txt""
[psexec]
[-s]
[@C:\myscript\computers.txt]
[cmd]
[/c]
["ps -ExecutionPolicy Bypass AND ps -noninteractive -file "C:\Install.txt""]

如您所见,中间引号不是嵌套引号,而是按原样保留在命令中,然后cmd /c将具有另一种怪异的行为:剥离第一个和最后一个引号,然后将其余内容作为一个命令运行

PowerShell也strips double quotes,但仅是每个参数的外部,并且在传递给命令之前

现在要修复,您必须使用以下两种方法之一在参数中包括双引号
psexec -s @C:\myscript\computers.txt cmd /c "Powershell Set-ExecutionPolicy -Scope CurrentUser -ExecutionPolicy Bypass && PowerShell -noninteractive -file ""C:\Install.ps1"""
psexec -s @C:\myscript\computers.txt cmd /c "Powershell Set-ExecutionPolicy -Scope CurrentUser -ExecutionPolicy Bypass && PowerShell -noninteractive -file `"C:\Install.ps1`""
psexec -s @C:\myscript\computers.txt cmd /c '"Powershell Set-ExecutionPolicy -Scope CurrentUser -ExecutionPolicy Bypass && PowerShell -noninteractive -file "C:\Install.ps1"'
psexec -s @C:\myscript\computers.txt cmd /c --% "Powershell Set-ExecutionPolicy -Scope CurrentUser -ExecutionPolicy Bypass && PowerShell -noninteractive -file "C:\Install.ps1""

或者,如果文件路径中没有空格,则只需删除它们即可在cmd和PowerShell中使用
psexec -s @C:\myscript\computers.txt cmd /c "Powershell Set-ExecutionPolicy -Scope CurrentUser -ExecutionPolicy Bypass && PowerShell -noninteractive -file C:\Install.ps1"

实际上,如果路径包含"C:\some dir\Install.ps1"之类的空格,则您的命令将在cmd和PowerShell中均失败,因为现在cmd还将空格后的部分拆分为新的参数。试试看
psexec -s @C:\myscript\computers.txt cmd /c "Powershell Set-ExecutionPolicy -Scope CurrentUser -ExecutionPolicy Bypass && PowerShell -noninteractive -file "C:\some dir\Install.ps1""

关于powershell - 为什么命令在Windows CMD中而不在PowerShell中起作用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47215705/

相关文章:

powershell - 登录-AzureRmAccount 和选择-AzureRmSubscription

batch-file - PSEXEC 系统找不到指定的文件错误

batch-file - 批处理文件 - 捕获 PSEXEC 结果

powershell - 使用Psexec运行Powershell脚本时出错

string - PowerShell Out-File 在字符之间输出额外的空格

PowerShell 无法确定正在使用的参数集

powershell - Powershell中的模拟-访问远程文件

windows - PsExec 抛出错误消息,但工作没有任何问题

command-line - 批处理文件中的 sleep 命令?

PowerShell 等待应用程序启动