1

此 powershell 代码工作正常:

powershell -NoProfile -Command {Start-Process -FilePath wscript.exe -Verb RunAs -ArgumentList '"C:\Users\TestAccount\Desktop\cartella  con  spazi\test.vbs" "/CurrentDirectory:C:\Users\TestAccount\Desktop\Cartella  con  spazi" "/AppData:C:\Users\TestAccount\AppData\Roaming"'}

但是当我输入完整的命令时,powershell 在单词之间只留下一个空格,但在我的路径中有两个连续的空格:

Start-Process -FilePath powershell.exe -WorkingDirectory "$env:ALLUSERSPROFILE" -Credential $credential -WindowStyle Hidden -ArgumentList "-NoProfile -Command & {Start-Process -FilePath wscript.exe -Verb RunAs -ArgumentList '\`"C:\Users\TestAccount\Desktop\cartella  con  spazi\test.vbs\`" \`"/CurrentDirectory:C:\Users\TestAccount\Desktop\Cartella  con  spazi\`" \`"/AppData:C:\Users\TestAccount\AppData\Roaming\`"'}"

与此相同的错误:

Start-Process -FilePath powershell.exe -WorkingDirectory "$env:ALLUSERSPROFILE" -Credential $credential -WindowStyle Hidden -ArgumentList "-NoProfile -Command Start-Process -FilePath wscript.exe -Verb RunAs -ArgumentList '\`"C:\Users\TestAccount\Desktop\cartella  con  spazi\test.vbs\`" \`"/CurrentDirectory:C:\Users\TestAccount\Desktop\Cartella  con  spazi\`" \`"/AppData:C:\Users\TestAccount\AppData\Roaming\`"'"

这是错误消息:

在此处输入图像描述

如您所见,在错误消息中,路径仅包含单词之间的一个空格,而在代码中我正确输入了两个连续的空格。

这是输入凭据的代码(就在给出错误的行之前):

$username = 'Username'
$password = 'Password'
$securePassword = ConvertTo-SecureString $password -AsPlainText -Force
$credential = New-Object System.Management.Automation.PSCredential $username, $securePassword

几天来,我一直在让一行代码正常工作,但没有成功。
我输入的那些示例路径实际上是变量(具有不定数量的连续空格),因此通过将 -ArgumentList 括在单引号中,变量不会被扩展。
你可以采用你认为最适合帮助我的策略。
Windows 10 Pro 64 位
Powershell 版本:5.1.19041.1237(集成在 Windows 10 中)。

更新:

@mklement0 存在的问题是,实际上有问题的行包含一个可扩展变量:

Start-Process -FilePath powershell.exe -WorkingDirectory "$env:ALLUSERSPROFILE" -Credential $credential -WindowStyle Hidden -ArgumentList @"
-NoProfile -Command "Start-Process -FilePath wscript.exe -Verb RunAs -ArgumentList '\"$PWD\test.vbs\" \"/CurrentDirectory:$PWD\" \"/AppData:$env:APPDATA\"'"
"@

因此,如果路径包含单引号,则该行出错。

更新 2:

@mklement0您的解决方案已停止工作,因为我将它放入我需要的脚本中,并带有以下错误消息:

在此处输入图像描述

4

2 回答 2

2

注意:这个答案解决了这个Start-Process问题;对于路径中有空格的文件在文件资源管理器中双击时无法运行的不相关问题,请参阅此答案.ps1


尝试以下操作,参数逐字传递

Start-Process `
  -FilePath powershell.exe `
  -WorkingDirectory "$env:ALLUSERSPROFILE" `
  -Credential $credential `
  -WindowStyle Hidden `
  -ArgumentList @'
    -NoProfile -Command "Start-Process -FilePath wscript.exe -Verb RunAs -ArgumentList '\"C:\Users\TestAccount\Desktop\cartella  con  spazi\test.vbs\" \"/CurrentDirectory:C:\Users\TestAccount\Desktop\Cartella  con  spazi\" \"/AppData:C:\Users\TestAccount\AppData\Roaming\"'"
