我试图通过传递本地定义的函数来使Invoke-Command
cmdlet使用CredSsp会话。
我有两个本地功能:
MyCopy
只在带有附加开关的传递参数上调用Copy-Item cmdlet MyCopyReturn
与上述相同,但最后还有return
声明现在,当我将这些函数传递给Invoke-Command
而没有-Session
参数时,它们都成功了。
但是,为-Session
指定Invoke-Command
时,MyCopy
会失败并出现以下异常(2.案例):
Cannot bind argument to parameter 'Path' because it is null.
+ CategoryInfo : InvalidData: (:) [Copy-Item], ParameterBindingValidationException
+ FullyQualifiedErrorId : ParameterArgumentValidationErrorNullNotAllowed,Microsoft.PowerShell.Commands.CopyItemCommand
+ PSComputerName : localhost
有人可以解释为什么传递MyCopyReturn
的结果与传递MyCopy
不同?
function MyCopy ($from, $to) {
Copy-Item $from $to -Force -Recurse -Verbose
}
function MyCopyReturn ($from, $to) {
Copy-Item $from $to -Force -Recurse -Verbose
return
}
$credential = Get-Credential
$computerName = 'localhost'
$session = New-PSSession -ComputerName $computerName -Credential $credential -Authentication Credssp
# src is a file
$src = "c:\sandbox\a\test"
# dest is a directory
$dest = "c:\sandbox\b"
# 1.
# MyCopy works fine without giving session
Invoke-Command -ScriptBlock ${function:MyCopy} -ArgumentList $src,$dest
# 2.
# MyCopy DOESN'T WORK when session is given
Invoke-Command -Session $session -ScriptBlock ${function:MyCopy} -ArgumentList $src,$dest
# 4.
# MyCopyReturn works fine without the session
Invoke-Command -ScriptBlock ${function:MyCopyReturn} -ArgumentList $src,$dest
# 3.
# MyCopyReturn works fine with session too
Invoke-Command -Session $session -ScriptBlock ${function:MyCopyReturn} -ArgumentList $src,$dest
Remove-PSSession $session
答案 0 :(得分:1)
我用ILSpy进行了一些挖掘,可以说ScriptBlock.GetPowerShell
方法中的bug存在问题。如果参数不是来自param
块:
function f($Arg){write "`$Arg=`"$Arg`";`$Args=`"$Args`""}
function g{param($Arg) write "`$Arg=`"$Arg`";`$Args=`"$Args`""}
$Function:f.GetPowerShell('Test1','Test2').Invoke()
# $Arg="";$Args="Test1 Test2"
$Function:g.GetPowerShell('Test1','Test2').Invoke()
# $Arg="Test1";$Args="Test2"
如您所见,$Function:f.GetPowerShell('Test1','Test2')
将两个参数绑定到$Args
自动变量,并且没有任何内容绑定到$Arg
。所以当你调用这个命令时
Invoke-Command -Session $session -ScriptBlock ${function:MyCopy} -ArgumentList $src,$dest
$from
和$to
未正确绑定并导致错误。
为什么不使用-Session
参数时不会发生错误?
看起来Invoke-Command
必须将ScriptBlock
转换为PowerShell
以在远程会话中调用命令,而在本地调用ScriptBlock
时则不需要。
为什么MyCopyReturn
不会导致同样的错误?
并非所有ScripBlock
都可以通过GetPowerShell
方法转换为PowerShell(特别是,ScriptBlock
必须有一个语句,另一个语句return
违反此条款) 。如果是这种情况(GetPowerShell
抛出ScriptBlockToPowerShellNotSupportedException
),则Invoke-Command
使用某些备份方案将ScriptBlock
转换为PowerShell
,并且该方案不会受到错误的影响GetPowerShell
方法。