【问题标题】:How to pass command-line arguments to a PowerShell ps1 file如何将命令行参数传递给 PowerShell ps1 文件
【发布时间】:2010-11-20 14:28:54
【问题描述】:

多年来,我一直使用cmd/DOS/Windows shell 并将命令行参数传递给批处理文件。例如,我有一个文件zuzu.bat,在其中访问%1%2 等。现在,当我调用PowerShell 脚本when I am in a Cmd.exe shell 时,我想做同样的事情。我有一个脚本xuxu.ps1(并且我已将 PS1 添加到我的 PATHEXT 变量中,并使用 PowerShell 关联 PS1 文件)。但无论我做什么,我似乎都无法从$args 变量中得到任何东西。它的长度始终为 0。

如果我在PowerShell shell 中,而不是cmd.exe,它可以工作(当然)。但我还不够舒服,无法全职生活在 PowerShell 环境中。我不想输入powershell.exe -command xuxu.ps1 p1 p2 p3 p4。我想输入xuxu p1 p2 p3 p4

这可能吗?如果可以,怎么做?

我无法工作的样本是微不足道的,foo.ps1:

Write-Host "Num Args:" $args.Length;
foreach ($arg in $args) {
    Write-Host "Arg: $arg";
}

结果总是这样:

C:\temp> foo
Num Args: 0
C:\temp> foo a b c d
Num Args: 0
c:\temp>

