PowerShell 在 Invoke-Command 上展开参数列表
PowerShell Splatting the Argumentlist on Invoke-Command
如何使用散列 table 中收集的参数与 Invoke-Command
上的 ArgumentList
一起使用?
$CopyParams = @{
Source = 'E:\DEPARTMENTS\CBR\SHARE\Target'
Destination = 'E:\DEPARTMENTS\CBR\SHARE\Target 2'
Structure = 'yyyy-MM-dd'
}
Invoke-Command -Credential $Cred -ComputerName 'SERVER' -ScriptBlock ${Function:Copy-FilesHC} -ArgumentList @CopyParams
无论我尝试什么,它总是抱怨 'Source':
Cannot validate argument on parameter 'Source'. The "Test-Path $_" validation script for the argument with
value "System.Collections.Hashtable" did not return true. Determine why the validation script failed
这个 blog 谈到了类似的问题,但我无法让它工作。
Invoke-Command
内的简单Copy-Item
也是如此,例子:
Invoke-Command -Credential $Cred -ComputerName 'SERVER' -ScriptBlock {Copy-Item} -ArgumentList @CopyParams
Invoke-Command : Missing an argument for parameter 'ArgumentList'. Specify a parameter of type 'System.Obj
ect[]' and try again.
At line:11 char:89
+ ... ck {Copy-Item} -ArgumentList @CopyParams
感谢您的帮助。
这是一种传递命名参数的方法:
function Copy-FilesHC
{
param ($Source,$Destination,$Structure)
"Source is $Source"
"Desintation is $Destination"
"Structure is $Structure"
}
$CopyParams = @{
Source = 'E:\DEPARTMENTS\CBR\SHARE\Target'
Destination = "'E:\DEPARTMENTS\CBR\SHARE\Target 2'" #Nested quotes required due to embedded space in value.
Structure = 'yyyy-MM-dd'
}
$SB = [scriptblock]::Create(".{${Function:Copy-FilesHC}} $(&{$args}@CopyParams)")
Invoke-Command -Credential $Cred -ComputerName 'SERVER' -ScriptBlock $SB
基本上,您从调用的脚本中创建一个新的脚本块,并将参数从散列 table 中分离出来。脚本块中的所有内容都已展开,因此没有要传递的参数列表。
我找到了解决方法,但您必须确保模块文件中的 Advanced function
已在本地会话中预先加载。所以它可以在远程会话中使用。我为此写了一个小辅助函数。
Function Add-FunctionHC {
[CmdletBinding(SupportsShouldProcess=$True)]
Param(
[String]$Name
)
Process {
Try {
$Module = (Get-Command $Name -EA Stop).ModuleName
}
Catch {
Write-Error "Add-FunctionHC: Function '$Name' doesn't exist in any module"
$Global:Error.RemoveAt('1')
Break
}
if (-not (Get-Module -Name $Module)) {
Import-Module -Name $Module
}
}
}
# Load funtion for remoting
Add-FunctionHC -Name 'Copy-FilesHC'
$CopyParams = @{
Source = 'E:\DEPARTMENTS\CBR\SHARE\Target\De file.txt'
Destination = 'E:\DEPARTMENTS\CBR\SHARE\Target 2'
}
$RemoteFunctions = "function Copy-FilesHC {${function:Copy-FilesHC}}" #';' seperated to add more
Invoke-Command -ArgumentList $RemoteFunctions -ComputerName 'SERVER' -Credential $Cred -ScriptBlock {
Param (
$RemoteFunctions
)
. ([ScriptBlock]::Create($RemoteFunctions))
$CopyParams = $using:CopyParams
Copy-FilesHC @CopyParams
}
最大的好处是你不需要在脚本中复制你的完整函数,它可以留在模块中。因此,当您将模块中的某些内容更改为函数时,它也将在远程会话中可用,而无需更新您的脚本。
我知道这已经晚了,但我 运行 遇到了同样的问题并找到了适合我的解决方案。将它分配给脚本块中的一个变量,然后使用该变量进行 splat 没有显示任何问题。
这是一个例子:
$param=@{"parameter","value"}
invoke-command -asjob -session $session -ScriptBlock {$a=$args[0];cmdlet @a } -ArgumentList $param
一行代码,将远程脚本转换为接受来自哈希的命名参数。
给定一个您希望这样调用的脚本块:
$Options = @{
Parameter1 = "foo"
Parameter2 = "bar"
}
Invoke-Command -ComputerName REMOTESERVER -ArgumentList $Options -ScriptBlock {
param(
$Parameter1,
$Parameter2
)
#Script goes here, this is just a sample
"ComputerName: $ENV:COMPUTERNAME"
"Parameter1: $Parameter1"
"Parameter2: $Parameter2"
}
你可以像这样转换它
Invoke-Command -Computername REMOTESERVER -ArgumentList $Options -ScriptBlock {param($Options)&{
param(
$Parameter1,
$Parameter2
)
#Script goes here, this is just a sample
"ComputerName: $ENV:COMPUTERNAME"
"Parameter1: $Parameter1"
"Parameter2: $Parameter2"
} @Options}
这是怎么回事?本质上我们已经像这样包装了原始脚本块:
{param($Options)& <# Original script block (including {} braces)#> @options }
这使得原始脚本块成为一个匿名函数,并创建了一个带有参数$Options
的外部脚本块,它除了调用内部脚本块之外什么都不做,传递@options
来splat散列。
我最近遇到了类似的问题,并通过利用 $using 变量作用域在调用中构建散列(或重建散列)解决了这个问题(更多关于 here)
看起来像这样:
$Source = 'E:\DEPARTMENTS\CBR\SHARE\Target'
$Destination = 'E:\DEPARTMENTS\CBR\SHARE\Target 2'
$Structure = 'yyyy-MM-dd'
Invoke-Command -Credential $Cred -ComputerName 'SERVER' -ScriptBlock {
$CopyParms= @{
'Source'=$Using:Source
'Destination'=$Using:Destination
'Structure'=$Using:Structure
}
Function:Copy-FilesHC @CopyParms
}
这对我有用:
$hash = @{
PARAM1="meaning of life"
PARAM2=42
PARAM3=$true
}
$params = foreach($x in $hash.GetEnumerator()) {"$($x.Name)=""$($x.Value)"""}
如何使用散列 table 中收集的参数与 Invoke-Command
上的 ArgumentList
一起使用?
$CopyParams = @{
Source = 'E:\DEPARTMENTS\CBR\SHARE\Target'
Destination = 'E:\DEPARTMENTS\CBR\SHARE\Target 2'
Structure = 'yyyy-MM-dd'
}
Invoke-Command -Credential $Cred -ComputerName 'SERVER' -ScriptBlock ${Function:Copy-FilesHC} -ArgumentList @CopyParams
无论我尝试什么,它总是抱怨 'Source':
Cannot validate argument on parameter 'Source'. The "Test-Path $_" validation script for the argument with
value "System.Collections.Hashtable" did not return true. Determine why the validation script failed
这个 blog 谈到了类似的问题,但我无法让它工作。
Invoke-Command
内的简单Copy-Item
也是如此,例子:
Invoke-Command -Credential $Cred -ComputerName 'SERVER' -ScriptBlock {Copy-Item} -ArgumentList @CopyParams
Invoke-Command : Missing an argument for parameter 'ArgumentList'. Specify a parameter of type 'System.Obj
ect[]' and try again.
At line:11 char:89
+ ... ck {Copy-Item} -ArgumentList @CopyParams
感谢您的帮助。
这是一种传递命名参数的方法:
function Copy-FilesHC
{
param ($Source,$Destination,$Structure)
"Source is $Source"
"Desintation is $Destination"
"Structure is $Structure"
}
$CopyParams = @{
Source = 'E:\DEPARTMENTS\CBR\SHARE\Target'
Destination = "'E:\DEPARTMENTS\CBR\SHARE\Target 2'" #Nested quotes required due to embedded space in value.
Structure = 'yyyy-MM-dd'
}
$SB = [scriptblock]::Create(".{${Function:Copy-FilesHC}} $(&{$args}@CopyParams)")
Invoke-Command -Credential $Cred -ComputerName 'SERVER' -ScriptBlock $SB
基本上,您从调用的脚本中创建一个新的脚本块,并将参数从散列 table 中分离出来。脚本块中的所有内容都已展开,因此没有要传递的参数列表。
我找到了解决方法,但您必须确保模块文件中的 Advanced function
已在本地会话中预先加载。所以它可以在远程会话中使用。我为此写了一个小辅助函数。
Function Add-FunctionHC {
[CmdletBinding(SupportsShouldProcess=$True)]
Param(
[String]$Name
)
Process {
Try {
$Module = (Get-Command $Name -EA Stop).ModuleName
}
Catch {
Write-Error "Add-FunctionHC: Function '$Name' doesn't exist in any module"
$Global:Error.RemoveAt('1')
Break
}
if (-not (Get-Module -Name $Module)) {
Import-Module -Name $Module
}
}
}
# Load funtion for remoting
Add-FunctionHC -Name 'Copy-FilesHC'
$CopyParams = @{
Source = 'E:\DEPARTMENTS\CBR\SHARE\Target\De file.txt'
Destination = 'E:\DEPARTMENTS\CBR\SHARE\Target 2'
}
$RemoteFunctions = "function Copy-FilesHC {${function:Copy-FilesHC}}" #';' seperated to add more
Invoke-Command -ArgumentList $RemoteFunctions -ComputerName 'SERVER' -Credential $Cred -ScriptBlock {
Param (
$RemoteFunctions
)
. ([ScriptBlock]::Create($RemoteFunctions))
$CopyParams = $using:CopyParams
Copy-FilesHC @CopyParams
}
最大的好处是你不需要在脚本中复制你的完整函数,它可以留在模块中。因此,当您将模块中的某些内容更改为函数时,它也将在远程会话中可用,而无需更新您的脚本。
我知道这已经晚了,但我 运行 遇到了同样的问题并找到了适合我的解决方案。将它分配给脚本块中的一个变量,然后使用该变量进行 splat 没有显示任何问题。
这是一个例子:
$param=@{"parameter","value"}
invoke-command -asjob -session $session -ScriptBlock {$a=$args[0];cmdlet @a } -ArgumentList $param
一行代码,将远程脚本转换为接受来自哈希的命名参数。
给定一个您希望这样调用的脚本块:
$Options = @{
Parameter1 = "foo"
Parameter2 = "bar"
}
Invoke-Command -ComputerName REMOTESERVER -ArgumentList $Options -ScriptBlock {
param(
$Parameter1,
$Parameter2
)
#Script goes here, this is just a sample
"ComputerName: $ENV:COMPUTERNAME"
"Parameter1: $Parameter1"
"Parameter2: $Parameter2"
}
你可以像这样转换它
Invoke-Command -Computername REMOTESERVER -ArgumentList $Options -ScriptBlock {param($Options)&{
param(
$Parameter1,
$Parameter2
)
#Script goes here, this is just a sample
"ComputerName: $ENV:COMPUTERNAME"
"Parameter1: $Parameter1"
"Parameter2: $Parameter2"
} @Options}
这是怎么回事?本质上我们已经像这样包装了原始脚本块:
{param($Options)& <# Original script block (including {} braces)#> @options }
这使得原始脚本块成为一个匿名函数,并创建了一个带有参数$Options
的外部脚本块,它除了调用内部脚本块之外什么都不做,传递@options
来splat散列。
我最近遇到了类似的问题,并通过利用 $using 变量作用域在调用中构建散列(或重建散列)解决了这个问题(更多关于 here)
看起来像这样:
$Source = 'E:\DEPARTMENTS\CBR\SHARE\Target'
$Destination = 'E:\DEPARTMENTS\CBR\SHARE\Target 2'
$Structure = 'yyyy-MM-dd'
Invoke-Command -Credential $Cred -ComputerName 'SERVER' -ScriptBlock {
$CopyParms= @{
'Source'=$Using:Source
'Destination'=$Using:Destination
'Structure'=$Using:Structure
}
Function:Copy-FilesHC @CopyParms
}
这对我有用:
$hash = @{
PARAM1="meaning of life"
PARAM2=42
PARAM3=$true
}
$params = foreach($x in $hash.GetEnumerator()) {"$($x.Name)=""$($x.Value)"""}