2

我正在创建一个 WIX 安装程序引导程序(DisplayInternalUI="yes"在 msipackage 上),但是当同时发生其他安装时它会挂起。

如果我使用 msiexec 自行运行 MSI 文件,我会收到一条 Windows 安装程序错误 "Another installation is in progress"消息(即 1500 MSI 错误消息)——我认为这是挂起我的安装。

因此,我正在做的是查看是否可以_MSIExecute mutex在用户按下安装按钮之后(即在 之前ProgressDlg)锁定。如果我可以锁定 Mutex,则没有其他安装正在进行 - 因此继续安装(即执行阶段)是安全的。如果不是,安装程序会显示取消按钮(并且没有其他按钮) - 因此安装将不会继续。

我想知道是否有办法防止"Another installation is in progress"错误消息(和其他消息)挂起安装程序。

4

3 回答 3

1

来自 serverfault.com 的更简单解释


没有 MSI 并发:为什么“同时”发生其他安装 - 或者换句话说同时发生?当谈到 WiX Burn 引导程序时,我并没有受过太多的便盆训练,但我想知道有问题的 MSI 是否包含任何启动其他 MSI 安装的自定义操作?这对于 MSI 软件包是不允许的。您不能同时InstallExecuteSequences运行两个并发。因此,您不能从InstallExecuteSequence. 有些人试图从InstallUISequence,由于许多原因,这也是非常不可取的 - 一方面,当安装程序以静默模式运行时,它根本不会运行。如果您为自定义操作设置检查退出代码以及类似的东西,我还怀疑提升的潜在问题和意外的设置失败。它总是置换。要记住的基本经验法则是:自定义操作绝不能启动其他 MSI 安装。WiX Burn 引导程序基本上专门用于允许您按顺序运行 MSI 文件 - 而不是同时运行 - 但它也更多:它是一个组合引导程序、链接器、下载器等......

互斥锁:强词夺理,但如果您知道什么对您有好处,您将远离 MSI 互斥锁。救你自己!:-)。MSI是一种反击技术,如果你参加战斗,你将真正与风车战斗。这就是我能说的警告你的全部内容。除非您遵循基本规则,否则确实无法处理,在这种情况下,一次运行一个安装程序。不过,WiX 家伙可以处理它 - 留给他们 - 并使用他们的工具属性(WiX Burn)。尽管我不清楚技术细节,但它们肯定会实现您所描述的功能(检查系统是否已准备好安装)。

挂起安装:也有可能您的系统上存在需要撤消的挂起安装,然后才能安装 MSI 文件。您可以尝试安装另一个 MSI 文件并查看它是否正常运行吗?我不是 100% 确定这是正确的链接,但您也可以尝试:修复阻止程序被安装或删除的问题

于 2018-05-03T18:42:54.667 回答
0

更新:关于_MSIExecute Mutex。有关使用QueryServiceStatusEx检查当前 Windows Installer 状态的技术信息,请参阅底部。Heath Stewart 提出了另一种方法(示例 C++ 代码)。

此外,一些预先存在的相关答案:


首先是对手头问题的一些评论(虚拟更新和等待重新启动):

Windows 更新进行中:如果您正在处理在后台执行 Windows 更新并且 MSI 安装不会运行的情况,那么 WiX Burn 可能会在检查系统重启是否挂起时挂起。我以前见过这样的问题(请参阅下面的“技术问题”)。

真正的修复:如果是这种情况,唯一真正的修复是让 Windows 更新完成,然后重新启动并保持新的虚拟机状态,然后安装你的包。这是唯一明智的解决方法-在我看来。不是你想听到的:-)。

肮脏的“修复”:我想你也可以停止 Windows 更新服务以阻止安装 Windows 更新,但我猜如果你这样做,你的虚拟机最终会感染恶意软件,然后你就会遇到可怕的情况,你可能不小心将恶意软件保留在您的虚拟机中,然后定期复活,并且不会被安全软件(通常不会扫描虚拟机)检测到。由于难以根除和发现它(与只读媒体上的恶意软件和检入源代码控制系统的恶意软件处于同一联盟),这可能是现有的最糟糕的恶意软件向量之一摆脱它)。善意的建议(从未想要的那种——我们都生活在现实中):请不要在没有适当考虑后果的情况下禁用虚拟机上的 Windows 更新。在整个公司范围内,我永远不会允许这样的事情——仅作为具有超出正常测试需求的特定用户的例外情况——并且虚拟设备将被强制定期检查恶意软件。这提醒我检查哪些安全软件可以正确扫描离线虚拟机。更多的研究要做。有趣的是,写 stackoverflow 的答案总是教会我我自己做得不好的地方!不好 :-)。

技术问题:关于技术问题。我之前看到过 WiX Burn 挂起的问题,因为它专门试图避免在正在更新的系统上安装:

也许检查链接答案中的那个小 VBScript(或您想要的任何语言的等效 COM 调用)是否会告诉您系统是否尚未准备好安装?

简单的黑客?:未验证,但也许您可以检查注册表项/值(不确定这是一个值还是一个键):HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Installer : InProgress- 据我所知,它应该存在以指示活动的 Windows Installer 会话。我认为这比尝试处理互斥锁和其他操作系统基础要好。

奇怪的是,我不知道有任何MSI API 调用会告诉您是否有活动的安装会话(互斥集)。我唯一能看到的是一个 Win32 函数(即不是 COM 自动化):MsiBeginTransaction(最近添加到 MSI API,仅限 4.5 版本)。

还有这个:MSDN: _MSIExecute Mutex - 建议使用QueryServiceStatusEx并检查值是否dwControlsAcceptedSERVICE_ACCEPT_SHUTDOWN. 我从未尝试过。坦率地说,我会尝试检查上面的注册表项。

于 2018-05-04T13:53:02.037 回答
0

如果 Windows 更新是您主要关心的问题,那么您将使用 Windows 更新代理 API 来检测是否有正在进行的更新。我认为在尝试安装 MSI 之前,您需要从自己的引导程序运行它。一般的 C++ 思路如下:

#include "stdafx.h" 
#include <wuapi.h> 
#include <iostream> 
#include <ATLComTime.h> 
#include <wuerror.h> 
using namespace std; 

int _tmain(int argc, _TCHAR* argv[]) 
{ 
HRESULT hr; 
hr = CoInitialize(NULL); 
IUpdateSession* iUpdate; 
IUpdateSearcher* searcher; 
IUpdateInstaller* iInstaller; 
ISearchResult* results; 
BSTR criteria = SysAllocString(L"IsInstalled=1 or IsHidden=1 or 
IsPresent=1"); 
hr = CoCreateInstance(CLSID_UpdateInstaller, NULL, 
CLSCTX_INPROC_SERVER, IID_IUpdateInstaller, (LPVOID*)&iInstaller); 
VARIANT_BOOL Busy; 
hr = iInstaller->get_IsBusy(&Busy); 

ETC

基本上 IsBusy 属性会告诉您是否正在进行更新。

https://msdn.microsoft.com/en-us/library/windows/desktop/aa386502(v=vs.85).aspx

这里的讨论线程:

http://windows-installer-xml-wix-toolset.687559.n2.nabble.com/Windows-Updates-either-pending-or-running-causes-our-installs-to-fail-td7598536.html

还有一个更好的代码示例。我不知道托管代码接口或内置 WiX 支持。

于 2018-05-06T20:22:39.700 回答