PowerShell crashes when using start-job in a loop

In one of my scripts I needed to implement a kind of watch dog for part of the script which had a tendency to barf and get stuck. I settled on using start-job with a timeout so I just wrapped the buggy method in that and then give it 15 seconds to comply before terminating. When the next loop runs it starts by looking for any dead process threads and kills them so all the memory doesn’t fill up. For those interested – the $workbook.close() sometimes just sat there and did nothing until I killed the excel.exe process.

While this seemed to work, after a couple of loops of using start-job PowerShell.exe would display a crash error while the shell window in the background kept running. If you acknowledge the crash, the window would close. This outcome was basically as bad as the buggy part of the script I was trying to correct so I rolled up my sleeves and eventually found the solution.

PowerShell code

Below I’ve highlighted what I had to remove to stop the PowerShell.exe process from crashing. I guess there is something about releasing the com object and calling the garbage collector inside a script block which eventually causes PowerShell to fall over.

[Update from a few hours later] After further investigation it wasn’t the code below, making the change just prevented the error from appearing for a longer period of time. The fix turned out to be installing PowerShell 4.0 x64 on Windows Server 2008 R2 (was at version 2).

#background job code
$scriptblock =
{
param($e,$w)
$e = $Excel
$w = $workbook
$workbook.close()   
$Excel.Quit()
[System.Runtime.Interopservices.Marshal]::ReleaseComObject($Excel)
[gc]::collect()
[gc]::WaitForPendingFinalizers()
   
$Excel = $null
}

$ExcelVar = $Excel
$WorkBookVar = $workbook
$timeout = 15
$job = Start-Job -Scriptblock $scriptblock -ArgumentList @($ExcelVar, $WorkBookVar) -RunAs32
Wait-Job $job -Timeout $timeout
Receive-Job $job
Stop-Job $job
Remove-Job $job

PowerShell Crash Error

Problem signature:
  Problem Event Name:	PowerShell
  NameOfExe:	powershell.exe
  FileVersionOfSystemManagementAutomation:	6.1.7601.17514
  InnermostExceptionType:	System.NullReferenceException
  OutermostExceptionType:	System.NullReferenceException
  DeepestPowerShellFrame:	tOfProcessClientCommandTransportManager.CloseAsync
  DeepestFrame:	tOfProcessClientCommandTransportManager.CloseAsync
  ThreadName:	unknown
  OS Version:	6.1.7601.2.1.0.272.7
  Locale ID:	2057

Read our privacy statement online:
  http://go.microsoft.com/fwlink/?linkid=104288&clcid=0x0409

If the online privacy statement is not available, please read our privacy statement offline:
  C:\Windows\system32\en-US\erofflps.txt

The Fix

Install Windows PowerShell 4.0

Download Windows Powershell 4.0 http://www.microsoft.com/en-us/download/details.aspx?id=40855

and

Create a file “powershell.exe.config” in the C:\Windows\System32\WindowsPowerShell\v1.0

In the file include the following:

<?xml version="1.0"?>
<configuration>
	<startup useLegacyV2RuntimeActivationPolicy="true">
		<supportedRuntime version="v4.0.30319"/>
		<supportedRuntime version="v2.0.50727"/>
	</startup>
</configuration>

References

(which didn’t have any solutions but were similar-ish)

http://www.bonusbits.com/main/KB:PowerCLI_Script_Crashes_When_Running_as_Background_Job

http://connect.microsoft.com/PowerShell/feedback/details/684136/powershell-can-crash-on-exit-if-background-job-sleeps-in-a-loop

http://timothygraves.com/2012/12/09/powershell-has-stopped-working/