首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何使用Invoke-Command传递命名参数?

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

Stack Overflow用户
提问于 2010-11-19 22:08:31
回答 5查看 171.1K关注 0票数 80

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

代码语言:javascript
复制
Invoke-Command -ComputerName (Get-Content C:\Scripts\Servers.txt) `
               -FilePath C:\Scripts\ArchiveEventLogs\ver5\ArchiveEventLogs.ps1

只要我使用默认参数,它就能正常工作。但是,该脚本有两个命名开关参数(-Debug和-Clear)

如何通过Invoke-Command传递切换后的参数?我已经尝试了-ArgumentList,但我得到了错误,所以我一定是语法错误或什么。任何帮助都是非常感谢的。

EN

回答 5

Stack Overflow用户

回答已采纳

发布于 2010-11-19 22:39:39

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

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

当您使用-File调用它时,它仍然像一个哑弹数组一样传递参数。我已经提交了一个feature request,以便将其添加到命令中(请投票支持)。

因此,您有两个选择:

如果您在远程计算机可访问的网络位置中有一个脚本,如下所示(请注意,-Debug是隐含的,因为当我使用Parameter属性时,该脚本隐式获取CmdletBinding,从而获得所有公共参数):

代码语言:javascript
复制
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语法之一:

代码语言:javascript
复制
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,只是为了演示如何传递开关参数:

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

另一种选择

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

代码语言:javascript
复制
$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

PostScript:

如果您确实需要为脚本名传入一个变量,那么您应该做什么将取决于该变量是本地定义的还是远程定义的。通常,如果您有一个带有脚本名的变量$Script或环境变量$Env:Script,则可以使用调用运算符(&)执行它:&$Script&$Env:Script

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

代码语言:javascript
复制
Invoke-Command -cn $Env:ComputerName { 
    param([String]$Script, [bool]$Clear)
    & $ScriptPath "uno" "dos" -Debug -Clear:$Clear
} -ArgumentList $ScriptPath, (Test-Path $Profile)
票数 99
EN

Stack Overflow用户

发布于 2016-05-24 04:01:54

我的解决方案是使用[scriptblock]:Create动态编写脚本块

代码语言:javascript
复制
# 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] (或脚本文件)的字符串的内容和变量扩展,因此“调用命令”咒语没有什么真正的问题。

(这不应该那么难。:)

票数 7
EN

Stack Overflow用户

发布于 2017-04-20 17:02:17

我怀疑这是一个新特性,因为这篇文章是创建的--使用$Using:var向脚本块传递参数。如果脚本已经在计算机上或位于与计算机相关的已知网络位置,那么传递参数就很简单了

以主要的例子为例:

代码语言:javascript
复制
icm -cn $Env:ComputerName { 
    C:\Scripts\ArchiveEventLogs\ver5\ArchiveEventLogs.ps1 -one "uno" -two "dos" -Debug -Clear $Using:Clear
}
票数 5
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/4225748

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档