Dus*_*gas 4 powershell invoke-command powershell-jobs
我正在使用Invoke-Command,并且在-ScriptBlock我正在使用的范围内Start-Job。我必须使用$Using:varinside Start-Job,但会话正在本地会话中查找声明的变量(之前声明Invoke-Command)。这是我正在做的事情的一个非常简短的例子:
Invoke-Command -ComputerName $computer -ScriptBlock {
$sourcePath = 'C:\Source'
$destPath = 'C:\dest.zip'
$compressionLevel = [System.IO.Compression.CompressionLevel]::Optimal
$includeBaseDirectory = $false
Start-Job -Name "compress_archive" -ScriptBlock {
Add-Type -AssemblyName System.IO.Compression.FileSystem
[System.IO.Compression.ZipFile]::CreateFromDirectory("$using:sourcePath","$using:destPathTemp",$using:compressionLevel,$using:includeBaseDirectory)
}
}
Invoke-Command : The value of the using variable '$using:sourcePath' cannot be retrieved because it has not been set in the local session.
At line:1 char:1
+ Invoke-Command -ComputerName vode-fbtest -ScriptBlock {
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [Invoke-Command], RuntimeException
+ FullyQualifiedErrorId : UsingVariableIsUndefined,Microsoft.PowerShell.Commands.InvokeCommandCommand
Run Code Online (Sandbox Code Playgroud)
如果我$using在调用变量时省略,Start-Job -ScriptBlock {}那么我会收到Cannot find an overload for "CreateFromDirectory" and the argument count: "4".错误,因为变量未在该范围内定义。
有没有一种方法可以在远程会话中而不是本地会话中使用$using变量,或者我可以指定另一个范围来从远程会话中获取变量?我可以在修复此问题之前在本地声明这些变量,但这需要大量工作,因为变量包含动态值(所有这些都在 a 中,其数据是在远程计算机上检索的,因此我需要如果我无法完成这项工作,请重新构建整个脚本)。Invoke-Commandforeach ($obj in $objects)
-ComputerName我在 Windows Server 2012 R2(源主机和调用命令的主机)上使用 PS v5.1(如果这有什么区别的话)。
看看这个答案,我发现您可以将变量公开给较低级别的脚本块,但我需要实际从远程会话中声明变量。该值需要来自运行远程会话的计算机。您能否以某种方式从远程会话中声明该变量,使其可用于顶级脚本块中的脚本块?
正如之前无数次一样, PetSerAl在对该问题的简短评论中提供了关键的指针:
你需要:
用于创建要从字符串动态[scriptblock]::Create()传递的脚本块Start-Job
在脚本块内进行调用[scriptblock]::Create(),因为只有这样才能确保其中声明的变量 是通过范围说明符在创建的脚本块中引用的变量。Invoke-Command[scriptblock]::Create()$using:
{ ... }和Start-Job,如您的尝试,$using:引用不是指Invoke-Command脚本块的范围,而是指的调用者的范围Invoke-Command,即对使整体Invoke-Command调用。$using:...足够智能,可以处理嵌套范围(如本例所示),但 PowerShell Core 7.0.0-preview.3 的情况并非如此。警告:正如 PetSerAl 指出的那样,如果您使用Invoke-Command命令范围的临时会话(通过使用暗示) - 而不是在with之前创建并传递给with-ComputerName的长期会话-当调用返回时,后台作业将终止,在它(可能)有机会完成之前。虽然您可以通过管道将调用传递给,但只有当您启动多个作业时,这才值得。New-PSSessionInvoke-Command-SessionInvoke-CommandStart-Job... | Receive-Job -Wait -AutoRemove
所以:
Invoke-Command -ComputerName $computer -ScriptBlock {
# Inside this remotely executing script block, define the variables
# that the script block passed to Start-Job below will reference:
$sourcePath = 'C:\Source'
$destPath = 'C:\dest.zip'
$compressionLevel = [System.IO.Compression.CompressionLevel]::Optimal
$includeBaseDirectory = $false
# Define the Start-Job script block as *literal* (here-)*string*, so as
# to defer interpretation of the $using: references, and then
# construct a script block from it using [scriptblock]::Create(), which
# ties the $using: references to *this* scope.
$jobSb = [scriptblock]::Create(
@'
Add-Type -AssemblyName System.IO.Compression.FileSystem
[System.IO.Compression.ZipFile]::CreateFromDirectory("$using:sourcePath","$using:destPathTemp",$using:compressionLevel,$using:includeBaseDirectory)
'@
)
Start-Job -Name "compress_archive" -ScriptBlock $jobSb
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
2318 次 |
| 最近记录: |