2009-03-02 8 views
7

Abbiamo diversi script che usiamo per installare e configurare le dipendenze che supportano i sistemi che manteniamo. Eseguiamo questi in qualsiasi momento stabiliamo un ambiente di sviluppo, test, demo, treno, prod, ecc. Troviamo spesso che dobbiamo fare i conti con l'architettura x64 rispetto a x86, specialmente per quanto riguarda gli script di PowerShell.Qual è il modo migliore per programmare contro la variabilità x64 vs x86 di powershell

Ad esempio, ho uno script che utilizza lo Windows Installer PowerShell Extensions per determinare se è stato installato un programma o una patch. Lo script non funziona in un ambiente x64 senza invocare esplicitamente PowerShell (x86), che, per impostazione predefinita, non si trova nel percorso. Portando questi script sulla piattaforma x64 sarebbe bello mantenere un singolo set di script che funzionano in PowerShell su entrambe le architetture e invocare solo il codice x86 quando necessario.

Qualcuno sa di una strategia per farlo?

risposta

15

Mi sono imbattuto molto in questo problema con i miei script di configurazione. L'approccio di base è quello di iniziare la

  1. Utilizzare diverse funzioni per verificare se sono in un ambiente a 64 bit (http://blogs.msdn.com/jaredpar/archive/2008/10/16/powershell-and-64-bit-windows-helper-functions.aspx)
  2. Invoke x86/x64 PowerShell in base alle esigenze di un particolare script

Sfortunatamente molto di questo viene fatto in maniera bruta. Ogni particolare voce di configurazione dipendente da x86/x64 ha essenzialmente 2 percorsi di codice (uno per ogni architettura).

L'unica vera eccezione che ho potuto fare è verificare l'esistenza di determinati programmi su disco. Ho una comoda funzione (Get-ProgramFiles32) che facilita il test dei programmi.

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

Ecco tutte le funzioni di supporto che ho nella mia libreria comune che si occupano di 32/64 differenze bit.

# 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 
} 
+0

Non vuoi 'Get-ProgramFiles32' per controllare' Test-Win64Machine' invece di 'Test-Win64'? È necessario il percorso corretto basato sulla macchina, non basato sul processo corrente. O mi sta sfuggendo qualcosa? – CoderDennis