如何使用最佳传递脚本块,以便从'Start-Job' 'Invoke-Command'



我发现了一个powershell示例,它主要满足了我的需求(感谢Lee_Dayey,https://stackoverflow.com/a/54469296/18171669)然而,该示例在机器列表上连续运行,这意味着任何断电的机器都会导致超时,目前每台机器的超时时间大约为60秒。由于许多机器可能处于离线状态,这可能意味着要等待很长时间。所以我把这个例子搞砸了,以获取每个启动作业的信息&调用命令我看到了"@user4003407"的一个建议,它对我来说很有意义(使用StartJob调用InvokeCommand(,我有一个工作版本。

然而,为了使它发挥作用,我必须将Invoke命令的脚本块放入for循环中,这有点困扰我,因为它在每次循环迭代中都会被初始化。因此,我希望有人能为我指明一个正确的方向,找到一个可以将scriptblock从for循环中取出的方法,这样它只需要初始化一次。我试着用$using:xxx和一大堆其他方法将脚本块作为参数传递,但我似乎无法使其工作。

我承认这是一个权力空壳。

提前谢谢。

#requires -RunAsAdministrator
param($myCSV = '.getSysInfo.csv')
# fake reading in a list of computer names
<#
$ComputerList = @' 
jupiter
saturn
'@ -split [environment]::NewLine
#>
$ComputerList = Get-ADObject -LDAPFilter "(objectClass=computer)" -SearchBase 'OU=Servercomputers,OU=batcave,DC=gothham,DC=com' -Properties name | Select-Object -Property name | foreach { $_.name }
foreach ($computer in $ComputerList) {
$running = @(Get-Job | Where-Object { $_.State -eq 'Running' })
if ($running.Count -ge 16) {
$running | Wait-Job -Any | Out-Null
}

$job = {
$IC_ScriptBlock = {
$CIM_ComputerSystem = Get-CimInstance -ClassName CIM_ComputerSystem
$CIM_BIOSElement = Get-CimInstance -ClassName CIM_BIOSElement
$CIM_OperatingSystem = Get-CimInstance -ClassName CIM_OperatingSystem
$CIM_Processor = Get-CimInstance -ClassName CIM_Processor
$CIM_LogicalDisk = Get-CimInstance -ClassName CIM_LogicalDisk |
Where-Object {$_.Name -eq $CIM_OperatingSystem.SystemDrive}
$Win32_QuickFixEngineering = Get-CimInstance -ClassName Win32_QuickFixEngineering -Property HotFixId | Select-Object -Property HotFixId
$CIM_NetworkAdapter = Get-CimInstance -ClassName CIM_NetworkAdapter

[PSCustomObject]@{
LocalComputerName = $env:COMPUTERNAME
Manufacturer = $CIM_ComputerSystem.Manufacturer
Model = $CIM_ComputerSystem.Model
SerialNumber = $CIM_BIOSElement.SerialNumber
CPU = $CIM_Processor.Name
SysDrive_Capacity_GB = '{0:N2}' -f ($CIM_LogicalDisk.Size / 1GB)
SysDrive_FreeSpace_GB ='{0:N2}' -f ($CIM_LogicalDisk.FreeSpace / 1GB)
SysDrive_FreeSpace_Pct = '{0:N0}' -f ($CIM_LogicalDisk.FreeSpace / $CIM_LogicalDisk.Size * 100)
RAM_GB = '{0:N2}' -f ($CIM_ComputerSystem.TotalPhysicalMemory / 1GB)
OperatingSystem_Name = $CIM_OperatingSystem.Caption
OperatingSystem_Version = $CIM_OperatingSystem.Version
OperatingSystem_BuildNumber = $CIM_OperatingSystem.BuildNumber
OperatingSystem_ServicePack = $CIM_OperatingSystem.ServicePackMajorVersion
CurrentUser = $CIM_ComputerSystem.UserName
LastBootUpTime = $CIM_OperatingSystem.LastBootUpTime
HotFixes = $Win32_QuickFixEngineering.HotFixId -join '; '
NetworkAdapter_Name = $CIM_NetworkAdapter.Name -join '; '
}
}
Invoke-Command -ComputerName $args[0] -ScriptBlock $IC_ScriptBlock -ErrorAction 'SilentlyContinue'
}
#Write-Host "Starting job for $computer"
Start-Job -Name $computer -ScriptBlock $job -ArgumentList $computer | Out-Null
}
Write-Host "Waiting for jobs to complete..."
# Wait for all jobs to complete and results ready to be received
Wait-Job -Name $ComputerList | Out-Null
# Get-Job *
$RespondingSystems = Receive-Job -Name $ComputerList
Remove-Job -Name $ComputerList
$RespondingSystems | Select-Object -Property * -ExcludeProperty PSShowComputerName, PSComputerName, RunspaceId | Export-Csv -Path $myCSV -NoTypeInformation -Delimiter ';'
$NOT_RespondingSystems = $ComputerList.Where({
$_ -notin $RespondingSystems.LocalComputerName
})
Write-Host "`nNon-Responding Systems: "
$NOT_RespondingSystems

启动一个将调用保存到远程主机的本地作业效率非常低,另一方面远程作业效率很高,只需允许Invoke-Command获取计算机阵列并并行调用远程作业就可以简化代码,您可以收集所有调用的结果,然后按ErrorRecord类型的对象进行筛选。

$ou = 'OU=Servercomputers,OU=batcave,DC=gothham,DC=com'
$computers = Get-ADComputer -Filter * -SearchBase $ou
$IC_ScriptBlock = { <# Original IC Scriptblock code here #> }
$result = Invoke-Command -ComputerName $computers -ScriptBlock $IC_ScriptBlock 2>&1
$failed, $success = $result.where({
$_ -is [System.Management.Automation.ErrorRecord] }, 'Split'
)
$success | Export-Csv .... -NoTypeInformation
$failed.Exception.Message # => Is the list of failed invocations

最新更新