Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the best way to program against powershell's x64 vs. x86 variability

Tags:

powershell

We have several scripts we use to install and configure the dependencies backing the systems we maintain. We run these anytime we establish a dev, test, demo, train, prod, etc. environment. We often find that we have to deal with x64 vs. x86 architecture, especially where the powershell scripts are concerned.

For example, I have a script that uses the Windows Installer PowerShell Extensions to determine if a program/patch has been installed. The script doesn't work in an x64 environment without explicitly invoking PowerShell (x86), which, isn't in the path by default. As we port these scripts to the x64 platform it would be great to maintain a single set of scripts that work in powershell on both architectures and only invoke x86 code when needed.

Does anyone know of a strategy for doing this?

like image 563
Rob Murdoch Avatar asked Mar 02 '09 11:03

Rob Murdoch


People also ask

Which is better x64 or x86?

Overall, x64 is much more capable than x86, utilizing all installed RAM, providing more hard drive space, faster bus speeds, and overall better performance.

What is the difference between x64 and x86?

What is the difference between x86 and x64? As you guys can already tell, the obvious difference will be the amount of bit of each operating system. x86 refers to a 32-bit CPU and operating system while x64 refers to a 64-bit CPU and operating system.

Is PowerShell x86 or x64?

When you run Windows PowerShell, the 64-bit version runs by default. However, you might occasionally need to run Windows PowerShell (x86), such as when you're using a module that requires the 32-bit version or when you're connecting remotely to a 32-bit computer.


2 Answers

I run into this issue a lot with my configuration scripts. The basic approach I take is to

  1. Use several functions to test if I'm in a 64 bit environment (http://blogs.msdn.com/jaredpar/archive/2008/10/16/powershell-and-64-bit-windows-helper-functions.aspx)
  2. Invoke x86/x64 PowerShell based on the needs of a particular script

Unfortunately a lot of this is done in a brute force manner. Each particular configuration entry that is x86/x64 dependent essentially has 2 code paths (one for each architecture).

The only real exception I've been able to make is to test for the existince of certain programs on disk. I have a handy function (Get-ProgramFiles32) which makes it easy to test for programs.

if ( test-path (join-path Get-ProgramFiles32 "subversion") ) { ...

Here are all of the helper functions that I have in my common library that deal with 32/64 bit differences.

# Get the path where powershell resides.  If the caller passes -use32 then 
# make sure we are returning back a 32 bit version of powershell regardless
# of the current machine architecture
function Get-PowerShellPath() {
    param ( [switch]$use32=$false,
            [string]$version="1.0" )

    if ( $use32 -and (test-win64machine) ) {
        return (join-path $env:windir "syswow64\WindowsPowerShell\v$version\powershell.exe")
    }

    return (join-path $env:windir "System32\WindowsPowerShell\v$version\powershell.exe")
}


# Is this a Win64 machine regardless of whether or not we are currently 
# running in a 64 bit mode 
function Test-Win64Machine() {
    return test-path (join-path $env:WinDir "SysWow64") 
}

# Is this a Wow64 powershell host
function Test-Wow64() {
    return (Test-Win32) -and (test-path env:\PROCESSOR_ARCHITEW6432)
}

# Is this a 64 bit process
function Test-Win64() {
    return [IntPtr]::size -eq 8
}

# Is this a 32 bit process
function Test-Win32() {
    return [IntPtr]::size -eq 4
}

function Get-ProgramFiles32() {
    if (Test-Win64 ) {
        return ${env:ProgramFiles(x86)}
    }

    return $env:ProgramFiles
}

function Invoke-Admin() {
    param ( [string]$program = $(throw "Please specify a program" ),
            [string]$argumentString = "",
            [switch]$waitForExit )

    $psi = new-object "Diagnostics.ProcessStartInfo"
    $psi.FileName = $program 
    $psi.Arguments = $argumentString
    $psi.Verb = "runas"
    $proc = [Diagnostics.Process]::Start($psi)
    if ( $waitForExit ) {
        $proc.WaitForExit();
    }
}

# Run the specified script as an administrator
function Invoke-ScriptAdmin() {
    param ( [string]$scriptPath = $(throw "Please specify a script"),
            [switch]$waitForExit,
            [switch]$use32=$false )

    $argString = ""
    for ( $i = 0; $i -lt $args.Length; $i++ ) {
        $argString += $args[$i]
        if ( ($i + 1) -lt $args.Length ) {
            $argString += " "
        }
    }

    $p = "-Command & "
    $p += resolve-path($scriptPath)
    $p += " $argString" 

    $psPath = Get-PowershellPath -use32:$use32
    write-debug ("Running: $psPath $p")
    Invoke-Admin $psPath $p -waitForExit:$waitForExit
}
like image 93
JaredPar Avatar answered Oct 20 '22 10:10

JaredPar


The msgoodies blog has this suggestion for determining the architecture. One could use this approach to determine the architecture and invoke the x86 powershell when there is a known incompatibility.

like image 32
Rob Murdoch Avatar answered Oct 20 '22 12:10

Rob Murdoch