【PowerShell】依存関係チェッカーに学ぶ、必須ソフトウェアのチェック方法

前回の投稿では、Identity Developer Training Kit で発生する、日本語環境でのエラー回避方法について紹介しました。

【WP7 for IT Pro】Identity Developer Training Kit の前提条件チェックが通らないときの対処

エラー回避のキーとなるのは、Windows PowerShell スクリプトでした。

で、依存関係チェッカーが使用しているスクリプトを改めて眺めてみると、コレが結構勉強になる代物でして。簡単なスクリプトなんですけどね。

Identity Developer Training Kit で用意されている前提条件チェック用スクリプトは以下の通りです。ファイル名を見れば何をチェックしているか、一目瞭然ですよね。

PS C:\IdentityTrainingKitVS2010\Assets\DependencyChecker\scripts\dependencies\check> dir |ft name

Name ---- CheckASPNET4.ps1 CheckAzureMMC.ps1 CheckAzureTools13ForVS2010.ps1 CheckAzureTools14ForVS2010.ps1 CheckAzureToolsForVS2008.ps1 CheckAzureToolsForVS2010.ps1 CheckIIS7.ps1 CheckIis7AspNet.ps1 CheckIisRewrite.ps1 CheckIISStaticContent.ps1 CheckLoadUserProfile.ps1 CheckNET35SP1.ps1 CheckNET4.ps1 CheckNetServicesSDK.ps1 CheckSilverlight4ToolsForVS.ps1 CheckSilverlightDevTools.ps1 CheckSilverlightToolsForVS.ps1 CheckSqlServer.ps1 CheckSqlServer2008.ps1 CheckVistaSP2.ps1 CheckVS2008.ps1 CheckVS2010.ps1 CheckWCFHTTPAct.ps1 CheckWifRuntime.ps1 CheckWifSdk4.ps1 CheckWP7AddInVS2010.ps1 CheckWP7Emulator.ps1

ここで、CheckVS2010.ps1 の中身を見てみましょう。以下は CheckVS2010.ps1 の全体像です。

function SearchUninstall($SearchFor, $UninstallKey, $Version) { $uninstallObjects = ls -path $UninstallKey; $found = $FALSE;

foreach($uninstallEntry in $uninstallObjects) { $entryProperty = Get-ItemProperty -LiteralPath registry::$uninstallEntry if($entryProperty.DisplayName -like $searchFor -and $entryProperty.DisplayVersion -like $Version) { $found = $TRUE; break; } }

$found; }

function SearchAllUninstallKeys($SearchFor, $Version) { $os = Get-WMIObject win32_operatingsystem [bool] $found = $False; $SearchFor64bits = "$SearchFor (64-bit)" # Seach in uninstall folder $found = SearchUninstall -SearchFor $SearchFor -UninstallKey 'HKLM:SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\' -Version $Version; if($found) {return $found;} #Search in 64 bit keys folders if ($os.OSArchitecture -eq "64-bit") { #Wow folder $found = SearchUninstall -SearchFor $SearchFor -UninstallKey 'HKLM:SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\' -Version $Version; if($found) {return $found;} #Wow folder, 64 bits $found = SearchUninstall -SearchFor $SearchFor64bits -UninstallKey 'HKLM:SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\'-Version $Version; if($found) {return $found;} #32bit folder, 64 bits $found = SearchUninstall -SearchFor $SearchFor64bits -UninstallKey 'HKLM:SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\'-Version $Version; if($found) {return $found;} } return $found; }

## SearchAllUninstallKeys -SearchFor 'Microsoft Visual Studio 2010*' -Version '10.0.30319'; SearchAllUninstallKeys -SearchFor 'Microsoft Visual Studio 2010*' -Version '10.0.40219';

一番最後の行が最初に実行されるコマンドで、ここで指定した文字列(製品名)とバージョン番号が SearchUninstall と SearchAllUninstallKeys という関数に渡されます。

SearchUninstall は引数として与えられたレジストリキー(Uninstall)の中から、製品名とバージョン番号を検索する関数です。エントリと値が存在していれば True が返されます。

SearchUninstall を呼び出しているのが SearchAllUninstallKeys 関数です。この関数では、以下の4つのパターンを想定して検索を行っており、いずれかが True になればインストールされていると判断しています。

    • 32ビット用のキーに32ビット版がインストールされている場合
    • 64ビット用のキーに64ビット版がインストールされている場合
    • 64ビット用のキーに32ビット版がインストールされている場合
    • 32ビット用のキーに64ビット版がインストールされている場合

(参考)32-bit and 64-bit Application Data in the Registry (Windows)

もう一つ、別のタイプのスクリプトを見てみましょう。CheckIIS7.ps1 です。ファイル名からわかるとおり、IIS7とASP.NETがインストールされているかどうかをチェックするスクリプトです。

function Check-RegistryValue($PropertyPath, $PropertyName, $PropertyValue) { if ((Test-Path -path $PropertyPath) -ne $True) { return $FALSE; }

    $found = $FALSE; $entryProperty = Get-ItemProperty -path $PropertyPath

    if($entryProperty.psobject.Properties -ne $null) { $registryValue = $entryProperty.psobject.Properties[$PropertyName].value;

        if($registryValue -eq $PropertyValue) { $found = $TRUE; } }

    $found; }

$query = Get-WmiObject Win32_Service | where {$_.Name -eq "w3svc" }

$hasIIS = ($query -ne $null); $hasAspNet = Check-RegistryValue -PropertyPath "HKLM:\SOFTWARE\Microsoft\INETSTP\Components" -PropertyName "ASPNET" -PropertyValue "1";

$hasIIS -and $hasAspNet;

このスクリプトでは、はじめに Win32_Service を使用して IIS(w3csvc)のサービス状態を取得しています。ためしに、PowerShell のコンソールで、以下のコマンドを入力してみてください。

Get-WmiObject Win32_Service | where {$_.Name -eq "w3svc" }

IISが稼働しているかどうかにかかわらず、ただしくサービスとしてインストールされていれば、以下のような結果が返されます。

PS C:\> Get-WmiObject Win32_Service | where {$_.Name -eq "w3svc" }

ExitCode : 0 Name : W3SVC ProcessId : 3108 StartMode : Auto State : Running Status : OK

ASP.NET がインストールされているかどうかはサービスを見るだけでは判別できないため、例によってレジストリキーをチェックしています。ただし、これまでのように「製品」としてインストールされているわけでは無いので Uninstall キーをチェックしても意味がありません。そこで、Uninstall キーの代わりに \SOFTWARE\Microsoft\INETSTP\Components というキーをチェックしています。

最後に、IIS のインストール状態と ASP.NET のインストール状態を論理演算し、結果が True であればチェックをパスすることができます。

以前はこうしたスクリプトは VBSで提供されることが多かったのですが、ここ数年ですっかり Windows PowerShell にとって変わられました。こうした現状を見るにつけ、Windows の次のバージョン(なんて名前になるかは知りませんが)で VBS が使えなくなることは無いにしても、おそらく進化も望めないのだろうと、若干寂しくなる今日この頃です。