使用PowerShell进行多线程处理

时间:2016-04-06 03:37:29

标签: event-log powershell-remoting powershell-v4.0

我已经使用Get-JobWait-Job在PowwerShell中完成了大量关于多线程的阅读,但似乎仍无法解决这个问题。

最终,我会将此作为基于GUI的脚本运行,并且不希望我的GUI在执行任务时冻结。

脚本正在查找我的域控制器的事件日志,然后获取我想要的详细信息,然后输出它们,它就像我需要它一样。

我可以使用Invoke-Command {#script goes here} -ComputerName ($_) -AsJob -JobName $_开始工作并运行作业。

下面的脚本:

Clear-Host

Get-Job | Remove-Job

(Get-ADDomainController -Filter *).Name | ForEach-Object {

    Invoke-Command -ScriptBlock {

        $StartTime = (Get-Date).AddDays(-4)

        Try{
            Get-WinEvent -FilterHashtable @{logname='Security'; id=4740;StartTime=$StartTime} -ErrorAction Stop `
            | Select-Object * | ForEach-Object {

                $Username   = $_.Properties[0].Value
                $lockedFrom = $_.Properties[1].Value
                $DC         = $_.Properties[4].Value
                $Time       = $_.TimeCreated

                Write-Host "---------------------------------------------"
                Write-Host $Username
                Write-Host $lockedFrom
                Write-Host $DC
                Write-Host $Time
                Write-Host "---------------------------------------------"

            }#ForEach-Object

        }catch [Exception] {
            If ($_.Exception -match "No events were found that match the specified selection criteria") {  
                Write-Host "No events for locked out accounts." -BackgroundColor Red
            }#If

        }#Try Catch

    } -ComputerName ($_) -AsJob -JobName $_ | Out-Null # Invoke-Command

}#ForEach-Object

目前我有一个While循环告诉我它等待然后向我显示结果:

(Get-ADDomainController -Filter *).Name | ForEach-Object {

    Write-Host "Waiting for: $_."

        While ($(Get-Job -Name $_).State -ne 'Completed') {
            #no doing anything here 
        }#While

    Receive-Job -Name $_ -Keep

}#ForEach-Object

#clean up the jobs
Get-Job | Remove-Job

考虑到我的GUI(要创建),我将为每个域控制器创建一个列并在每个标题下显示结果,如何使它不冻结我的GUI并在它们到达时显示结果?

我知道有几次被问过,但是我不能解决这些例子。

1 个答案:

答案 0 :(得分:0)

我会避免使用Start-Job进行线程处理 - 为了提高效率,请尝试运行空间工厂。

这是一个基本设置,可能很有用(我也有PS 4.0),并且可以接受建议/改进。

$MaxThreads = 2
$ScriptBlock = {
   Param ($ComputerName)
   Write-Output $ComputerName
   #your processing here...
}

$runspacePool = [RunspaceFactory]::CreateRunspacePool(1, $MaxThreads)
$runspacePool.Open()
$jobs = @()

#queue up jobs:
$computers = (Get-ADDomainController -Filter *).Name
$computers | % {
    $job = [Powershell]::Create().AddScript($ScriptBlock).AddParameter("ComputerName",$_)
    $job.RunspacePool = $runspacePool
    $jobs += New-Object PSObject -Property @{
        Computer = $_
        Pipe = $job
        Result = $job.BeginInvoke()
    }
}

# wait for jobs to finish:
While ((Get-Job -State Running).Count -gt 0) {
    Get-Job | Wait-Job -Any | Out-Null
}

# get output of jobs
$jobs | % {
    $_.Pipe.EndInvoke($_.Result)
}