Windows Restart Manager 重啓管理器

Restart Manager(如下簡稱RM)能夠減小或避免安裝或更新程序所須要的系統重啓次數。安裝(或更新)過程當中須要重啓的主要緣由是須要更新的某些文件當前正被一些其它程序或服務所使用。RM容許除關鍵系統服務(Critical System Services)以外的全部程序(或服務)關閉和重啓。這將釋放正在使用的文件從而使安裝得以完成。windows

 
RM DLL導出了一組可供安裝包使用的C接口。安裝包能夠向RM註冊安裝過程當中須要被替換的文件列表,隨後,安裝包能夠經過RM來判斷其中哪些文件正在使用;RM能夠關閉並重啓那些佔用了這些文件的程序;安裝包能夠根據被佔用的文件,進程ID,或Windows服務的短名稱來指導RM關閉和重啓應用程序(或服務)。
 
RM自Vista開始提供,Windows Installer V4會自動使用RM,自定義Installer也能夠調用RM API來使用其功能。在不可避免須要重啓的狀況下,Installer能夠藉助RM來規劃什麼時候重啓以最大限度減小對用戶工做流的干擾。
 
對佔用文件的程序,RM如下列順序關閉它們,並在完成更新後,以相反的順序重啓它們:
1. GUI應用程序
2. Console應用程序
3. Windows服務
4. Windows Explorer
 
RM只有獲得調用方容許後纔會關閉程序(或服務)。不支持跨會話進行關閉操做。
 
對於使用Windows Installer V4的安裝包,若是它是交互式的,則其用戶接口應包括MsiRMFilesInUse對話框。
 

1. 在自定義安裝包中使用RM API

全部經過RM API執行的操做都必須與一個session關聯。在一個用戶會話中,最多能夠同時開啓64個RM session。主安裝包(Primary Installer)負責啓動和中止RM session。
 
必要的狀況下,若干個從安裝包(Secondary Installer)能夠加入RM Session並與主安裝包同時運行(在同一進程或不一樣進程中)。加入RM Session須要使用其session key。
 
交互式安裝包的用戶界面應包括一個MsiRMFilesInUse對話框 —— 用於請求用戶關閉應用程序或服務。
 
安裝包不能在調用RM API前禁用文件系統重定向,這意味着在64位Windows上運行的32位安裝包不能註冊「%windir\system32」目錄中的文件。
 

1.1 在主安裝包中使用RM

當在單個安裝包中使用RM時,該安裝包也就是主安裝包。
1. 調用RmStartSession啓動一個RM session,獲得session handle和key。
2. 調用RmRegisterResources註冊資源。RM只能經過註冊的資源來判斷哪些程序和服務須要被重啓。資源能夠是文件名、服務的短名稱,或一個RM_UNIQUE_PROCESS結構。
3. 調用RmGetList得到一個RM_PROCESS_INFO數組,其中包含了全部須要被重啓的進程和服務。
   若是RmGetList返回的lpdwRebootReason不爲0,則表示RM沒法經過重啓來釋放所註冊的資源。在這種狀況下,則須要重啓OS來完成安裝。
   若是RmGetList返回的lpdwRebootReason爲0,則能夠經過調用RmShutdown來關閉佔用資源的程序和服務,而後安裝包能夠進行安裝操做,最後,調用RmRestart來重啓被關閉的程序。
4. 能夠經過RmAddFilter來防止某些程序(或服務)被RM關閉,這稱爲添加一個過濾器。RmRemoveFilter能夠移除一個過濾器,RmGetFilterList則能夠得到當前的過濾器列表。
5. 調用RmEndSession關閉RM session。
 
