如何将命令行参数传递给 PowerShell ps1 文件

Posted

技术标签:

【中文标题】如何将命令行参数传递给 PowerShell ps1 文件【英文标题】:How to pass command-line arguments to a PowerShell ps1 file 【发布时间】: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>

【问题讨论】:

【参考方案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 中的一项基本安全功能。有了这种理解,您可以这样做:

    打开Windows Explorer 窗口 菜单工具 -> 文件夹选项 -> 选项卡文件类型 找到 PS1 文件类型并点击高级按钮 点击新建按钮 对于行动投入:打开 对于应用程序 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”

以上是关于如何将命令行参数传递给 PowerShell ps1 文件的主要内容,如果未能解决你的问题,请参考以下文章

将文件扩展名作为参数传递给powershell脚本

PowerShell 将命名参数传递给 ArgumentList

将 PowerShell 参数传递给 Process.Start

如何将空参数传递给 msdeploy powershell deploy 命令

如何将命令行参数传递给构建的 Mix Release

如何将命令行参数传递给 WinForms 应用程序?