惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

量子位
小众软件
小众软件
S
SegmentFault 最新的问题
人人都是产品经理
人人都是产品经理
博客园 - 【当耐特】
博客园 - 三生石上(FineUI控件)
C
Check Point Blog
S
Schneier on Security
Microsoft Azure Blog
Microsoft Azure Blog
N
Netflix TechBlog - Medium
Engineering at Meta
Engineering at Meta
GbyAI
GbyAI
罗磊的独立博客
有赞技术团队
有赞技术团队
V
V2EX
Y
Y Combinator Blog
博客园 - 叶小钗
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
F
Fortinet All Blogs
W
WeLiveSecurity
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
Stack Overflow Blog
Stack Overflow Blog
The Cloudflare Blog
S
Security @ Cisco Blogs
TaoSecurity Blog
TaoSecurity Blog
MyScale Blog
MyScale Blog
Hugging Face - Blog
Hugging Face - Blog
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
www.infosecurity-magazine.com
www.infosecurity-magazine.com
PCI Perspectives
PCI Perspectives
H
Heimdal Security Blog
Schneier on Security
Schneier on Security
Security Latest
Security Latest
AWS News Blog
AWS News Blog
月光博客
月光博客
Security Archives - TechRepublic
Security Archives - TechRepublic
Recent Announcements
Recent Announcements
Google DeepMind News
Google DeepMind News
博客园 - Franky
Cisco Talos Blog
Cisco Talos Blog
T
Threat Research - Cisco Blogs
M
MIT News - Artificial intelligence
T
Troy Hunt's Blog
N
News and Events Feed by Topic
Cloudbric
Cloudbric
Scott Helme
Scott Helme
云风的 BLOG
云风的 BLOG
Attack and Defense Labs
Attack and Defense Labs

博客园 - 泉子

算法题:求一个序列S中所有包含T的子序列(distinct sub sequence) Django模板输出Dict所有Value的效率问题 笔记:LNK2001不代表链接器真的需要链接相关符号 advapi32.dll kernel32.dll 中的两套注册表API 使用GDI+保存带Alpha通道的图像(续) 使用GDI+保存带Alpha通道的图像 窗口销毁的相关函数与消息,ActiveX控件的销毁 为什么不能将ptr_fun(operator delete)传递给For_Each 两个数之间的最短路径问题 C/C++函数中局部对象的构造与析构时机 四年记——身在中小企业 C++ Const总结 [转载]怎样用VB编写.DLL动态链接库文件 Visual Studio 6.0编译PWLib1.12总结 在Windows上编译PWLib 金山词霸没落了么? SendInput模拟键盘输入的问题 数组变量在取地址时回归:不再是指针 创建用于非Visual C++工具的DLL——VB调用C++ DLL为何必须使用def文件 - 泉子
Windows Restart Manager 重启管理器
泉子 · 2014-08-22 · via 博客园 - 泉子

Restart Manager(以下简称RM)可以减少或避免安装或更新程序所需要的系统重启次数。安装(或更新)过程中需要重启的主要原因是需要更新的某些文件当前正被一些其它程序或服务所使用。RM允许除关键系统服务(Critical System Services)之外的所有程序(或服务)关闭和重启。这将释放正在使用的文件从而使安装得以完成。

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