如何从C#向powershell.exe传递包含a的参数< SPACE>

jucafojl  于 2023-10-18  发布在  Shell
关注(0)|答案(2)|浏览(187)

我想在C#中启动一个进程,导致powershell启动另一个需要参数的程序,如:“M=a B”。我试过各种文字字符串格式,都无济于事。在PowerShell中,以下内容可以正常工作:

  1. Start-Process -FilePath 'C:\MY.exe' -ArgumentList 'A','"M=a b"'

在C#中,以下内容无法正常工作(My.exe抛出:未找到“M=a”。)

  1. string arg = @"Start-Process -FilePath 'C:\MY.exe' -ArgumentList 'A','""M=a b""'";
  2. psTry("powershell.exe",arg)
  3. static void psTry(string file,string arg)
  4. {
  5. Process process = new Process();
  6. process.StartInfo.FileName = file;
  7. process.StartInfo.Arguments = arg;
  8. process.Start();
  9. }

我在PowerShell和C#中尝试了各种“s”和“s”的组合。我试过

  1. arg = @"...".ToString() + @"'""M=a b""'".ToString()
zwghvu4y

zwghvu4y1#

  • @"... '""M=a b""'"替换为@"... '\""M=a b\""'"
  • 这将在 *process命令行 * 上转换为逐字的'\"M=a b\"',这使得PowerShell最终将'"M=a b"'视为Start-Process调用中的-ArgumentList参数之一(如在您成功的会话中调用),其中-由于一个长期存在的错误,不会被修复,请参阅GitHub issue #5576-在MY.exe的进程命令行上作为逐字"M=a b"放置,完整内容如下:
  • "C:\MY.exe" A "M=a b"
  • 因此,在解析其命令行后,MY.exe将看到两个参数,分别具有逐字值AM=a b

也就是说,在C#逐字字符串中,使用\""生成\",这是将"通过 * 逐字 * 传递给最终执行的PowerShell命令所必需的。
powershell.exe,Windows PowerShell CLI,需要"字符。作为命令的一部分保留,作为\"进行转义[1]

  • 未转义 * "字符。假设仅在命令行上具有语法函数 *,因此在将参数(的串联)作为PowerShell代码进行评估之前被 * 删除 *。

完整地说明解决方案:

  1. // Note the `\` before `""`
  2. string arg = @"-NoProfile Start-Process -FilePath 'C:\MY.exe' -ArgumentList 'A', '\""M=a b\""'";
  3. psTry("powershell.exe", arg);
  4. static void psTry(string file, string arg)
  5. {
  6. Process process = new Process();
  7. process.StartInfo.FileName = file;
  8. process.StartInfo.Arguments = arg;
  9. process.Start();
  10. }

退一步
如果唯一的意图是启动另一个带有参数的应用程序,则根本不需要涉及PowerShell CLI(powershell.exe-您可以**直接调用C:\MY.exe *,如下所示。

唯一需要注意的是,你必须设置process.StartInfo.UseShellExecute = true,以模仿Start-Process的默认行为,即**在 * 新窗口 * 中启动应用程序(进程):[2]

  1. // Note how the arguments are passed *inside a single string*,
  2. // with embedded double-quoting.
  3. psTry("C:\MY.exe", @"A ""M=a b""");
  4. void psTry(string file, string args)
  5. {
  6. Process process = new Process();
  7. process.StartInfo.FileName = file;
  8. process.StartInfo.Arguments = args;
  9. process.StartInfo.UseShellExecute = true; // execute in NEW WINDOW
  10. process.Start();
  11. }

如果您的C#应用程序使用的是**.NET Core/ .NET 5+而不是.NET Framework,参数传递甚至可以通过.ArgumentList属性简化/在概念上更清晰**,该属性-作为单字符串.Arguments属性的替代-接受 literal(未加引号)参数数组 *,.NET负责任何所需的引号和/或转义:

  1. // .NET Core / .NET 5+ only:
  2. // Pass the arguments as an *array* of *literal* tokens.
  3. psTry("dep.exe", new [] { "A", "M=a b" });
  4. void psTry(string file, string[] args)
  5. {
  6. Process process = new Process();
  7. process.StartInfo.FileName = file;
  8. foreach (string arg in args)
  9. {
  10. process.StartInfo.ArgumentList.Add(arg);
  11. }
  12. process.StartInfo.UseShellExecute = true;
  13. process.Start();
  14. }

[1]这同样适用于pwsh.exe,PowerShell(核心)CLI;后者可选择地接受"";此外,后者需要将-Command-c)放在命令参数之前,这在Windows PowerShell中是 * 隐含 * 的。
[2]事实上,这正是PowerShell的Start-Process插件在幕后所做的-它只是一个围绕System.Diagnostics.ProcessSystem.Diagnostics.ProcessStartInfo.NET API的PowerShell友好 Package 器。

展开查看全部
gr8qqesn

gr8qqesn2#

实际上,cmd.exe显示了我的代码出错的地方。我不得不为 * powershell.exe * 和 * MY.exe * 分别添加一个 * \,其中*@**使错误不那么明显。感谢有耐心的助手。

相关问题