为什么命令在 Windows CMD 而不是 PowerShell 中工作?
Why does command work in Windows CMD and not PowerShell?
我有一个脚本可以将可执行文件和 .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 中,如果引号后没有分隔符(如 space 或制表符),则参数将继续。这意味着 "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
C:\Install.ps1
被拆分为不同的参数,与 cmd 相比,它被识别为一个参数:
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""
或者如果文件路径没有任何 spaces 你可以简单地删除它们,这将在 cmd 和 PowerShell 中工作
psexec -s @C:\myscript\computers.txt cmd /c "Powershell Set-ExecutionPolicy -Scope CurrentUser -ExecutionPolicy Bypass && PowerShell -noninteractive -file C:\Install.ps1"
事实上,如果路径包含 spaces,如 "C:\some dir\Install.ps1"
,那么您的命令将在 both cmd 和 PowerShell 中失败,因为现在 cmd 也拆分了该部分在 space 之后添加一个新参数。试试看
psexec -s @C:\myscript\computers.txt cmd /c "Powershell Set-ExecutionPolicy -Scope CurrentUser -ExecutionPolicy Bypass && PowerShell -noninteractive -file "C:\some dir\Install.ps1""
我有一个脚本可以将可执行文件和 .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 中,如果引号后没有分隔符(如 space 或制表符),则参数将继续。这意味着 "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
C:\Install.ps1
被拆分为不同的参数,与 cmd 相比,它被识别为一个参数:
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""
或者如果文件路径没有任何 spaces 你可以简单地删除它们,这将在 cmd 和 PowerShell 中工作
psexec -s @C:\myscript\computers.txt cmd /c "Powershell Set-ExecutionPolicy -Scope CurrentUser -ExecutionPolicy Bypass && PowerShell -noninteractive -file C:\Install.ps1"
事实上,如果路径包含 spaces,如 "C:\some dir\Install.ps1"
,那么您的命令将在 both cmd 和 PowerShell 中失败,因为现在 cmd 也拆分了该部分在 space 之后添加一个新参数。试试看
psexec -s @C:\myscript\computers.txt cmd /c "Powershell Set-ExecutionPolicy -Scope CurrentUser -ExecutionPolicy Bypass && PowerShell -noninteractive -file "C:\some dir\Install.ps1""