如何在变量中存储 powershell 作业信息
How to store powershell job information in a variable
我目前有一个 powershell (v2) 脚本,它获取主机 PC 列表,远程检查一些 files/software 是否在它们应该在的位置,并在完成后通过电子邮件发送一串结果。但是,当尝试在 100 多个房间中一次一个地依次执行此操作时,脚本需要相当长的时间才能完成。
为了加快速度,我一直在尝试通过使用作业报告每个主机名来使脚本成为多线程。为了清楚起见,我将代码的主要部分放在下面,并删除了一些较大的不相关部分。
$pcHostNames = Get-Content "$scriptPath\HostNames.txt"
$scriptBlock = {
Param(pcHostName)
$softwareInstalled = $false
# Test to see if host can be reached
If (Test-Connection -ComputerName $pcHostName -Quiet)
{
# Multiple lines of code to check if different files/software are installed on each remote PC
# If they are installed, set $softwareInstalled to true
if (-not $softwareInstalled)
{
$reportList += "$pcHostName`: Not installed`n"
}
else
{
$reportList += "$pcHostName`: Fully installed`n"
}
}
else
{
$reportList += "$pcHostName`: Error - Connection failed`n"
}
} # End - $scriptBlock
$pcHostNames | % { Start-Job -Scriptblock $scriptBlock -ArgumentList $_ } | Get-Job | Wait-Job | Receive-Job
目前,该脚本对 PC 执行 ping 命令,然后检查是否安装了各种 files/software,并将一个字符串添加到 $reportList,然后在电子邮件中使用该字符串在我的代码的另一部分发送报告。
由于 $reportList 超出了每个作业的范围,我得到的只是脚本末尾的空白电子邮件。由于无法从作业中将字符串值添加到变量,有没有办法将我的作业管道代码编辑为 return 一个字符串值,然后我可以将其添加到变量?
我认为这个问题可能与我的代码的最后一行有关,所以我尝试了几种不同的执行作业变体,但我在网上找到的东西并没有太多运气。
或者,是否有更好的方法通过其他方法多线程处理此脚本?
变量存在于它们被创建的范围内。
当您在作业中声明变量时,它们仅存在于该作业的范围内。
如果您想将详细信息从子作业传回给调用者,您需要使用 Write-Output。然后使用Get-Job监控作业的状态,直到完成,然后使用Receive-Job获取输出。
start-job {write-output "hello world"}
get-job | receive job
编辑:
以您的示例代码块为例,下面使用 write-output 从作业中获取 return 结果,过滤成功完成的作业,接收作业的输出并将它们存储在$reportList 变量
$pcHostNames = Get-Content "$scriptPath\HostNames.txt"
$scriptBlock = {
Param(pcHostName)
$softwareInstalled = $false
# Test to see if host can be reached
If (Test-Connection -ComputerName $pcHostName -Quiet)
{
# Multiple lines of code to check if different files/software are installed on each remote PC
# If they are installed, set $softwareInstalled to true
if (-not $softwareInstalled)
{
Write-Output "$pcHostName`: Not installed`n"
}
else
{
Write-Output "$pcHostName`: Fully installed`n"
}
}
else
{
Write-Output "$pcHostName`: Error - Connection failed`n"
}
} # End - $scriptBlock
$pcHostNames | % {
Start-Job -Scriptblock $scriptBlock -ArgumentList $_
}
$reportList = Get-Job | Wait-Job | ?{$_.state -eq "Completed"} | Receive-Job
我目前有一个 powershell (v2) 脚本,它获取主机 PC 列表,远程检查一些 files/software 是否在它们应该在的位置,并在完成后通过电子邮件发送一串结果。但是,当尝试在 100 多个房间中一次一个地依次执行此操作时,脚本需要相当长的时间才能完成。
为了加快速度,我一直在尝试通过使用作业报告每个主机名来使脚本成为多线程。为了清楚起见,我将代码的主要部分放在下面,并删除了一些较大的不相关部分。
$pcHostNames = Get-Content "$scriptPath\HostNames.txt"
$scriptBlock = {
Param(pcHostName)
$softwareInstalled = $false
# Test to see if host can be reached
If (Test-Connection -ComputerName $pcHostName -Quiet)
{
# Multiple lines of code to check if different files/software are installed on each remote PC
# If they are installed, set $softwareInstalled to true
if (-not $softwareInstalled)
{
$reportList += "$pcHostName`: Not installed`n"
}
else
{
$reportList += "$pcHostName`: Fully installed`n"
}
}
else
{
$reportList += "$pcHostName`: Error - Connection failed`n"
}
} # End - $scriptBlock
$pcHostNames | % { Start-Job -Scriptblock $scriptBlock -ArgumentList $_ } | Get-Job | Wait-Job | Receive-Job
目前,该脚本对 PC 执行 ping 命令,然后检查是否安装了各种 files/software,并将一个字符串添加到 $reportList,然后在电子邮件中使用该字符串在我的代码的另一部分发送报告。
由于 $reportList 超出了每个作业的范围,我得到的只是脚本末尾的空白电子邮件。由于无法从作业中将字符串值添加到变量,有没有办法将我的作业管道代码编辑为 return 一个字符串值,然后我可以将其添加到变量?
我认为这个问题可能与我的代码的最后一行有关,所以我尝试了几种不同的执行作业变体,但我在网上找到的东西并没有太多运气。
或者,是否有更好的方法通过其他方法多线程处理此脚本?
变量存在于它们被创建的范围内。
当您在作业中声明变量时,它们仅存在于该作业的范围内。
如果您想将详细信息从子作业传回给调用者,您需要使用 Write-Output。然后使用Get-Job监控作业的状态,直到完成,然后使用Receive-Job获取输出。
start-job {write-output "hello world"}
get-job | receive job
编辑:
以您的示例代码块为例,下面使用 write-output 从作业中获取 return 结果,过滤成功完成的作业,接收作业的输出并将它们存储在$reportList 变量
$pcHostNames = Get-Content "$scriptPath\HostNames.txt"
$scriptBlock = {
Param(pcHostName)
$softwareInstalled = $false
# Test to see if host can be reached
If (Test-Connection -ComputerName $pcHostName -Quiet)
{
# Multiple lines of code to check if different files/software are installed on each remote PC
# If they are installed, set $softwareInstalled to true
if (-not $softwareInstalled)
{
Write-Output "$pcHostName`: Not installed`n"
}
else
{
Write-Output "$pcHostName`: Fully installed`n"
}
}
else
{
Write-Output "$pcHostName`: Error - Connection failed`n"
}
} # End - $scriptBlock
$pcHostNames | % {
Start-Job -Scriptblock $scriptBlock -ArgumentList $_
}
$reportList = Get-Job | Wait-Job | ?{$_.state -eq "Completed"} | Receive-Job