'@
  • -Command参数括在其中"..."是为了按原样保留命令内部空间。

  • 命令字符串中的嵌入字符被转义为 "\"

  • 外部-ArgumentList使用here-string来简化嵌入的引用。

    • 此处使用逐字形式 ( @'<newline>...<newline>'@);如果您需要字符串插值(嵌入变量引用和表达式的能力),请使用 _expandable 形式@"<newline>...<newline>"@- 请参阅下一节。
  • 虽然 PowerShell- 在内部使用`反引号作为转义字符,但 PowerShell 的CLI期望"字符在命令行上\进行转义,以符合最广泛使用的转义约定。

    • 跨平台PowerShell (Core) 7+版本现在也接受""作为\"Windows 上另一个常见约定的替代方案。

    • 虽然您可能需要结合两种转义方法,即使用以`\"引用CLI的" 第一个,然后用于 PowerShell 内部使用,但在解释-Command参数的上下文中,在上面的命令中不需要这样做,因为内部-ArgumentList参数使用引号,其中内部"可以按原样使用。


通用解决方案,通过变量提供参数:

假设是要使用其值的变量名为$dir1, $dir2, 和$dir3(并且它们的值没有嵌入的"字符。但"无论如何在 Windows 上的文件系统路径中不支持)。

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参数。

  • 由于变量值被插入到powershell.exe单引号字符串 ( '...') 中,因此嵌入在变量值中的任何'字符都必须转义为'',这就是-replace "'", "''"嵌入$(...) 子表达式中的作用。


可选阅读:对外部程序的调用进行故障排除:

诊断调用外部程序的问题可能很困难,尤其是在这样的嵌套调用中。

准备工作:创建助手可执行文件echoArgsPause.exe

下面创建了一个辅助可执行文件 ,echoArgsPause.exe它回显了调用它的完整命令行,以及它解析命令行的各个参数,然后等待击键。

笔记:

  • 作为基于 .NET 的*.exe,它使用 .NET 的命令行解析规则,而后者又基于Microsoft 的 C/C++ 约定。不幸的是,并非所有可执行文件都保证使用相同的约定。实际上,例如,WSH CLI (cscript.exewscript.exe) 不支持在参数中嵌入 "字符。

  • 从Windows PowerShell运行代码,因为从PowerShell (Core) 7.2开始,不支持通过创建可执行文件。Add-Type

  • 为了以后重用,将生成的.\echoArgsPause.exe文件放在 PATH 中的目录中(在 中列出的目录中$env:PATH)。

  • 要创建不等待击键的变体,请删除Console.Write("Press a key to exit: ");Console.ReadKey(true);行并更改-OutputAssembly .\echoArgsPause.exe为,例如,-OutputAssembly ./echoArgs.exe

Add-Type -OutputType ConsoleApplication -OutputAssembly .\echoArgsPause.exe -TypeDefinition @'
  using System;
  static class ConsoleApp {
    static int Main(string[] args) {
      Console.WriteLine("\nraw: [{0}]\n", 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) 来打印命令行和解析的参数。
# 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:\temp''o  1'
$dir2='c:\temp   2'
$dir3='c:\temp    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 "'", "''")\"'"
"@
于 2021-11-03T21:51:57.617 回答
0

我找到了另一个没有 Here-String 的解决方案:

$username = 'Username'
$password = 'Password'
$securePassword = ConvertTo-SecureString $password -AsPlainText -Force
$credential = New-Object System.Management.Automation.PSCredential $username, $securePassword
Start-Process -FilePath powershell -WorkingDirectory "$env:ALLUSERSPROFILE" -Credential $credential -WindowStyle Hidden -ArgumentList "-NoProfile -Command `"Start-Process -FilePath wscript -Verb RunAs -ArgumentList '\`"$((Get-Location).Path -replace "'", "''")\test.vbs\`" \`"/CurrentDirectory:$((Get-Location).Path -replace "'", "''")\`" \`"/AppData:$($env:APPDATA -replace "'", "''")\`"'`""
于 2021-11-08T17:18:01.293 回答