WMI を使用した IIS 7 でのワーカー プロセスと AppDomain の管理

作成者: Tim Ammann

WMI スクリプトを使用すると、IIS のワーカー プロセスとアプリケーション ドメイン (AppDomain) を比較的簡単に管理できます。 IIS ワーカー プロセスは、Windows プロセス アクティブ化サービス (WAS) によって生成され、W3wp.exe によって実行されます。 ワーカー プロセスには、通常 .aspx ページの要求に応じて作成される AppDomain を含めることができます。

この記事では、わずか数行の VBScript で次のタスクを実行する方法について説明します。

  • ワーカー プロセスに対して現在実行中の要求を表示する
  • すべてのワーカー プロセスの状態を取得する
  • 特定の AppDomain またはすべての AppDomain をアンロードする
  • すべての AppDomain とそのプロパティを表示する

最初の手順

  1. IIS とスクリプトが有効になっていることを確認します。

    a. Windows Vista を使用している場合は、[コントロール パネル]、[プログラムと機能]、[Windows の機能] の順に開きます。 [Web 管理ツール] で、[IIS 管理スクリプトとツール] を選択してスクリプトを有効にします。 b. Windows Server® 2008 を使用している場合は、サーバー マネージャーを開きます。 役割の追加ウィザードを使用して、IIS Web サーバーをインストールします。 [役割サービスの選択] ページの [管理ツール] セクションで、[IIS 管理スクリプトとツール] を選びます。

  2. 管理者としてコマンドを実行します。 コマンド プロンプト ウィンドウを管理者特権で開くには、[スタート] ボタンをクリックし、[すべてのプログラム] をポイントします。次に、[アクセサリ] をクリックし、[コマンド プロンプト] を右クリックして、[管理者として実行] をクリックします。 管理者としてコマンド シェルを開いた場合、そのコマンド シェルから実行するすべてのアプリケーションは管理者として実行されます。

  3. スクリプト ファイルを、拡張子 .vbs を付けてテキスト形式で保存します。 これらは、コマンド プロンプトで構文 "cscript.exe <scriptname>.vbs" を使用して実行できます。

  4. 開始する前に、AppCmd ツールを使用して System32\inetsrv\config\applicationhost.config ファイルのバックアップを作成します。 バックアップ コピーを使用すると、後で元のバージョンをコピーするだけで、IIS を元の状態に復元できます。 バックアップを作成するには、次の手順に従います。

    a. 管理者特権のコマンド プロンプト ウィンドウを開きます。
    b. 「cd %Windir%\system32\inetsrv\」と入力します。c. 「appcmd add backup backupName」と入力して、ApplicationHost.config ファイルのバックアップを作成します。ここで、backupName はバックアップに指定する名前です。 指定したバックアップ名を持つディレクトリが %Windir%\system32\inetsrv\backup ディレクトリの下に作成されます。 名前を指定しない場合、現在の日付と時刻を使用して、appcmd によってディレクトリ名が自動的に生成されます。

ワーカー プロセス

このセクションでは、Web サーバー上の各ワーカー プロセスに対して現在実行中の要求を取得する方法について説明します。 次に、各ワーカー プロセスの PID、状態、それが属するアプリケーション プールを表示する方法を学習します。

実行中の要求を取得する

IIS の魅力的な新機能の 1 つは、ワーカー プロセスで現在実行中の要求を表示する機能です。 これを行うには、WorkerProcess.GetExecutingRequests メソッドを使用します。

WorkerProcess.GetExecutingRequests メソッドは、メソッドの実行時に実行されていた要求をスナップショット形式で報告します。 ほとんどの要求は非常に迅速に実行されるため、Web ブラウザーでメソッドを手動でテストするのは簡単ではない場合があります。 このため、この目的のためだけに Web ページを作成します。

メモ帳を使用して、次のテキストをテキスト ファイルに入力します。 次に、Sleep.aspx という名前を使用してそのファイルを保存します。

<%  System.Threading.Thread.Sleep(30000)
Response.Write ("I'm finally finished...") %>

Sleep.aspx ファイルを、既定の Web サイトのコンテンツ ディレクトリ (%systemdrive%\inetpub\wwwroot) に配置します。

