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
相关文章
相关标签/搜索