当我将参数传递给嵌套的 Start-Process 命令时,PowerShell 删除了多个连续的空格 [英] PowerShell removes multiple consecutive whitespaces when I pass arguments to a nested Start-Process command
问题描述
这个 powershell 代码运行良好:
This powershell code works fine:
powershell -NoProfile -Command {Start-Process -FilePath wscript.exe -Verb RunAs -ArgumentList '"C:UsersTestAccountDesktopcartella con spazi est.vbs" "/CurrentDirectory:C:UsersTestAccountDesktopCartella con spazi" "/AppData:C:UsersTestAccountAppDataRoaming"'}
但是当我输入完整的命令时,powershell 在单词之间只留下一个空格,但在我的路径中有两个连续的:
But when I enter the complete command, powershell leaves only one space between the words but in my path there are two consecutive ones:
Start-Process -FilePath powershell.exe -WorkingDirectory "$env:ALLUSERSPROFILE" -Credential $credential -WindowStyle Hidden -ArgumentList "-NoProfile -Command & {Start-Process -FilePath wscript.exe -Verb RunAs -ArgumentList '`"C:UsersTestAccountDesktopcartella con spazi est.vbs`" `"/CurrentDirectory:C:UsersTestAccountDesktopCartella con spazi`" `"/AppData:C:UsersTestAccountAppDataRoaming`"'}"
同样的错误:
Start-Process -FilePath powershell.exe -WorkingDirectory "$env:ALLUSERSPROFILE" -Credential $credential -WindowStyle Hidden -ArgumentList "-NoProfile -Command Start-Process -FilePath wscript.exe -Verb RunAs -ArgumentList '`"C:UsersTestAccountDesktopcartella con spazi est.vbs`" `"/CurrentDirectory:C:UsersTestAccountDesktopCartella con spazi`" `"/AppData:C:UsersTestAccountAppDataRoaming`"'"
这是错误信息:
如您所见,在错误消息中,路径在单词之间仅包含一个空格,而在代码中我正确输入了两个连续的空格.
As you can see, in the error message the path contains only one space between words, while in the code I have correctly entered two consecutive ones.
这是输入凭据的代码(就在给出错误的行之前):
This is the code to enter the credentials (just before the line that gives an error):
$username = 'Username'
$password = 'Password'
$securePassword = ConvertTo-SecureString $password -AsPlainText -Force
$credential = New-Object System.Management.Automation.PSCredential $username, $securePassword
几天来我一直在让一行代码正常工作,但没有成功.
我输入的那些示例路径实际上是变量(具有不定数量的连续空格),因此通过将 -ArgumentList 括在单引号中,变量不会被扩展.
您可以采用您认为最适合帮助我的策略.
Windows 10 专业版 64 位
Powershell 版本:5.1.19041.1237(集成在 Windows 10 中).
I've been getting a single line of code to work properly for days but without success.
Those example paths I entered are actually variables (with an indefinite number of consecutive spaces) and therefore by enclosing -ArgumentList in single quotes, the variables are not expanded.
You can adopt the strategy you think is most appropriate to help me.
Windows 10 Pro 64-bit
Powershell Version: 5.1.19041.1237 (Integrated in Windows 10).
更新:
@mklement0 问题在于,实际上有问题的行包含一个可扩展变量:
@mklement0 There is the problem that in reality the line in question contains an expandable variable:
Start-Process -FilePath powershell.exe -WorkingDirectory "$env:ALLUSERSPROFILE" -Credential $credential -WindowStyle Hidden -ArgumentList @"
-NoProfile -Command "Start-Process -FilePath wscript.exe -Verb RunAs -ArgumentList '"$PWD est.vbs" "/CurrentDirectory:$PWD" "/AppData:$env:APPDATA"'"
"@
因此,如果路径包含单引号,则该行会出错.
so if the path contains single quotes, the line goes in error.
更新 2:
@mklement0 您的解决方案已停止工作,因为我将它放入我需要的脚本中,并显示以下错误消息:
@mklement0 Your solution has stopped working since I put it in a script, which is what I need, with the following error message:
推荐答案
注意:这个答案解决了 Start-Process
问题;对于 .ps1
文件的不相关问题,在文件资源管理器中双击时,路径中有空格的文件无法运行,请参阅 这个答案.
Note: This answer addresses the Start-Process
problem; for the unrelated problem with .ps1
files whose paths have spaces in them failing to run when they are double-clicked in File Explorer, see this answer.
尝试以下操作,参数通过逐字逐句:
Try the following, with the arguments passed verbatim:
Start-Process `
-FilePath powershell.exe `
-WorkingDirectory "$env:ALLUSERSPROFILE" `
-Credential $credential `
-WindowStyle Hidden `
-ArgumentList @'
-NoProfile -Command "Start-Process -FilePath wscript.exe -Verb RunAs -ArgumentList '"C:UsersTestAccountDesktopcartella con spazi est.vbs" "/CurrentDirectory:C:UsersTestAccountDesktopCartella con spazi" "/AppData:C:UsersTestAccountAppDataRoaming"'"
'@
-Command
参数包含在"..."
中,以便按原样保留命令内部空间.The
-Command
argument is enclosed in"..."
in order to preserve the command-internal spaces as-is.命令字符串中的嵌入
"
字符转义为"
The embedded
"
characters in the command string are escaped as"
外部
-ArgumentList
使用 here-string 以简化嵌入的引用.The outer
-ArgumentList
uses a here-string to simplify the embedded quoting.- 这里使用逐字逐句形式(
@'<newline>...<newline>'@
);如果您需要字符串插值(嵌入变量引用和表达式的能力),请使用 _expandable 形式@"<newline>...<newline><@
- 请参阅下一节.
- The verbatim form (
@'<newline>...<newline>'@
) is used here; use the _expandable form,@"<newline>...<newline>"@
, if you need string interpolation (the ability to embed variable references and expressions) - see next section.
而 PowerShell-在内部是
`
,即反引号,用作转义字符,PowerShell 的 CLI 期望"
字符为-在命令行转义,以符合最广泛使用的转义约定.
While PowerShell-internally it is
`
, the backtick, that serves as the escape character, PowerShell's CLI expects"
characters to be-escaped on the command line, so as to conform to the most widely used escaping convention.
跨平台 PowerShell (Core) 7+ edition 现在也接受
"""
作为"
的替代方案,这是 Windows 上的另一个常见约定.
The cross-platform PowerShell (Core) 7+ edition now also accepts
""
as an alternative to"
, another common convention on Windows.
虽然您可能需要结合这两种转义方法,即使用
`"
来引用"
first 用于 CLI,then 用于 PowerShell 内部使用,在解释-Command
参数的上下文中,这不是在上面的命令中需要,因为内部-ArgumentList
参数使用 single-quoting,其中"
可以按原样使用.While you may situationally have to combine the two escaping approaches, i.e. to use
`"
in order to quote a"
first for the CLI and then for PowerShell-internal use, in the context of interpreting a-Command
argument, this isn't needed in the command above, because the inner-ArgumentList
argument uses single-quoting, inside of which"
can be be used as-is.广义解决方案,通过变量提供参数:
Generalized solution, with arguments provided via variables:
假设要使用其值的变量名为
$dir1
、$dir2
和$dir3
(并且它们的值没有嵌入的"
字符.但 Windows 上的文件系统路径不支持"
).The assumption is that the variable whose value are to be used are named
$dir1
,$dir2
, and$dir3
(and that their values have no embedded"
chars., but"
aren't supported in file-system paths on Windows anyway).Start-Process ` -FilePath powershell.exe ` -WorkingDirectory "$env:ALLUSERSPROFILE" ` -Credential $credential ` -WindowStyle Hidden ` -ArgumentList @" -NoProfile -Command "Start-Process -FilePath wscript.exe -Verb RunAs -ArgumentList '"$($dir1 -replace "'", "''")" "/CurrentDirectory:$($dir2 -replace "'", "''")" "/AppData:$($dir3 -replace "'", "''")"'" "@
here-string (
@"<newline>...<newline>"@
) 的 插值 形式现在必须是用于外部-ArgumentList
参数.The interpolating form of a here-string (
@"<newline>...<newline>"@
) must now be used for the outer-ArgumentList
argument.由于变量值被插入到
powershell.exe
将被视为单引号字符串 ('...'
) 的内容中,因此任何>'
嵌入在变量值中的字符必须转义为''
,这就是- 替换 ""'", "''"
在嵌入式$(...)
子表达式 可以.Since the variable values are interpolated inside what
powershell.exe
will see as a single-quoted string ('...'
), any'
characters embedded in the variable values must be escaped as''
, which is what-replace "'", "''"
in the embedded$(...)
subexpressions does.很难诊断调用外部程序的问题,尤其是在这样的嵌套调用中.
It can be difficult to diagnose problems with calls to external programs, especially in a nested call such as this.
以下创建一个辅助可执行文件,
echoArgsPause.exe
,它回显调用它的完整命令行,以及它解析命令行的各个参数,然后等待一个按键.The following creates a helper executable,
echoArgsPause.exe
, which echoes the full command line it was called with, as well as the individual arguments it has parsed the command line into, and then waits for a keystroke.注意:
作为基于 .NET 的
*.exe
,它使用 .NET 的命令行解析规则,而后者又基于 微软的 C/C++约定.不幸的是,并非所有可执行文件都保证使用相同的约定.而且,确实,WSH CLI(cscript.exe
和wscript.exe
)不支持 embedded"
例如,参数中的字符.
As a .NET-based
*.exe
, it uses .NET's rules for command-line parsing, which in turn is based on Microsoft's C/C++ conventions. Unfortunately, not all executables are guaranteed to use the same conventions. And, indeed, the WSH CLIs (cscript.exe
andwscript.exe
) do not support embedded"
characters in arguments, for instance.
从 Windows PowerShell 运行代码,因为从 PowerShell (Core) 7.2 开始,通过 可执行文件="https://docs.microsoft.com/powershell/module/microsoft.powershell.utility/add-type" rel="nofollow noreferrer">
Add-Type
不是支持.Run the code from Windows PowerShell, because, as of PowerShell (Core) 7.2, creating executables via
Add-Type
isn't supported.为了以后重用,将生成的
.echoArgsPause.exe
文件放在 PATH 中的目录中(在$env:PATH
中列出的目录中).For later reuse, place the resulting
.echoArgsPause.exe
file in a directory in your PATH (in a directory listed in$env:PATH
).要创建不等待击键的变体,请删除
Console.Write("Press a key to exit: ");
和Console.ReadKey(true);
行并将-OutputAssembly .echoArgsPause.exe
更改为-OutputAssembly ./echoArgs.exe
To create a variant that doesn't wait for a keystroke, remove the
Console.Write("Press a key to exit: ");
andConsole.ReadKey(true);
lines and change-OutputAssembly .echoArgsPause.exe
to, say,-OutputAssembly ./echoArgs.exe
Add-Type -OutputType ConsoleApplication -OutputAssembly .echoArgsPause.exe -TypeDefinition @' using System; static class ConsoleApp { static int Main(string[] args) { Console.WriteLine(" raw: [{0}] ", Environment.CommandLine); for (int i = 0; i < args.Length; ++i) { Console.WriteLine("arg #{0}: [{1}]", i, args[i]); } Console.Write("Press a key to exit: "); Console.ReadKey(true); return 0; } } '@
使用
echoArgsPause.exe
解决呼叫问题- 以下自包含示例代码使用您的命令的简化版本,并使用
echoArgsPause.exe
代替您的目标可执行文件 (wscript.exe
)打印命令行和解析的参数. - The following, self-contained sample code uses a simplified version of your command, and uses the
echoArgsPause.exe
in lieu of your target executable (wscript.exe
) to print the command line and the parsed arguments.
Use of
echoArgsPause.exe
to troubleshoot a call# Specify the full path to the helper executable. # Here I'm assuming it is in the current dir. $echoArgsPausePath = "$($PWD.ProviderPath)echoArgsPause.exe" # Sample variable values. $dir1='c: emp''o 1' $dir2='c: emp 2' $dir3='c: emp 3' # Call your command, with echoArgsPause.exe in lieu # of the target executable (wscript.exe) Start-Process ` -FilePath powershell.exe ` -WorkingDirectory "$env:ALLUSERSPROFILE" ` -WindowStyle Hidden ` -ArgumentList @" -NoProfile -Command "Start-Process -FilePath "$echoArgsPausePath" -Verb RunAs -ArgumentList '"$($dir1 -replace "'", "''")" "/CurrentDirectory:$($dir2 -replace "'", "''")" "/AppData:$($dir3 -replace "'", "''")"'" "@
这篇关于当我将参数传递给嵌套的 Start-Process 命令时,PowerShell 删除了多个连续的空格的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!
- 这里使用逐字逐句形式(