Runspace hashtables becomes empty outside scriptblock

Hi,

I’m having a problem where my variable synchronised hashtable $hash does not exist my scriptblock with the data i store to it in the script block.

The line in my scriptblock generates what i expect and i get the desired count:

$hash = $theResults2.Clone()
 $hash.stuff.count

but when I exit my runspace and run the below again, it’s zero.

        $hash.stuff.count
 
        # Clean-up Runspace Pool
        $pool.close();
        $pool.dispose();

Any ideas? The full runspace snippet of code as follows:

$block = {

    #Use $line and $dest parameters into script block
	Param(
        #[string] $element,
        
        [hashtable]$hash,
        $theSearch,
        $theSourceStart,
        $theSource,
        $theDest,
        [int]$i,
        $getSearchCountStrLength,
        $theResults
   
    )


    function BlkGetMessage {

        Param(
            [string]$msg,
            [string]$num
        )
        $timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
        $statusMessage.host.ui.WriteLine("[$timestamp][$num]: $msg")

    }

    $theSource = Get-Item -LiteralPath $element
    $theFinalDest = $theDest + '\' + $theSearch + '.csv'
    $i2 = "{0:d$getSearchCountStrLength}" -f $i

    $msg1 = "Started searching $theSourceStart with keyword '$theSearch'"
    BlkGetMessage $msg1 $i2

    $theResults = $theSource | Select-String -Pattern $theSearch | Select-Object -Property Path, Pattern, LineNumber, Line
    [pscustomobject]@{
    'Path'=$theResults.Path
    'Pattern'=$theResults.Pattern
    'LineNumber'=$theResults.LineNumber
    'Line'=$theResults.Line
    } | Out-Null

    $theResults2 = $theResults | Group-Object -Property Pattern -AsHashTable

    $hash = $theResults2.Clone()
    

    $theResultsCount = $theResults.Count

    $msg2 = "Finished searching $theSourceStart with keyword '$theSearch'. $theResultsCount lines located"
    BlkGetMessage $msg2 $i
}
..... some code....

$runspace = ""

$statusMessage = [hashtable]::Synchronized(@{})
$statusMessage.Flag = $True
$statusMessage.Host = $host

$hash = [hashtable]::Synchronized(@{})

$Variable = New-object System.Management.Automation.Runspaces.SessionStateVariableEntry -ArgumentList 'statusMessage',$statusMessage ,$Null
$sessionstate = [System.Management.Automation.Runspaces.InitialSessionState]::CreateDefault()


$sessionstate.Variables.Add($Variable)

...some code....

 if ($searchCount -ne 0) {

        GetMessage "Search process started"

        ForEach($file in $getFiles) {

            $theSource = $file
   
            #Counter to identify the number of the file being converted
            $i++

            #Create runspace for for each CSV identified
            $runspace = [PowerShell]::Create()

            #Add the script block and all variables to be used within the script block
            $null = $runspace.AddScript($block)
            $null = $runspace.AddArgument($hash)
	        $null = $runspace.AddArgument($theSearch)
	        $null = $runspace.AddArgument($theSourceStart)
            $null = $runspace.AddArgument($theSource)
            $null = $runspace.AddArgument($theDest)
            $null = $runspace.AddArgument($i)
            $null = $runspace.AddArgument($getSearchCountStrLength)
            $null = $runspace.AddArgument($theResults)
            $null = $runspace.AddArgument($statusMessage)

            #Add the runspace to the pool and execute it
            $runspace.RunspacePool = $pool
            $runspaces += [PSCustomObject]@{ Pipe = $runspace; Status = $runspace.BeginInvoke() }
        }

        
        

        $currentcount = 0;
        $totalcount = ($runspaces | measure-object).count;
 
        # Pause until all runspaces have completed
        while ($runspaces.status -ne $null)
        {
            $completed = $runspaces | where { $_.status.iscompleted -eq $true };
        
            # Progress bar update with counter
            $currentcount = $currentcount + ($completed | measure-object).count;
            write-progress -activity "Searching Files.." -status "[$currentcount/$totalcount Keywords Completed]" -percentcomplete (([int]$currentcount/[int]$totalcount)*100);
        
            # Set or clear completed runspaces by $null
            foreach ($runspace in $completed)
            {
                $runspace.pipe.endinvoke($runspace.status)
                $runspace.status = $null 
                           
            }
        }   


        $hash.stuff.count
 
        # Clean-up Runspace Pool
        $pool.close();
        $pool.dispose();

Hey Vertigo888, welcome back to the forum. The issue you are seeing is scope. Script blocks are a contained scope similar to a function. The script block does not appear to actually return the hash table as a result. That is being executed in a remote session, so the result needs to be returned as a result. If you look at this example:

Example 1 of returning data back from a runspace · GitHub

On line 20 the result of the scriptblocks is being returned and line 52 is compiling those results to return all results on line 63. This is another example of getting results:

Immediately Output Runspace Results to the Pipeline | netnerds.net