MSI / WIX:如何(自行)更新正在运行的服务

时间:2016-08-15 13:09:00

标签: windows wix windows-installer

我必须编写一个自动更新服务,在我们的客户端PC上更新我们公司的应用程序。要更新的应用程序之一是更新程序本身。我使用WIX创建的MSI包部署所有应用程序。

然后该服务使用“msiexec.exe / q / i”进行扫描以启动静默安装。

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

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

1 个答案:

答案 0 :(得分:2)

感谢您提供的意见,以下是我提出的建议:

我正在使用具有MajorUpgrade支持的WIX安装程序和ServiceInstall元素来安装新服务。这将导致MSI停止服务并升级安装。

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

基本上我们需要打电话:

msiexec /package path_to_msi /quiet

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

// 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";

现在,我们开始这个过程:

// 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");

我们已经完成了。

安装程序现在将发出停止服务信号,确保正确处理!

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

完成; - )

如果有人需要更多细节,请随便提出。