作成した Sleep.aspx ファイルによって、Web ページの要求が強制的に実行されるまでに 30 秒かかります。 これにより、GetExecutingRequests の動作を表示するスクリプトを実行する時間が得られます。

GetExecutingRequests メソッドは、空の配列変数を OUT パラメータとして受け取り、それを HttpRequest オブジェクトで埋めます。 各要求の属性を表示するには、これらの要求を繰り返します。 次のスクリプトは、HttpRequest オブジェクトの出力を受け取り、各要求の現在のモジュール、動詞、ホスト名、URL を表示します。

次のスクリプトをメモ帳にコピーし、GetRequests.vbs というファイル名で保存します。

Set oWebAdmin = GetObject("winmgmts:root\WebAdministration")
Set oWorkerProcesses = oWebAdmin.InstancesOf("WorkerProcess")
     
For Each oWorkerProcess In oWorkerProcesses
    ' Place the requests queued for a process into an array variable.
    oWorkerProcess.GetExecutingRequests arrReqs
    
    ' Show the number of requests queued.
    If IsNull(arrReqs) Then
        WScript.Echo "No currently executing requests."

    Else
        ' Display the number of requests.
        WScript.Echo "Number of currently executing requests: " & _
            UBound(arrReqs) + 1
        WScript.Echo
  
        ' List the properties of each request.
        For Each oRequest In arrReqs
            WScript.Echo "Module: " & "[" & oRequest.CurrentModule & "]"
            WScript.Echo "Verb:" & "[" & oRequest.Verb & "]"
            WScript.Echo "HostName: " & "[" & oRequest.HostName & "]"
            WScript.Echo "Url: " & "[" & oRequest.Url & "]"
            WScript.Echo
        Next
    End If
Next

管理者特権でのコマンド プロンプト ウィンドウを開き、GetRequests.vbs ファイルを保存したディレクトリに移動します。

スクリプトを実行する前に、Web ブラウザーのアドレス バーに「http://localhost/sleep.aspx」を入力します。 これにより、要求の実行が開始され、ブラウザーが Sleep.aspx ページのレンダリングを待機する時間が 30 秒に設定されます。

ブラウザーがページのレンダリングを待機している間に、先ほど開いたコマンド プロンプト ウィンドウに次を入力してスクリプトを実行します。

Cscript.exe GetRequests.vbs

出力例

表示される出力は次のようになります。

Number of currently executing requests: 2
Module: [ManagedPipelineHandler]
Verb:[GET]
HostName: [localhost]
Url: [/MyApp/]
Module: [ManagedPipelineHandler]
Verb:[GET]
HostName: [localhost]
Url: [/MyApp/default.aspx]

ワーカー プロセスの状態の取得

IIS WMI プロバイダーの WorkerProcess オブジェクトには、ワーカー プロセスが開始、実行、または停止しているかどうかを示す GetState メソッドがあります。 WorkerProcess には、ApplicationPool と PID という 2 つの興味深いプロパティもあります。 ApplicationPool プロパティは、ワーカー プロセスが属するアプリケーション プールを表します。 PID プロパティには、ワーカー プロセスを一意に識別するプロセス ID が含まれています。

次のコードを使用すると、各ワーカー プロセスの PID と状態、およびそのアプリケーション プールを一覧表示できます。 ワーカー プロセスが実行されていない場合、スクリプトはサイレントで終了します。 コードをメモ帳にコピーし、GetState.vbs というファイル名で保存します。

' Connect to the WMI WebAdministration namespace. 
Set oWebAdmin = GetObject("winmgmts:root\WebAdministration") 
       
' Get the worker process instances. 
Set oWorkerProcesses = oWebAdmin.InstancesOf("WorkerProcess") 
       
' Get the ID of each worker process in the application pool and report its status. 
For Each oWorkerProcess In oWorkerProcesses 
       
    ' Report the worker process state via the GetStateDescription helper function. 
    WScript.Echo "WorkerProcess " & oWorkerProcess.ProcessID & ": " & _ 
        GetStateDescription(oWorkerProcess.GetState) 
    WScript.Echo "Application Pool: " & oWorkerProcess.AppPoolName
    WScript.Echo 
Next 

