为了账号安全,请及时绑定邮箱和手机立即绑定

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

/ 猿问

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

烧仙草VB 2019-12-26 10:18:23

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


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

               -FilePath C:\Scripts\ArchiveEventLogs\ver5\ArchiveEventLogs.ps1

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


如何通过调用命令传递已切换的参数?我已经尝试过-ArgumentList,但是出现错误,因此我必须使用错误的语法或其他内容。任何帮助是极大的赞赏。


查看完整描述

3 回答

?
千万里不及你

-ArgumentList基于与脚本块命令一起使用,例如:


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

当您使用a调用它时,-File它仍会像哑哑数组那样传递参数。我已经提交了功能请求,以将其添加到命令中(请对此进行投票)。


因此,您有两个选择:


如果您有一个看起来像这样的脚本,那么该脚本位于远程机器可以访问的网络位置(请注意,这-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

在那篇文章中,我将在脚本块中复制我关心的所有参数,以便可以传递值。如果我可以对它们进行硬编码(这是我实际上所做的),则无需这样做并使用PSBoundParameters,我只需传递所需的内容即可。在下面的第二个示例中,我将传递$ Clear,只是为了演示如何传递开关参数:


icm -cn $Env:ComputerName { 

    param([bool]$Clear)

    C:\Scripts\ArchiveEventLogs\ver5\ArchiveEventLogs.ps1 "uno" "dos" -Debug -Clear:$Clear

} -ArgumentList $(Test-Path $Profile)

另一种选择

如果脚本在您的本地计算机上,并且您不想将参数更改为位置参数,或者您想指定作为通用参数的参数(因此您无法控制它们),则需要获取以下内容:该脚本并将其嵌入到您的scriptblock中:


$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

后记:

如果您确实需要为脚本名称传递一个变量,那么您将执行的操作将取决于该变量是在本地还是远程定义的。在一般情况下,如果你有一个变量$Script或环境变量$Env:Script与脚本的名称,就可以与呼叫运营商()执行它:&$Script或&$Env:Script


如果它是已经在远程计算机上定义的环境变量,则仅此而已。如果它是局部变量,则必须将其传递给远程脚本块:


Invoke-Command -cn $Env:ComputerName { 

    param([String]$Script, [bool]$Clear)

    &$Script "uno" "dos" -Debug -Clear:$Clear

} -ArgumentList $ScriptPath, $(Test-Path $Profile)


查看完整回答
反对 回复 2019-12-26
?
当年话下

我的解决方案是使用[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等,如没有问题,期望这只是工作。


由于我控制以[scriptblock]这种方式创建(或脚本文件)的字符串的内容和变量扩展,因此“ invoke-command”命令没有真正的问题。


(不应该那么难。:))


查看完整回答
反对 回复 2019-12-26
?
料青山看我应如是

我怀疑这是自创建该帖子以来的一项新功能-使用$ Using:var将参数传递到脚本块。然后,如果脚本已在计算机上或相对于计算机的已知网络位置中,则传递参数很简单


以主要示例为例:


icm -cn $Env:ComputerName { 

    C:\Scripts\ArchiveEventLogs\ver5\ArchiveEventLogs.ps1 -one "uno" -two "dos" -Debug -Clear $Using:Clear

}


查看完整回答
反对 回复 2019-12-26

添加回答

回复

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信