Powershellのx64とx86のばらつきに対応するプログラミングの最良の方法は何ですか
-
03-07-2019 - |
質問
維持しているシステムを支える依存関係をインストールおよび構成するために使用するいくつかのスクリプトがあります。開発、テスト、デモ、トレーニング、製品などの環境を確立するたびにこれらを実行します。特にpowershellスクリプトが関係する場合、x64とx86のアーキテクチャを扱う必要があることがよくあります。
たとえば、 Windows Installer PowerShell拡張機能を使用してプログラム/パッチがインストールされました。このスクリプトは、PowerShell(x86)を明示的に呼び出さない限り、x64環境では機能しません。これは、デフォルトではパスにありません。これらのスクリプトをx64プラットフォームに移植する際、両方のアーキテクチャでpowershellで動作し、必要な場合にのみx86コードを呼び出す単一のスクリプトセットを維持することは素晴らしいことです。
これを行うための戦略を知っている人はいますか
解決 2
msgoodiesブログには、アーキテクチャを決定するためのこの提案。このアプローチを使用してアーキテクチャを決定し、既知の非互換性がある場合にx86 powershellを呼び出すことができます。
他のヒント
構成スクリプトでこの問題に頻繁に遭遇します。私が取る基本的なアプローチは
- いくつかの関数を使用して、64ビット環境にいるかどうかをテストします( http://blogs.msdn.com/jaredpar/archive/2008/10/16/powershell-and-64-bit-windows-helper-functions.aspx )
- 特定のスクリプトのニーズに基づいてx86 / x64 PowerShellを呼び出す
残念ながら、これの多くは総当たりで行われます。 x86 / x64に依存する各特定の構成エントリには、本質的に2つのコードパスがあります(アーキテクチャごとに1つ)。
私が作成できた唯一の本当の例外は、ディスク上の特定のプログラムの存在をテストすることです。プログラムのテストを簡単にする便利な関数(Get-ProgramFiles32)があります。
if ( test-path (join-path Get-ProgramFiles32 "subversion") ) { ...
これは、32/64ビットの違いを処理する共通ライブラリにあるヘルパー関数のすべてです。
# 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
}