【问题讨论】:

    标签: command-line powershell arguments


    【解决方案1】:

    您可能不会像看起来那样得到“xuxu p1 p2 p3 p4”。但是当你在 PowerShell 中并且你设置了

    PS > Set-ExecutionPolicy Unrestricted -Scope CurrentUser
    

    您可以像这样运行这些脚本:

    ./xuxu p1 p2 p3 p4
    

    .\xuxu p1 p2 p3 p4
    

    ./xuxu.ps1 p1 p2 p3 p4
    

    我希望这能让您更熟悉 PowerShell。

    【讨论】:

      【解决方案2】:

      如果你想从 cmd 调用 ps1 脚本并传递参数而不像调用脚本一样

      powershell.exe script.ps1 -c test
      script -c test ( wont work )
      

      您可以执行以下操作

      setx PATHEXT "%PATHEXT%;.PS1;" /m
      assoc .ps1=Microsoft.PowerShellScript.1
      ftype Microsoft.PowerShellScript.1=powershell.exe "%1" %*
      

      这是假设 powershell.exe 在你的路径中

      https://docs.microsoft.com/en-us/windows-server/administration/windows-commands/ftype

      【讨论】:

      • 值得注意的是,这需要以管理员身份运行 cmd 提示符。此外,我正在努力让它在 Windows 10 版本 1903 (18362.778) 上运行 - 所有命令都成功运行,但参数仍然没有传入。我认为用 .bat 文件包装是最便携的解决方案。跨度>
      【解决方案3】:

      你可以在文件中声明你的参数,比如 param:

      [string]$para1
      [string]$param2
      

      然后像.\temp.ps1 para1 para2....para10等那样调用PowerShell文件

      【讨论】:

        【解决方案4】:

        This article 有帮助。特别是本节:

        -文件

        在本地范围(“dot-sourced”)中运行指定的脚本,以便脚本创建的函数和变量在当前会话中可用。输入脚本文件路径和任何参数。 File 必须是命令中的最后一个参数,因为在 File 参数名称之后键入的所有字符都被解释为脚本文件路径,后跟脚本参数。

        powershell.exe -File "C:\myfile.ps1" arg1 arg2 arg3
        

        表示运行文件 myfile.ps1 和 arg1 arg2 & arg3 是 PowerShell 脚本的参数。

        【讨论】:

        • 这仍然无助于操作员想要什么(“我想输入xuxu p1 p2 p3 p4”)。
        【解决方案5】:

        在深入研究 PowerShell 文档后,我发现了一些关于此问题的有用信息。如果您在文件开头使用了param(...),则不能使用$args;相反,您需要使用$PSBoundParameters。我将您的代码复制/粘贴到一个 PowerShell 脚本中,它在 PowerShell 版本 2 中可以正常工作(我不确定您遇到此问题时使用的是哪个版本)。

        如果你使用$PSBoundParameters(只有在脚本开头使用param(...)时才有效),那么它不是一个数组,它是一个哈希表,所以你需要引用它使用键/值对。

        param($p1, $p2, $p3, $p4)
        $Script:args=""
        write-host "Num Args: " $PSBoundParameters.Keys.Count
        foreach ($key in $PSBoundParameters.keys) {
            $Script:args+= "`$$key=" + $PSBoundParameters["$key"] + "  "
        }
        write-host $Script:args
        

        当被调用时...

        PS> ./foo.ps1 a b c d
        

        结果是……

        Num Args:  4
        $p1=a  $p2=b  $p3=c  $p4=d
        

        【讨论】:

        • 这并没有说明 OP 使用 powershell.exe 或 pwsh 启动他的命令行。当 OP 这样做时,行为会发生变化。
        • @EricHansen 我不明白你的意思,无论哪种方式我都得到相同的结果:` Powershell>powershell.exe .\ParamTest.ps1 val1 val2 val3 val4 Num Args: 4 $p1=val1 $p2=val2 $p3=val3 $p4=val4 `
        • @RandallBrock 参数的行为改变了我。如果我在 CMD/batch 中,并且我执行 pwsh .\ParamTest.ps1 -arg1 val1 -listOfArgs val2 val3 val4 之类的操作,它真的不喜欢那样。另一方面,如果我在 PowerShell 中并执行 .\ParamTest.ps1 -arg1 val1 -listOfArgs val2 val3 val4,那么它就像我期望的那样工作。我听说这是出于“安全原因”的原因。
        • @EricHansen 我想知道这是否是版本问题。对我来说,pwsh 启动 6.2.0,但 powershell.exe 启动 5.1.17134.858,两者产生的结果相同:Powershell>pwsh .\ParamTest.ps1 val1 val2 val3 val4 产生:Num Args: 4 $p1=val1 $p2=val2 $p3=val3 $p4=val4
        • @Timo 我不知道你到底在做什么,但param 是一种语言结构,但它必须是文件中的第一件事。您是否在它之前声明了一个变量或其他东西?更多信息:docs.microsoft.com/en-us/powershell/module/…
        【解决方案6】:

        也许您可以将 PowerShell 调用包装在 .bat 文件中,如下所示:

        rem ps.bat
        @echo off
        powershell.exe -command "%*"
        

        如果您随后将此文件放在 PATH 中的文件夹下,您可以像这样调用 PowerShell 脚本:

        ps foo 1 2 3
        

        不过,引用可能会有些混乱:

        ps write-host """hello from cmd!""" -foregroundcolor green
        

        【讨论】:

        • +1 用于显示三引号。这让我停留了一段时间。
        【解决方案7】:

        好的,首先这是破坏 PowerShell 中的一项基本安全功能。有了这种理解,您可以这样做:

        1. 打开Windows Explorer 窗口
        2. 菜单工具 -> 文件夹选项 -> 选项卡文件类型
        3. 找到 PS1 文件类型并点击高级按钮
        4. 点击新建按钮
        5. 对于行动投入:打开
        6. 对于应用程序 put:"C:\WINNT\system32\WindowsPowerShell\v1.0\powershell.exe" "-file" "%1" %*

        根据您的个人资料的用途,您可能还想在其中添加 -NoProfile 参数。

        【讨论】:

        • 我认为关键在于您将参数传递给 powershell.exe 的第 6 步。 Daniel 说他已将 PS1 文件与 PowerShell 相关联,但如果没有额外的 %1 %* 规范,则不会传递参数。另请注意,-File 参数在 V1 中不可用。它是 V2 的新功能。
        • 关于 -file 参数的好消息,我忘记了。
        • 我必须先安装 V2,然后才能尝试您的建议。谢谢。当您说这破坏了基本安全功能时,“这个”是什么意思?从 Cmd.exe 调用 PowerShell 脚本,就好像它是 .com/.bat/.exe 文件一样?向脚本传递参数?
        • 对不起,我应该更清楚。调用脚本而不显式调用 powershell.exe。我并不是说它对您个人来说是一项重要的安全功能,而是通过默默无闻的安全性,无论如何我并不总是喜欢它。
        • 添加到 EBGreen 的评论中,PowerShell 试图避免的基本安全问题是人们双击附加到电子邮件的 PS1 文件并运行脚本。这就是为什么 PS1 文件默认仅与编辑器关联的原因。 Microsoft 真的不想要 ILoveYou 病毒的 PowerShell 版本,例如“给你的情书.TXT.ps1”
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-03-23
        • 2021-05-03
        • 2016-07-20
        • 1970-01-01
        • 2018-09-16
        • 2013-06-15
        相关资源
        最近更新 更多