Question

I am searching a list of computers event logs for a specific event. This list is 7,000+ systems. I would love to have this utilize runspaces. I have the following code, yet it does not work. It looks like the return is null and of course causes the CSV export to fail.

Any suggestions?

Thanks!

# Max Runspaces
$Throttle = 5 #threads

# What is the total number of events to pull?
$eventMax = 10

# Which event log do we want to pull from?
$eventLog = "System"

$eventEntryID = "7023"

$eventMessage = "The Windows Modules Installer service terminated with the following error: 
The configuration registry database is corrupt."

# What is our source file, the one with ll the file names.
$computers = Get-Content "c:\temp\Louis\hostsins.txt"

# What is our CSV file
$outFile = "c:\temp\Louis\SearchEventLogResultsINS.csv"

$ScriptBlock = {
    Param (
        [string]$sComputer
    )

    $RunResult = Get-WinEvent -Oldest  -ComputerName $sComputer -FilterHashtable @{LogName = $eventLog; ID = $eventEntryID;} | 
                 where{$_.Message -eq $eventMessage} | 
                 Select machinename, TimeCreated, ID, LevelDisplayname, Message 
    write-host $RunResult

    Return $RunResult
}

$RunspacePool = [RunspaceFactory]::CreateRunspacePool(1, $Throttle)
$RunspacePool.Open()
$Jobs = @()

$computers | % {

   write-host $_

   $Job = [powershell]::Create().AddScript($ScriptBlock).AddArgument($_)
   $Job.RunspacePool = $RunspacePool
   $Jobs += New-Object PSObject -Property @{
        RunNum = $_
        Pipe = $Job
        Result = $Job.BeginInvoke()
   }
}

Write-Host "Running.." -NoNewline
Do {
    Write-Host "." -NoNewline
    Start-Sleep -Seconds 1
} While ( $Jobs.Result.IsCompleted -contains $false)
Write-Host "All jobs completed!"

$Results = @()
ForEach ($Job in $Jobs){
    $Results += $Job.Pipe.EndInvoke($Job.Result)
}

$Results | Export-Csv $outFile
Was it helpful?

Solution

It looks like you are declaring variables outside of the runspace and attempting to use them in the runspace.

I see you pass in each computer with .addargument($_). Nothing else though. Runspaces are great for speed, but a little less convenient due to issues like this.

For more reading, check out Dave Wyatt's post, which includes other references. Be sure to flip through the MSDN documentation on initialsessionstate, runspacefactory, runspacepool, and powershell, and explore and experiment with various properties and methods at the prompt.

I tried to rework your code, haven't tested it, but this should illustrate a workaround for you:

# Max Runspaces
$Throttle = 5 #threads

#Throw the stuff you want to pass in into a hashtable or whatever vehicle meets your needs
$params = @{
    eventMax = 10
    eventLog = "System"
    eventEntryID = "7023"
    eventmessage = "The Windows Modules Installer service terminated with the following error: 
The configuration registry database is corrupt."
    computer = $_
}

# What is our source file, the one with ll the file names.
$computers = Get-Content "c:\temp\Louis\hostsins.txt"

# What is our CSV file
$outFile = "c:\temp\Louis\SearchEventLogResultsINS.csv"

$ScriptBlock = {
    Param (
        [System.Collections.Hashtable]$hash
    )


    $RunResult = Get-WinEvent -Oldest  -ComputerName $hash.computer -FilterHashtable @{LogName = $hash.eventLog; ID = $hash.eventEntryID;} | 
                 where{$_.Message -eq $hash.eventMessage} | 
                 Select machinename, TimeCreated, ID, LevelDisplayname, Message 
    write-host $RunResult

    Return $RunResult
}

$RunspacePool = [RunspaceFactory]::CreateRunspacePool(1, $Throttle)
$RunspacePool.Open()
$Jobs = @()

$computers | % {

    $params = @{
        eventLog = "System"
        eventEntryID = "7023"
        eventmessage = "The Windows Modules Installer service terminated with the following error: 
    The configuration registry database is corrupt."
        computer = $_
    }

   write-host $_


   $Job = [powershell]::Create().AddScript($ScriptBlock).AddArgument($params)
   $Job.RunspacePool = $RunspacePool
   $Jobs += New-Object PSObject -Property @{
        RunNum = $_
        Pipe = $Job
        Result = $Job.BeginInvoke()
   }
}

Write-Host "Running.." -NoNewline
Do {
    Write-Host "." -NoNewline
    Start-Sleep -Seconds 1
} While ( $Jobs.Result.IsCompleted -contains $false)
Write-Host "All jobs completed!"

$Results = @()
ForEach ($Job in $Jobs){
    $Results += $Job.Pipe.EndInvoke($Job.Result)
}

$Results | Export-Csv $outFile

Cheers!

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top