Start-Job in 64-bit PowerShell fails if launched form 32-bit PowerShell

System Center Orchestrator launches 32-bit PowerShell 2.0 to run PowerShell scripts. I thought I had a good solution, wrapping code with this to launch it in a 64-bit 4.0 session of PowerShell. (This is the simplified version without parameters.)

If ( [IntPtr]::Size * 8 -eq 32 ) { Set-Location -Path 'C:\Windows\SysNative\WindowsPowerShell\v1.0' }
Else                             { Set-Location -Path 'C:\Windows\System32\WindowsPowerShell\v1.0'  }
.\PowerShell.exe -command {
# Code here
}

I can test it like this.

If ( [IntPtr]::Size * 8 -eq 32 ) { Set-Location -Path 'C:\Windows\SysNative\WindowsPowerShell\v1.0' }
Else                             { Set-Location -Path 'C:\Windows\System32\WindowsPowerShell\v1.0'  }
.\PowerShell.exe -command {
Return $PSVersionTable.PSVersion.ToString(), "$([IntPtr]::Size * 8)-bit"
}

Testing in many different types of PowerShell on various server OS’s, this verifies that no matter what version and bit-ness of PowerShell I run it it, the core code will be run in 64-bit 4.0.

The problem arises when I try to start a job. Like this.

If ( [IntPtr]::Size * 8 -eq 32 ) { Set-Location -Path 'C:\Windows\SysNative\WindowsPowerShell\v1.0' }
Else                             { Set-Location -Path 'C:\Windows\System32\WindowsPowerShell\v1.0'  }
.\PowerShell.exe -command {
 
$ExecutableJob = Start-Job -ScriptBlock { Return 'Result'}
Return $PSVersionTable.PSVersion.ToString(), "$([IntPtr]::Size * 8)-bit", $ExecutableJob.State
 }

When I run this from 64-bit PowerShell (any version) the returned job state is “Running.”. When I run this from 32-bit PowerShell (any version) the returned job state is “Failed”. Both the returned data and monitoring in Task Manager show that the code is running on a separate, 64-bit PowerShell instance. So what is the difference between a 64-bit PowerShell instance launched from 32-bit PowerShell and a 64-bit PowerShell instance launched from 64-bit PowerShell that causes jobs in the former to fail?

It’s probably something in the way jobs spin up additional PowerShell threads. It’s not exactly the same as starting a new process, because the original process in this case needs to be able to track and control the child process. It might simply be that a 32-bit process isn’t allowed to “own” 64-bit child processes.

Tim lots of info here on orchestrator & PS

i also found this which changes Orchestrator to default to PS 4.0

Orchestrator & Ps can be very fickle especially with exchange …

Some more from a guy called Noah Stahl who looks to be pretty clued up with Scorch & PS interaction and problems

Mark,

Thanks for the links. My group membership was finally approved, so I was able to take a look at this today.

I like the registry hack for forcing Orchestrator to use the lastest version of PowerShell. However, am I correct in assuming that it still launches a 32-bit session? 32-bit vs 64-bit can cause more problems than 2.0 vs 4.0.

At my current client, I would not be able to implement it in the current environment. Thousands of runbooks maintained by many different teams. Too big of a risk of a breaking change in a mission critical script. But it is definitely going on my check list for any future implementations.

Nick’s article uses Invoke-Command to launch a 64-bit session. Invoke-Command shares a shortcoming with PowerShell.exe -command in this usage, in that you can’t pass a scriptblock longer than roughly 12,000 bytes. In my current project, the goal was to take a bunch of existing scripts, wrap them in a simple wrapper, and plop them into Orchestrator activities without significant refactoring. Unfortunately, few of them meet that size constraint.

For most of the scripts so far, the quickest solution has been to tweak them to be 32-bit PS 2.0 compliant.

Thanks.