如何正确转义嵌套在启动进程命令中的"启动进程参数列表"命令中的空格?



很长一段时间以来,我一直在使用包含以下行的powershell脚本以不同的用户身份自动启动各种进程,并具有提升的权限:

start-process powershell -credential <username> -argumentlist '-command &{start-process <executable.exe> -verb runas -argumentlist <c:pathtofilethatexecutable-should-open.ext>}' -workingdirectory c:windowssystem32

以这种方式格式化它让我可以简单地创建一个方便的脚本快捷方式。这工作正常...只要<c:pathtofilethatexecutable-should-open.ext>不包含空格。但是,该文件现在位于包含空格的文件路径中,这是我无法更改的。

有无数的线程处理如何正确转义Start-Process-ArgumentList参数参数,但似乎没有一个解决方案适用于空间位于嵌套-ArgumentList中的情况。我已经尝试了好几天来找到单引号和双引号、反引号、反斜杠、$variables$($variables)@("arguments","as","arrays")、不使用&等的神奇酱汁组合。


谁能帮我做到这一点?我当然对不使用Start-Process的其他解决方案持开放态度,但理想情况下,工作解决方案应该在独立脚本中工作,一旦运行,应该不会打开额外的控制台窗口。

对于大多数不会直接抛出错误的尝试,我看到的行为是嵌套的Start-Processcmdlet 将c:pathtofilewith spacesfile.ext解释为两个单独的参数,即c:pathtofilewithspacesfile.ext.

我使用此语法打开几个不同的管理应用程序,但作为一个具体示例,这是我一直在测试但未能正常工作的应用程序。

原始工作脚本:

start-process powershell -credential domainusername -argumentlist '-command &{start-process mmc -verb runas -argumentlist c:custom-aduc.msc}' -workingdirectory c:windowssystem32`

新的非工作脚本:

start-process powershell -credential domainusername -argumentlist '-command &{start-process mmc -verb runas -argumentlist c:new pathcustom-aduc.msc}' -workingdirectory c:windowssystem32

作为参考,我无法更改路径的原因是custom-aduc.msc现在保留在OneDrive上,令人愤怒的是,它无法从drive:pathOneDrive - CompanyName更改其本地同步位置。这是 OneDrive 的大量支持功能请求,但尚未提交。

感谢您的任何见解。


附言我已经考虑过替代解决方案,例如:

  1. 但是,让脚本首先将文件下载/复制到没有空格的本地路径,这会阻止我使用可执行文件来修改文件,否则我将不得不监视更改并重新上传它们。

  2. 将 OneDrive 路径装载为单独的驱动器号。但这远不是一个独立的解决方案,而且似乎很严厉。

TL;DR:回答名义上的问题:这可能是可能的,但简单地将Start-Process命令拆分为不同的脚本要容易得多,以避免将一个嵌套在另一个的引号内。

经过对转义语法的更多尝试和错误,我能够找到一个可接受的解决方案。但是,我不得不将其拆分为两个单独的脚本文件,以避免将第二个Start-Process(以及其-ArgumentList参数(嵌套在任何其他引号中。

脚本1.ps1

#runas /user:domainusername "powershell -file `"c:script2.ps1`""
# Equivalent to the above, but provides a nicer credential prompt:
Start-Process -FilePath powershell -Credential domainusername -WorkingDirectory "c:windowssystem32" -ArgumentList "-File `"c:script2.ps1`""

脚本2.ps1

Start-Process -FilePath mmc -Verb runas -ArgumentList "`"C:pathwith spacesaduc.msc`""

重要的是,这样我就可以对每个-ArgumentList使用通常的转义方法,而不会相互干扰。可能仍然可以使用 cmd 解释器转义 (( 和 posh 转义 (`( 的组合在一行中完成所有这些工作,但我没有耐心弄清楚。也可以将其破解为单个脚本,但我不能被打扰。

此时,我可以简单地创建调用script1.ps1的快捷方式来实现所需的结果,就像我以前一样。

我喜欢将其用于至少 3 个不同的可执行文件,并使用 3 个不同的用户名(我的平均 joe 帐户和两个不同的超级用户帐户(。为了避免每个可执行文件+用户名组合需要两个脚本,我概括了脚本,如下所示:

脚本1.ps1

$app = $args[0]
$user = $args[1]
$script2 = "C:pathtoscript2.ps1"
# Dont run as different user if this is my usual Windows login
# Otherwise I have to enter a password for no good reason
if($user -eq "domainnon-su-account") {
& powershell -file "$script2" $app
}
else {
#runas /user:$user "powershell -file `"$script2`" $app"
# Equivalent to the above, but provides a nicer credential prompt:
Start-Process -FilePath powershell -Credential $user -WorkingDirectory "c:windowssystem32" -ArgumentList "-File `"$script2`" $app"
}

脚本2.ps1

$app = $args[0]
switch($app) {
"aduc" {
Start-Process -FilePath mmc -Verb runas -ArgumentList "`"C:pathwith spacesaduc.msc`""
break
}
"posh" {
Start-Process -FilePath powershell -Verb runas -ArgumentList "-nologo -noexit -command `"&{. `"C:pathwith spacescustom-powershell-profile.ps1`"}`""
break
}
"posh-noprofile" {
Start-Process -FilePath powershell -Verb runas -ArgumentList "-nologo -noexit"
break
}
"mecm" {
& "C:Program Files (x86)Microsoft Endpoint ManagerAdminConsolebinMicrosoft.ConfigurationManagement.exe"
break
}
}

因此,快捷方式目标如下所示:

C:WindowsSystem32WindowsPowerShellv1.0powershell.exe -file "C:pathtoscript1.ps1" aduc domainusername

打开 Powershell 并强行点采购我的自定义配置文件脚本并不是真正必要的,但它避免了接触超级用户帐户的 Powershell 配置文件的需要,使其更具可移植性。

现在我已经彻底展示了大多数降价解释器呈现嵌套/转义 powershell 引用的弱点,我向你道个好日子。希望这对至少另一个人有用。

最新更新