' The helper function translates the return value into text. 
Function GetStateDescription(StateCode) 
    Select Case StateCode 
        Case 0 
            GetStateDescription = "Starting" 
        Case 1 
            GetStateDescription = "Running" 
        Case 2 
            GetStateDescription = "Stopping" 
        Case 3 
            GetStateDescription = "Unknown" 
       
        Case Else 
            GetStateDescription = "Undefined value." 
    End Select 
End Function

管理者特権でのコマンド プロンプト ウィンドウを開き、GetState.vbs ファイルを保存したディレクトリに移動します。 開いたコマンド プロンプト ウィンドウに次を入力して、スクリプトを実行します。

Cscript.exe GetState.vbs

出力例

出力は次のようになります。

WorkerProcess 1336: Running 
Application Pool: DefaultAppPool 
       
WorkerProcess 3680: Running 
Application Pool: Classic .NET AppPool 
       
WorkerProcess 1960: Running 
Application Pool: NewAppPool

WMI スクリプトを使用してワーカー プロセスのシークレットを明らかにする方法を学習したので、アプリケーション ドメインに対しても同じことを行います。

AppDomain

ASP.NET ページの要求が初めて受信されると、IIS マネージド エンジン モジュールによってアプリケーション ドメイン (AppDomain) がメモリ内に作成されます。 AppDomain によって、aspx ページまたはマネージド コードを使用する任意のページに対する要求が処理されます。 WMI を使用して AppDomain をアンロードおよび列挙するのは簡単です。このセクションでは、両方の方法を説明します。

特定の AppDomain のアンロード

IIS 7 以降での AppDomain のアンロードは、IIS 6.0 とは若干異なる方法で動作します。 IIS 6.0 AppUnload コマンドがアウトプロセス ASP アプリケーションをアンロードしていたのに対し、IIS 7 以降の AppDomain.Unload メソッドは ASP.NET アプリケーション ドメインのみをアンロードします。 AppUnload 機能は、それをサポートしていた IIS 5.0 互換モードが IIS 7 以降には存在しなくなったため、なくなりました。

特定の AppDomain をアンロードするには、それを一意に識別できる必要があります。 AppDomain オブジェクトには、ApplicationPath、ID、SiteName の 3 つの主要なプロパティがあります。 ただし、これらの 1 つだけで十分な場合があります。

ちなみに、AppDomain ID プロパティは数値ではなく、次のようなパスです。

/LM/W3SVC/1/ROOT

一覧表示されているパスの "1" はサイト ID です (既定では、1 は既定の Web サイトに対応します)。最初にサーバーの AppDomain とそのプロパティの一覧を生成する必要がある場合は、この記事で後述する「AppDomain の列挙」セクションを参照してください。

次のスクリプトは、"Northwind" という AppDomain をアンロードします。このスクリプトは、一致する ApplicationPath を持つ AppDomain が見つかるまで、使用可能な AppDomain を反復処理します。 コードをメモ帳にコピーし、"Northwind" を任意の AppDomain アプリケーション パスに置き換え、AppDomainUnload.vbs という名前でファイルを保存します。

管理者特権でのコマンド プロンプト ウィンドウを開き、AppDomainUnload.vbs ファイルを保存したディレクトリに移動します。 開いたコマンド プロンプト ウィンドウに次を入力して、スクリプトを実行します。

Cscript.exe AppDomainUnload.vbs
Set oWebAdmin = GetObject("winmgmts:root\WebAdministration")
Set oAppDomains = oWebAdmin.ExecQuery("SELECT * FROM AppDomain")

' Unload only the Northwind application domain.
For Each oAppDomain In oAppDomains
    If oAppDomain.ApplicationPath = "/Northwind/" Then 
        oAppDomain.Unload
        Exit For 
    End If 
Next

すべての AppDomain のアンロード

サーバー上のすべての AppDomain をアンロードするのはさらに簡単です。単にそれらを取得し、反復処理し、順番に各 AppDomain をアンロードするだけです。

次の例では、IIS Web サーバー上のすべてのアプリケーション ドメインをアンロードします。 AppDomain を取得するために単純な WQL クエリ (WQL は SQL の WMI バージョンです) がどのように使用されているかに注目してください。

