如何使用Invoke-Command传递命名参数?

我有一个脚本,我可以通过Invoke-Command远程运行

Invoke-Command -ComputerName (Get-Content C:\Scripts\Servers.txt) ` -FilePath C:\Scripts\ArchiveEventLogs\ver5\ArchiveEventLogs.ps1 

只要我使用默认参数,它工作正常。 但是,脚本有2个名为[switch]的参数(-Debug和-Clear)

如何通过Invoke-Command传递参数? 我试过-ArgumentList,但我得到的错误,所以我必须有语法错误或什么的。 任何帮助是极大的赞赏。

-ArgumentList基于使用scriptblock命令,如:

 Invoke-Command -Cn (gc Servers.txt) {param($Debug=$False, $Clear=$False) C:\Scripts\ArchiveEventLogs\ver5\ArchiveEventLogs.ps1 } -ArgumentList $False,$True 

当你用-File调用它的时候,它仍然会传递一个哑数字的参数。 我已经提交了一个function请求 ,添加到命令(请投票)。

所以,你有两个select:

如果你有一个像这样的脚本,在远程机器可以访问的networking位置(请注意, -Debug是隐含的,因为当我使用Parameter属性时,脚本隐含地获取CmdletBinding,因此所有公共参数):

 param( [Parameter(Position=0)] $one , [Parameter(Position=1)] $two , [Parameter()] [Switch]$Clear ) "The test is for '$one' and '$two' ... and we $(if($DebugPreference -ne 'SilentlyContinue'){"will"}else{"won't"}) run in debug mode, and we $(if($Clear){"will"}else{"won't"}) clear the logs after." 

不要挂上$Clear的含义…如果你想调用它,你可以使用下面的Invoke-Command语法之一:

 icm -cn (gc Servers.txt) { param($one,$two,$Debug=$False,$Clear=$False) C:\Scripts\ArchiveEventLogs\ver5\ArchiveEventLogs.ps1 @PSBoundParameters } -ArgumentList "uno", "dos", $false, $true 

在那个中,我复制了所有我关心的scriptblock中的参数,所以我可以传递值。 如果我可以对它们进行硬编码(这就是我的实际做法),那么就没有必要这样做,并使用PSBoundParameters ,我只需将它们传递给我。 在下面的第二个例子中,我将通过$ Clear一个来演示如何传递开关参数:

 icm -cn $Env:ComputerName { param([bool]$Clear) C:\Scripts\ArchiveEventLogs\ver5\ArchiveEventLogs.ps1 "uno" "dos" -Debug -Clear:$Clear } -ArgumentList $(Test-Path $Profile) 

另一种select

如果脚本位于本地计算机上,并且不想将参数更改为位置参数,或者要指定常用参数(因此您无法控制它们)的参数,则需要获取该脚本并将其embedded到您的脚本块中:

 $script = [scriptblock]::create( @" param(`$one,`$two,`$Debug=`$False,`$Clear=`$False) &{ $(Get-Content C:\Scripts\ArchiveEventLogs\ver5\ArchiveEventLogs.ps1 -delimiter ([char]0)) } @PSBoundParameters "@ ) Invoke-Command -Script $script -Args "uno", "dos", $false, $true 

后记:

如果您确实需要为脚本名称传递一个variables,那么您要做什么取决于该variables是在本地还是远程定义的。 一般来说,如果你有一个variables$Script或一个$Env:Script名为$Env:Script的环境variables,你可以使用调用操作符(&)执行它: &$Script&$Env:Script

如果它是一个已经在远程计算机上定义的环境variables,那么就是这样。 如果它是一个局部variables,那么你必须把它传递给远程脚本块:

 Invoke-Command -cn $Env:ComputerName { param([String]$Script, [bool]$Clear) &$Script "uno" "dos" -Debug -Clear:$Clear } -ArgumentList $ScriptPath, $(Test-Path $Profile) 

我的解决scheme是用[scriptblock]:Createdynamic地编写脚本块[scriptblock]:Create

 # Or build a complex local script with MARKERS here, and do substitutions # I was sending install scripts to the remote along with MSI packages # ...for things like Backup and AV protection etc. $p1 = "good stuff"; $p2 = "better stuff"; $p3 = "best stuff"; $etc = "!" $script = [scriptblock]::Create("MyScriptOnRemoteServer.ps1 $p1 $p2 $etc") #strings get interpolated/expanded while a direct scriptblock does not # the $parms are now expanded in the script block itself # ...so just call it: $result = invoke-command $computer -script $script 

通过论证是非常令人沮丧的,尝试各种方法,例如,
-arguments$using:p1等,这只是按照需要工作,没有任何问题。

由于我用这种方法来控制创build[scriptblock] (或脚本文件)的string的内容和variables扩展,因此“invoke-command”咒语没有真正的问题。

(不应该那么辛苦:))

我需要用命名参数来调用脚本。 我们有一个策略,不使用参数的顺序定位,并需要参数名称。

我的方法类似于上面的方法,但获取您要调用的脚本文件的内容,并发送包含参数和值的参数块。

其中一个优点是,您可以selectselect要发送到脚本文件的参数,从而允许使用默认值的非必需参数。

假定在具有以下参数块的临时path中有一个名为“MyScript.ps1”的脚本:

 [CmdletBinding(PositionalBinding = $False)] param ( [Parameter(Mandatory = $True)] [String] $MyNamedParameter1, [Parameter(Mandatory = $True)] [String] $MyNamedParameter2, [Parameter(Mandatory = $False)] [String] $MyNamedParameter3 = "some default value" ) 

这是我如何从另一个脚本调用这个脚本:

 $params = @{ MyNamedParameter1 = $SomeValue MyNamedParameter2 = $SomeOtherValue } If ($SomeCondition) { $params['MyNamedParameter3'] = $YetAnotherValue } $pathToScript = Join-Path -Path $env:Temp -ChildPath MyScript.ps1 $sb = [scriptblock]::create(".{$(Get-Content -Path $pathToScript -Raw)} $(&{ $args } @params)") Invoke-Command -ScriptBlock $sb 

我已经在很多场景中使用过,效果非常好。 你偶尔需要做的一件事就是在参数值分配块周围加引号。 当值中有空格时,情况总是如此。

例如,此参数块用于调用脚本,将各种模块复制到包含空格字符的PowerShell C:\Program Files\WindowsPowerShell\Modules所使用的标准位置。

 $params = @{ SourcePath = "$WorkingDirectory\Modules" DestinationPath = "'$(Join-Path -Path $([System.Environment]::GetFolderPath('ProgramFiles')) -ChildPath 'WindowsPowershell\Modules')'" } 

希望这可以帮助!

我怀疑它的一个新function,因为这个职位是创build – 传递参数的脚本块使用$使用:var。 然后,它提供了一个简单的参数,只要脚本已经在机器上或相对于机器的已知networking位置

以主要的例子为例:

 icm -cn $Env:ComputerName { C:\Scripts\ArchiveEventLogs\ver5\ArchiveEventLogs.ps1 -one "uno" -two "dos" -Debug -Clear $Using:Clear }