Dynamically switch Powershell to run in 64-bit mode

03 Sep 2013

Powershell is an amazing tool in the MS Windows world of computing, I explain to the unfamiliar that it’s like BASH for windows. You can accomplish pretty much anything in *nix using BASH scripting and the same is becoming true using Powershell for Windows. Want to query Active Directory for all startup scripts assigned to a user in an OU? Powershell can do it. Want to deploy an application to every PC in your remote office in Tunguska, Siberia? Powershell can do it. Want to verify a service is running on your helpdesk server and restart it not? Powershell can do it.

As with any new tool Powershell does have its own learning curve and quirks, getting a handle of the syntax and process behavior does take some time as you’ll see with this example.

I stumbled upon this Powershell oddity while trying to parse and import a Microsoft Excel document into JD Edwards EnterpriseOne table. To do this I was calling Powershell from a C program using the jdeSystem command (the JDE version of a C library ‘system’ call). I developed the application, the business function and the Powershell script on my development client, tested it and everything went swimmingly, of course all this on the first try too. ;) Next comes a build and deploy for a unit-test in our development environment JAS and application servers. This time when I run the test I get…nothing. No errors, no warnings and no expected data. I was baffled; it still runs perfectly on my dev client but not on the server.

The culprit a combination our 64-bit Microsoft Server 2008 R2 Enterprise Server, 64-bit MS Excel ODBC driver and our 32-bit compiled JDE software. All JD Edwards C functions are compiled as 32-bit programs so when you make a ‘system’ call to launch Powershell it will by default launch the 32-bit Powershell environment regardless of the 64-bit OS… and 32-bit Powershell just won’t play nice with a 64-bit ODBC driver.

After a lot of Google-fu I found a blog post describing a similar situation and derived my fix. You ask Powershell to verify its architecture and relaunch itself recursively using, in my case, the 64-bit environment.

This is another good explanation as to when the $env:PROCESSOR_ARCHITE6432 is set to either x86 or AMD64.

Here is a brief explanation of the script below:

  1. Script launches
  2. Checks the environment variable PROCESSOR_ARCHITEW6432 to determine if we are in 64 or 32 bit land.
  3. If in 32-bit land, relaunch script using 64-bit Powershell and exit. Otherwise complete the script normally.

This really saved me a lot of headache and I hope it helps someone else.

####################################################
# 32-bit-Test.ps1
# Created: 03/20/2013
# Author: me
# Summary: This script will test if Powershell is 
#          running in 32-bit mode and if true
#          launch itself in 64-bit mode for completion
####################################################

########################################################################################################
#If Powershell is running the 32-bit version on a 64-bit machine, we need to force powershell to run in
#64-bit mode to allow the OleDb access to function properly.
########################################################################################################
if ($env:PROCESSOR_ARCHITEW6432 -eq "AMD64") {
	write-warning "Y'arg Matey, we're off to 64-bit land....."
	if ($myInvocation.Line) {
		&"$env:WINDIR\sysnative\windowspowershell\v1.0\powershell.exe" -NonInteractive -NoProfile $myInvocation.Line
	}else{
		&"$env:WINDIR\sysnative\windowspowershell\v1.0\powershell.exe" -NonInteractive -NoProfile -file "$($myInvocation.InvocationName)" $args
	}
exit $lastexitcode
}


write-host "Main script body"

################
# END
################