コードをメモ帳にコピーし、AppDomainUnloadAll.vbs という名前でファイルを保存します。 管理者特権でのコマンド プロンプト ウィンドウを開き、AppDomainUnloadAll.vbs ファイルを保存したディレクトリに移動します。 開いたコマンド プロンプト ウィンドウに次を入力して、スクリプトを実行します。

Cscript.exe AppDomainUnloadAll.vbs
Set oWebAdmin = GetObject("winmgmts:root\WebAdministration")

' Get all the application domains on the Web server.
Set oAppDomains = oWebAdmin.ExecQuery("SELECT * FROM AppDomain")

' Unload all the application domains.
For Each oAppDomain In oAppDomains
    oAppDomain.Unload
Next

以前に WorkerProcess で行ったのと同じように、WQL クエリ構文の代わりに、WMI InstancesOf メソッドを使用できます。

Set oAppDomains = oWebAdmin.InstancesOf("AppDomain")

AppDomain の列挙

前のスクリプトと同様のアプローチを使用して、現在実行中のすべての AppDomain とそのプロパティを表示できます。 AppDomain プロパティの一覧を次に示します。

  • ApplicationPath
  • Id
  • IsIdle
  • PhysicalPath
  • ProcessId
  • SiteName

次のスクリプトは、Physical Path プロパティを除く各 AppDomain のすべてのプロパティを示していますが、これは簡単に追加できます。 便宜上、このスクリプトではキーと実行時のプロパティを個別に表示しています。

コードをメモ帳にコピーし、AppDomainProps.vbs という名前でファイルを保存します。 管理者特権でのコマンド プロンプト ウィンドウを開き、AppDomainProps.vbs ファイルを保存したディレクトリに移動します。 開いたコマンド プロンプト ウィンドウに次を入力して、スクリプトを実行します。

Cscript.exe AppDomainProps.vbs
'Connect to the WMI WebAdministration namespace
Set oWebAdmin = GetObject("winmgmts:root\WebAdministration")
Set oAppDomains = oWebAdmin.InstancesOf("AppDomain")
WScript.Echo "AppDomain Count: " & oAppDomains.Count
WScript.Echo 
ADCounter = 0
For Each oAppDomain In oAppDomains
    ADCounter = ADCounter + 1
    WScript.Echo "---- AppDomain " & ADCounter & " of " & _
                oAppDomains.Count & " ----" & vbCrLf
    WScript.Echo "[ Key properties ]"
    WScript.Echo "ID: " & oAppDomain.ID
    WScript.Echo "Site Name: " & oAppDomain.SiteName
    WScript.Echo "Application Path: " & oAppDomain.ApplicationPath
    WScript.Echo
    WScript.Echo "[ Run-time properties ]"
    WScript.Echo "Process ID: " & oAppDomain.ProcessID
    WScript.Echo "Is idle: " & oAppDomain.IsIdle
    WScript.Echo vbCrLf
Next

出力例

出力は次のようになります。

AppDomain Count: 3
---- AppDomain 1 of 3 ----
[ Key properties ]
ID: /LM/W3SVC/1/ROOT
Site Name: Default Web Site
Application Path: /

[ Run-time properties ]
Process ID: 3608
Is idle: False

---- AppDomain 2 of 3 ----
[ Key properties ]
ID: /LM/W3SVC/2/ROOT/ContosoApp
Site Name: ContosoSite
Application Path: /ContosoApp/

[ Run-time properties ]
Process ID: 3608
Is idle: True

---- AppDomain 3 of 3 ----
[ Key properties ]
ID: /LM/W3SVC/1/ROOT/Fabrikam
Site Name: Default Web Site
Application Path: /Fabrikam/

[ Run-time properties ]
Process ID: 2552
Is idle: False

まとめ

この記事では、IIS ワーカー プロセスと AppDomain に関する情報を取得するための基本的な WMI スクリプト手法をいくつか紹介しました。 それらを取得するために WMI InstanceOf メソッドと WQL クエリが使用されました。 提示されたタスクと使用されたメソッドの簡単なレビューを次に示します。

  • ワーカー プロセスに対して現在実行中の要求を表示する: WorkerProcess.GetExecutingRequests
  • すべてのワーカー プロセスの状態を取得する: WorkerProcess.GetState
  • 特定の AppDomain またはすべての AppDomain をアンロードする: AppDomain.Unload