共用方式為


使用 WMI 管理 IIS 7 中的背景工作進程和 AppDomains

由 Tim Ammann 提供

WMI 腳本可讓您在 IIS 中管理背景工作進程和應用程式域 (AppDomains) 。 IIS 背景工作進程是由 Windows 進程啟用服務 (WAS) 所繁衍,並由W3wp.exe執行。 背景工作進程可以包含通常建立的 AppDomains,以回應 .aspx 頁面的要求。

本文說明如何完成,只要使用幾行 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.Type appcmd 新增 backup backupName 來備份ApplicationHost.config檔案,其中 backupName 是您為備份指定的名稱。 具有您指定之備份名稱的 %Windir%\system32\inetsrv\backup 目錄將會建立在目錄底下。 如果您沒有指定名稱,appcmd 將會使用目前的日期和時間自動產生目錄名稱。

工作者處理序

本節說明如何擷取 Web 服務器上每個背景工作進程目前執行的要求。 然後,您將瞭解如何顯示其所屬的每個背景工作進程 PID、狀態和應用程式集區。

取得執行要求

IIS 的一項令人興奮的新功能是能夠查看目前正在背景工作程式中執行的要求。 您可以使用 WorkerProcess.GetExecutingRequests 方法來執行此動作。

WorkerProcess.GetExecutingRequests 方法會以快照方式報告在方法執行時執行的要求。 因為大部分的要求會非常快速地執行,所以您可能不容易使用網頁瀏覽器手動測試方法。 基於這個理由,您只會針對此目的建立網頁。

使用記事本將下列文字放入文字檔中。 然後,使用 Name Sleep.aspx 儲存檔案。

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

將 Sleep.aspx 檔案放在預設網站的內容目錄中: %systemdrive%\inetpub\wwwroot

您所建立的 Sleep.aspx 檔案會強制要求網頁執行 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檔案的目錄。

執行腳本之前,請先輸入 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。 ApplicationPool 屬性代表背景工作進程所屬的應用程式集區。 PID 屬性包含可唯一識別背景工作進程的進程識別碼。

您可以使用下列程式碼來列出每個背景工作進程 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 頁面的要求,或任何使用 Managed 程式碼的頁面。 使用 WMI 卸載和列舉 AppDomains 很簡單,本節說明如何同時執行兩者。

卸載特定 AppDomain

AppDomain 在 IIS 7 和更新版本中的卸載運作方式與 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。 不過,其中一個可能就足以供您之用。

此外,AppDomain ID 屬性不是數位,而是如下所示的路徑:

/LM/W3SVC/1/ROOT

The "1" in the path listed is the Site ID (by default, 1 corresponds to the default Web site.) If you must generate a list of your server's AppDomains and their properties first, see the "Enumerating AppDomains" section later in this article.

下一個腳本會卸載名為 「Northwind」 的 AppDomain。腳本會逐一查看可用的 AppDomains,直到找到具有相符 ApplicationPath 的 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

卸載所有 AppDomains

卸載伺服器上的所有 AppDomains 更輕鬆:您只要擷取它們、逐一查看它們,然後依序卸載每一個。

下列範例會卸載 IIS Web 服務器上的所有應用程式域。 請注意,WQL (WQL 是 WMI 版本的 SQL) 如何用來擷取 AppDomains。

將程式碼複製到記事本,並以名稱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

作為 WQL 查詢語法的替代方案,您可以使用 WMI InstancesOf 方法,就像您稍早使用 WorkerProcess 一樣:

Set oAppDomains = oWebAdmin.InstancesOf("AppDomain")

列舉 AppDomains

您可以使用與先前腳本類似的方法來顯示所有目前執行中的 AppDomains 及其屬性。 以下是 AppDomain 屬性的清單:

  • ApplicationPath
  • 識別碼
  • IsIdle
  • PhysicalPath
  • ProcessId
  • SiteName

下列腳本顯示每個 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

結論

本文說明一些基本的 WMI 腳本技術,可用來擷取 IIS 背景工作進程和 AppDomains 的相關資訊。 WMI InstanceOf 方法和 WQL 查詢可用來擷取它們。 以下是所呈現工作的簡短檢閱,以及所使用的方法:

  • 檢視目前正在執行的背景工作進程要求: WorkerProcess.GetExecutingRequests
  • 取得所有背景工作進程的狀態: WorkerProcess.GetState
  • 卸載特定的 AppDomain 或所有 AppDomains:AppDomain.Unload