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


90

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

如果我在PowerShell外壳中,而不是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>

Answers:


34

本文有帮助。特别是,本节:

-文件

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

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

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


1
这仍然不能满足op的需求(“我要输入xuxu p1 p2 p3 p4”)。
thdoan

19

深入研究PowerShell文档之后,我发现了一些有关此问题的有用信息。$args如果param(...)在文件开头使用,则不能使用;相反,您将需要使用$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执行此操作后,行为会发生变化。
埃里克·汉森

1
@EricHansen我不明白你的意思,我用两种方法都得到相同的结果: $ P4 = VAL4`
兰德尔Borck

@RandallBrock参数的行为对我来说是变化的。如果我处于CMD /批处理中,并且执行类似的操作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
Randall Borck

1
@Timo我不知道您在做什么,但它param是一种语言构造,但是它必须是文件中的第一件事。您是否声明了变量或其他变量?这里更多的信息:docs.microsoft.com/en-us/powershell/module/...
兰德尔Borck

18

好的,因此,这首先破坏了PowerShell中的基本安全功能。了解了这一点之后,您可以执行以下操作:

  1. 打开Windows资源管理器窗口
  2. 菜单工具->文件夹选项->选项卡文件类型
  3. 找到PS1文件类型,然后单击高级按钮
  4. 点击新建按钮
  5. 采取行动:公开
  6. 对于应用程序,请输入:“ C:\ WINNT \ system32 \ WindowsPowerShell \ v1.0 \ powershell.exe”“-文件”“%1”%*

您可能也想-NoProfile在其中添加一个参数,具体取决于您的个人资料的用途。


4
我认为关键在于您将参数传递到powershell.exe的第6步。Daniel说他已经将PS1文件与PowerShell关联了,但是没有额外的%1%*规范就不会传递参数。另请注意,-File参数在V1中不可用。它是V2的新功能。
基思·希尔

关于-file参数,我已经忘记了这一点。
EBGreen

在尝试您的建议之前,我必须先安装V2。谢谢。当您说这破坏了基本的安全功能时,“这个”是什么意思?从Cmd.exe调用PowerShell脚本,就像它是.com / .bat / .exe文件一样?将参数传递给脚本?
丹尼尔“荡”格里菲斯

1
抱歉,我应该更清楚了。无需显式调用powershell.exe即可调用脚本。我并不是说这对您个人来说是一项重要的安全功能,而它却是通过默默无闻提供的安全性,我无论如何都不总是喜欢它。
EBGreen

6
为了增加对EBGreen的评论,PowerShell试图避免的基本安全问题是人们双击附在电子邮件上的PS1文件并运行脚本。这就是默认情况下PS1文件仅与编辑器关联的原因。Microsoft确实不想要PowerShell版本的ILoveYou病毒,例如“ LOVE-LETTER-FOR-YOU.TXT.ps1”
Keith Hill,2009年

11

您可以在文件中声明参数,例如param:

[string]$para1
[string]$param2

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


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用于显示三重引号。那让我停留了一段时间。
DeanOC

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有所了解。


0

如果您想从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/zh-cn/windows-server/administration/windows-commands/ftype


值得注意的是,这需要以管理员身份运行cmd提示符。另外,我正在努力使其真正在Windows 10版本1903(18362.778)上运行-所有命令都成功运行,但是参数仍未传递。我认为用.bat文件包装是最可移植的解决方案。
David Airapetyan
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.