示例:
DWORD dVal = 0;
DWORD dwSessionHandle = (DWORD) -1;
WCHAR sessKey[CCH_RM_SESSION_KEY+1];
UINT nProcInfo = 100;
UINT nProcInfoNeeded;
UINT nAffectedApps = 0;
RM_PROCESS_INFO rgAffectedApps[100]; //Size depends on # of entries found by RmGetList
DWORD lpdwRebootReason = 0;
DWORD nServices = 1;
LPCWSTR rgsServices[] = { L"iisadmin" };
DWORD nProcs = 0;
DWORD nFiles = 1;
LPCWSTR rgsFiles[] = { L"c:\\windows\\system32\\oleaut32.dll" };
 
// Starting Session
dVal = RmStartSession( &dwSessionHandle, 0, sessKey );
if (dVal != ERROR_SUCCESS)
goto RM_END;
 
// Register items
dVal = RmRegisterResources(
dwSessionHandle,
nFiles, rgsFiles, // Files
nProcs, NULL, // Processes
nServices, rgsServices ); // Services
if (dVal != ERROR_SUCCESS)
goto RM_END;
 
// Getting affected apps
dVal = RmGetList(
dwSessionHandle,
&nProcInfoNeeded,
&nAffectedApps, rgAffectedApps, &lpdwRebootReason );
if (dVal != ERROR_SUCCESS)
goto RM_END;
 
//Results of RmGetList can be presented & interpreted 
//by the user for determining subsequent action.
 
// Shut down apps
dVal = RmShutdown( dwSessionHandle, 0, NULL );
if (dVal != ERROR_SUCCESS)
goto RM_END;
 
//An installer can now replace the files.
 
// Restart apps
dVal = RmRestart( dwSessionHandle, 0, NULL );
if (dVal != ERROR_SUCCESS)
goto RM_END;
 
 
RM_END:
 
if (rgAffectedApps)
{
delete [] rgAffectedApps;
rgAffectedApps = NULL;
}
 
if (dwSessionHandle != -1)
{
// Clean up session
dVal = RmEndSession( dwSessionHandle );
dwSessionHandle = -1;
}
 

1.2 在從安裝包中使用RM

1. 想辦法從主安裝包中獲取RM session key,調用RMJoinSession來加入session。主安裝包和從安裝包必須運行在相同的用戶上下文中。
2. 使用RmRegisterResources註冊資源;使用RmGetList能夠獲取佔用資源的程序列表;
3. 能夠調用RmShutdown(存疑!若是可以調用的話,那會不會屢次調用RmShutdown的可能?)。
4. 主安裝包和從安裝包調用RmEndSession(存疑,不知道是指任何一方調用便可仍是雙方都須要調用一次)。
 
示例:
 
    DWORD dVal = 0;
    DWORD dwSessionHandle = (DWORD) -1;
    WCHAR sessKey[CCH_RM_SESSION_KEY+1]; //Primary installer session key.
    DWORD nServices = 1;
    LPCWSTR rgsServices[] = { L"iisadmin" };
    DWORD nProcs = 0;
    DWORD nFiles = 1;
    LPCWSTR rgsFiles[] = { L"c:\\windows\\system32\\oleaut32.dll" };
 
// Secondary installer obtains the session key from the
// primary installer & uses it to join the session.
 
    // Joining Session
    dVal = RmJoinSession( &dwSessionHandle, sessKey );
    if (dVal != ERROR_SUCCESS)
        goto RMSUB_END;
 
    // Register items. The Secondary installer is only allowed to register resources
    // and cannot perform other Restart Manager operations.
    dVal = RmRegisterResources(
        dwSessionHandle,
        nFiles, rgsFiles,            // Files
        nProcs, NULL,            // Processes
        nServices, rgsServices );        // Services
 
    if (dVal != ERROR_SUCCESS)
        goto RMSUB_END;
 
RMSUB_END:
    if (dwSessionHandle != -1)
    {
        // Clean up session
        dVal = RmEndSession( dwSessionHandle );
        dwSessionHandle = -1;
    }
 
 
來自:ms-help://MS.MSDNQTR.v90.chs/rstmgr/rstmgr/using_restart_manager.htm
相關文章
相關標籤/搜索