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

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?


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

  • 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)
  • 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 "syswow64WindowsPowerShellv$versionpowershell.exe")
        }
    
        return (join-path $env:windir "System32WindowsPowerShellv$versionpowershell.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
    }
    

    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.

    链接地址: http://www.djcxy.com/p/29098.html

    上一篇: 为什么不编辑并继续在x64 CLR上工作?

    下一篇: 针对PowerShell的x64与x86变异进行编程的最佳方式是什么?