如何将命令行参数传递给 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 将命名参数传递给 ArgumentList
将 PowerShell 参数传递给 Process.Start