我试图拉动的脚本让我感到有点失落。
简而言之:我想扫描我的域名计算机以获取WinRM连接 - 我可以做到这一点。问题是,完成需要5分钟 - 这就是我想要多线程完成任务的原因。
# this is normaly a textfile with lots of machine hostnames
$computers = "PC100","PC106","PC124","PC115","PC21"
function checkMachine($computers){
$ErrorActionPreference = "Stop"
foreach ($item in $computers){
#the function contest only performs a ping and returne $true or $false
$connection = ConTest($item)
if($connection){
try{
$winRM = test-wsman -ComputerName $item
if($winRM){
write-host "winRM"
[void] $objListboxLeft.Items.Add($item)
}
}catch{
write-host "NO winRM"
[void] $objListboxCenter.Items.Add($item)
}
}else{
write-host "offline"
[void] $objListboxRight.Items.Add($item)
}
}
}
这基本上只是我的skript做/将做的一小部分,但它是需要很长时间的部分。
我失败的runpace测试 - 我基本上没有得到任何结果。文本框中没有任何东西,我的命令行上没有输出,我基本上不知道我做错了什么。
function MulticheckMachine($computers){
$ErrorActionPreference = "Stop"
$runspaceCollection = @()
$runspacePool = [RunspaceFactory]::CreateRunspacePool(1,5)
$runspacePool.open()
$scriptBlock = {
Param($item)
$connection = ConTest($item)
if($connection){
try{
test-wsman -ComputerName $item
$winRM = test-wsman -ComputerName $item
if($winRM){
write-host "winRM"
[void] $objListboxLeft.Items.Add($item)
}
}catch{
write-host "NO winRM"
[void] $objListboxCenter.Items.Add($item)
}
}else{
write-host "offline"
[void] $objListboxRight.Items.Add($item)
}
}
Foreach($item in $computers){
$powershell = [PowerShell]::Create().AddScript($scriptBlock).AddArgument($item)
$powershell.runspacePool = $runspacePool
[Collections.Arraylist]$runspaceCollection += New-Object -TypeName PSObject -Property @{
Runspace = $powershell.BeginInvoke()
PowerShell = $powershell
}
$runspaceCollection
}
While($runspaceCollection){
Foreach($runspace in $runspaceCollection.ToArray()){
If($runspace.Runspace.IsCompleted){
$runspace.PowerShell.EndInvoke($runspace.Runspace)
$runspace.PowerShell.Dispose()
$runspaceCollection.Remove($runspace)
}
}
}
}
runpace代码来自这些指南的混合:
http://newsqlblog.com/2012/05/22/concurrency-in-powershell-multi-threading-with-runspaces/
我希望有人可以帮助我,告诉我在哪里/为什么失败。谢谢!
答案 0 :(得分:1)
嗯,谢谢提示,但问题更为基础。
我试图将我的数据放在错误的位置。另外,我简化了我的脚本。我不再在函数中调用函数了。
注1:我没有意识到我可以/需要使用我的scriptblock中的返回值作为运行空间。
注意2:我现在收集我的数据并将其插入到我的列表框中(或者我想要的其他地方)在while循环中我的函数结束 - 我基本上构建了我的运行空间。
注3:所有" GUI部分"我引用的是位于不同的文件中并且确实存在!
我把持续时间缩短到大约20秒(从差不多5分钟开始)
我使用的线程数有点随机,它是最快的组合之一。
代码:
function multiCheckMachine($computers){
$ErrorActionPreference = "Stop"
$runspaceCollection = @()
$runspacePool = [RunspaceFactory]::CreateRunspacePool(1,50)
$runspacePool.open()
$scriptBlock = {
Param($item)
$FQDNitem = "$item.domain.com"
$address = nslookup $FQDNitem
if($address -like "addresses*"){
$address = $address[5] -replace ".* ",""
}else{
$address = $address[4] -replace ".* ",""
}
$con = ping -n 1 $address
if($con[2] -like "*Bytes*"){
$winRM = test-wsman -ComputerName $item
if($winRM){
return "$item.winRM"
}else{
return "$item.NOremote"
}
}else{
return "$item.offline"
}
}
Foreach($item in $computers){
$powershell = [PowerShell]::Create().AddScript($scriptBlock).AddArgument($item)
$powershell.runspacePool = $runspacePool
[Collections.Arraylist]$runspaceCollection += New-Object -TypeName PSObject -Property @{
Runspace = $powershell.BeginInvoke()
PowerShell = $powershell
}
}
While($runspaceCollection){
Foreach($runspace in $runspaceCollection.ToArray()){
If($runspace.Runspace.IsCompleted){
if($runspace.PowerShell.EndInvoke($runspace.Runspace) -like "*winrm"){
[void] $objListboxOnline.Items.Add($runspace.PowerShell.EndInvoke($runspace.Runspace).split(".")[0])
}elseif($runspace.PowerShell.EndInvoke($runspace.Runspace) -like "*NOremote"){
[void] $objListboxNoWinRM.Items.Add($runspace.PowerShell.EndInvoke($runspace.Runspace).split(".")[0])
}elseif($runspace.PowerShell.EndInvoke($runspace.Runspace) -like "*offline"){
[void] $objListboxOffline.Items.Add($runspace.PowerShell.EndInvoke($runspace.Runspace).split(".")[0])
}
$runspace.PowerShell.Dispose()
$runspaceCollection.Remove($runspace)
}
}
}
}