2016-08-15 86 views
3

我必须编写一个自动更新服务,以在我们的客户端PC上更新我们公司的应用程序。更新的一个应用程序是更新程序本身。我使用WIX创建的MSI包部署所有应用程序。MSI/WIX:如何(自我更新)正在运行的服务

该服务然后用“msiexec.exe/q/i”跨过一个进程来启动无提示安装。

这适用于其他产品,但是当我想更新正在运行的服务时,该服务是启动调用安装程序的进程的服务。因此,我正在尝试更新正在运行的进程。

我该怎么办? “分叉”安装程序并退出服务?使用一些聪明的Windows内置方法?

解决方案

(见下文)

+1

最安全的方法可能是临时安装第二个服务来代表您的服务进行升级。但实际上,启动一个子进程应该也是一样,除了边缘情况,例如机器在错误时刻重启。 (可能会有更聪明的解决方案涉及Windows Installer,因此其他人可能有更好的主意。) –

+0

这与自定义卸载过程需要卸载自身的问题相同。一些可行的方法是将一个小的外部代码文件(不需要有exe后缀)复制到临时文件夹和CreateProcess服务中。它可能有代码等待你完成更新之前完成。将它置于临时状态通常不是问题,因为人员和流程将其清除。 – PhilDW

+0

我不认为msiexec关心哪个进程创建它。在任何情况下,如果MSI的操作停止并替换服务,然后重启服务,则应该没有问题 - 只要该服务在预期的时间范围内成功停止,即可响应停止信号。更新正在运行的服务很常见。请用一些代码来编辑问题以帮助显示问题。 –

回答

2

感谢您的输入,这里是我想出了:

我使用与MajorUpgrade支持维克斯安装程序和ServiceInstall元素安装新的服务。这将导致MSI停止服务并升级安装。

现在,要从内更新服务,我需要异步启动安装程序,然后允许停止正在运行的服务。

基本上,我们需要调用:

msiexec /package path_to_msi /quiet 

由于CreateProcess的需要的完整路径的可执行文件,我用SHGetKnownFolderPath检索系统

// note: FOLDERID_SystemX86 will return 32 bit version of system32 regardless of application type 
PWSTR str = nullptr; 
if (SHGetKnownFolderPath(FOLDERID_SystemX86, KF_FLAG_DEFAULT, NULL, &str) != S_OK) 
    throw std::runtime_error("failed to retrieve FOLDERID_SystemX86"); 
std::string exe = ...path to msiexec...; 
std::string options = " /package \"path_to_msi\" /quiet"; 

现在的SYSTEM32路径,我们启动这一进程:

// start process 
STARTUPINFO si; 
PROCESS_INFORMATION pi; 

ZeroMemory(&si, sizeof(si)); 
si.cb = sizeof(si); 
ZeroMemory(&pi, sizeof(pi)); 

if (!CreateProcess(exe.c_str(),  // application name 
       options.c_str(),  // Command line options 
       NULL,     // Process handle not inheritable 
       NULL,     // Thread handle not inheritable 
       FALSE,    // Set handle inheritance to FALSE 
       0,     // No creation flags 
       NULL,     // Use parent's environment block 
       NULL,     // Use parent's starting directory 
       &si,     // Pointer to STARTUPINFO structure 
       &pi))     // Pointer to PROCESS_INFORMATION structure 
    throw std::runtime_error("CreateProcess failed"); 

我们完成了。

安装程序现在将指示服务停止,请确保正确处理!

新服务将被安装,并希望在几秒钟内恢复运作。

完成;-)

如果有人需要更多的细节,只需要问。