【问题标题】:Running executable with command line parameters in PowerShell在 PowerShell 中使用命令行参数运行可执行文件
【发布时间】:2019-09-27 21:05:07
【问题描述】:

这必须是可能的。我可以在 Windows 中打开命令提示符并执行以下操作:

<some exe> <some exe command line parameters>

在 PowerShell 甚至标准的 Windows 批处理文件中必须有等效的方法来执行此操作。例如,在 windows 命令提示符下,我可以使用以下命令启动 docker 容器:

docker run –-net=kafka -d –-name=zookeeper -e ZOOKEEPER_CLIENT_PORT=2181 confluentinc/cp-zookeeper:4.1.0

但是,如果我用 PowerShell 尝试这样的事情

& "docker" run –-net=kafka -d –-name=zookeeper -e ZOOKEEPER_CLIENT_PORT=2181 confluentinc/cp-zookeeper:4.1.0

失败并出现一般错误:

invalid reference format.

也许 PowerShell 不适合这种类型的高级用例。任何建议将不胜感激!

对于这样的高级用法,有更好的脚本语言吗?

【问题讨论】:

  • 顺便说一句:这绝对不是一个高级用例:使用参数调用控制台应用程序是任何 shell 的核心功能,包括 PowerShell。

标签: powershell command execute


【解决方案1】:

powershell 转义有很多复杂性。我编写了这个模块来帮助运行外部命令:

https://github.com/choovick/ps-invoke-externalcommand

演示: https://terminalizer.com/view/49acb54a979

Install-Module -Name ExternalCommand -Scope CurrentUser
Invoke-ExternalCommand -Command "docker" -Arguments @("run","-d","--name=zookeeper","--net=kafka","-e","ZOOKEEPER_CLIENT_PORT=2181", "confluentinc/cp-zookeeper:4.1.0")

【讨论】:

    【解决方案2】:

    总的来说,PowerShell 中的外部程序的调用方式与 cmd.exe 中的调用方式相同 - 存在差异,因为 PowerShell 具有额外的元字符,例如 $@,但它们在你的具体情况。 (您的 &amp; "docker" ... 变体原则上也可以使用,但只有在必须使用 quoted基于变量 命令名称或路径时才需要使用 &amp; )。

    问题在于您的原始命令行包含两个 (EN DASH, U+2013) 实例,而不是预期的 ASCII 范围 - 破折号(连字符),而 docker 没有不认识。

    快速发现问题的方法:

    # Print the code points of characters outside the ASCII range.
    PS> [int[]] [char[]] '& "docker" run –-net=kafka -d –-name=zookeeper -e ZOOKEEPER_CLIENT_PORT=2181 confluentinc/cp-zookeeper:4.1.0' -gt 127
    8211
    8211
    

    十进制 8211 是十六进制。 0x2013,en-dash的代码点,而常规-的代码点是450x2d)。

    只需用- 替换这些 实例(并且,由于不需要引用docker,因此不需要&amp;):

    docker run --net=kafka -d --name=zookeeper -e ZOOKEEPER_CLIENT_PORT=2181 confluentinc/cp-zookeeper:4.1.0
    

    Your own answer 显示了命令的基于变量的实现,它实际上与上面的命令相同 - 如果事先知道所有参数,则永远不需要 /em> 使用变量。

    如果您确实想使用变量,则对所有参数使用单个数组变量并传递它要简单得多:

    $dockerExe =  'docker'
    $dockerArgs = 'run',
                  '--net=kafka',
                  '-d',
                  '--name=zookeeper',
                  '-e',
                  'ZOOKEEPER_CLIENT_PORT=2181',
                  'confluentinc/cp-zookeeper:4.1.0'
    
    & $dockerExe $dockerArgs
    

    注意:

    • 必须始终单独指定可执行文件名称/路径,如果它被引用或涉及变量引用(如本例所示),&amp; ,出于语法原因,call operator 必须用于调用。

    • 以这种方式将参数作为数组传递适用于外部程序;对于 PowerShell 命令,您将创建一个 hashtable 变量,并使用 sigil @ 而不是 $(称为 splatting 的功能)传递该变量。

    【讨论】:

      【解决方案3】:

      我认为 Start-Process cmdlet 会很有用。 ArgumentList 可以是单引号或双引号。

      Start-Process docker -ArgumentList "run –-net=kafka -d –-name=zookeeper -e ZOOKEEPER_CLIENT_PORT=2181 confluentinc/cp-zookeeper:4.1.0"

      【讨论】:

      • 这并不能解决命令行包含 em-dashes 而不是连字符的真正问题,但即使解决了,它也会从根本上改变调用的行为:默认情况下,Start-Process创建一个新窗口并以异步方式运行 - 它只是用于正常同步调用控制台应用程序(例如 docker)的错误工具。
      【解决方案4】:

      这里是如何做到这一点。

      $app = 'docker'
      
      $a1 = 'run'
      
      $a2 = '--net=kafka'
      
      $a3 = '-d'
      
      $a4 = '--name=zookeeper'
      
      $a5 = '-e'
      
      $a6 = 'ZOOKEEPER_CLIENT_PORT=2181'
      
      $a7 = 'confluentinc/cp-zookeeper:4.1.0'
      
      & $app $a1 $a2 $a3 $a4 $a5 $a6 $a7
      

      【讨论】:

      • 这与docker run --net=kafka -d --name=zookeeper -e ZOOKEEPER_CLIENT_PORT=2181 confluentinc/cp-zookeeper:4.1.0 没有什么不同。如果您确实需要通过变量提供参数,请声明一个 array ($a = 'run', '--net=kafka', ...) 并传递它 (docker $a)。
      • 上面接受的答案演示了如何在 powershell 中运行带有参数的命令。
      • 没错,您的回答演示了在 PowerShell 中运行带有参数的命令的 一种 方法,但这是一种不必要的复杂方法,因此是不明智的方法 - 它实际上是相同的作为我的第一条评论中显示的正常直接调用,因此它不能解决问题中提出的问题。
      • 它绝对是一个解决方案,因为第一条评论中的那个不起作用,而这个起作用。 :-)
      • 它是一个解决方案的唯一原因是因为您重新输入您的论点,从而碰巧消除了问题的真正根源:您原来的命令行不小心使用了 2 个 EN DASH 字符而不是常规破折号(连字符) - 请参阅我的答案。你的调用风格是不明智的,与真正的解决方案无关。
      猜你喜欢
      • 1970-01-01
      • 2021-12-21
      • 2020-01-12
      • 2014-09-30
      • 2014-10-25
      • 1970-01-01
      • 2020-09-13
      • 1970-01-01
      相关资源
      最近更新 更多