WiX - 试图找出安装顺序
我正在安装一个大型应用程序,其中一部分是一个名为“DbUpdateManager”的自定义编写工具,用于针对我们的目标数据库批量执行 SQL 脚本。
现在,WiX 2.x 安装可以工作,但它有一个缺陷:在安装过程中,我还安装了一些 Windows 服务,可以选择立即启动这些服务。 但是,如果 DbUpdateManager 尚未运行,这些操作将会失败。
所以我想要完成的是:
- 从 MSI 安装 DbUpdateManager 和我的服务 在
- 任何服务启动之前运行 DbUpdateManager
我当前的 WiX 源看起来像这样:
<Directory Id='INSTALLDIR' Name='DbUpdMgr' LongName='DbUpdateManager' >
<!-- DbUpdateManager component with the necessary files -->
<Component Id='DbUpdateManagerComponent' Guid='...' DiskId='1'>
<File Id='DbUpdateManagerFile' LongName='DbUpdateManager.Wizard.exe'
Name='DbUmWz.exe' src='DbUpdateManager.Wizard.exe' KeyPath='no' />
</Component>
<!-- Component to install one of my Windows services -->
<Component Id='InstallServiceComponent' Guid='...' DiskId='1'>
<File Id='InstallServiceFile' LongName='MyService.exe'
Name='MyServic.exe' src='MyService.exe' KeyPath='yes'/>
<ServiceInstall Id='InstallMyService' Name='MyService'
Description='My Service' ErrorControl='normal'
Start='auto' Type='ownProcess' Vital='yes' />
<ServiceControl Id='UninstallMyService' Name='MyService'
Remove='uninstall' Wait='yes' />
</Component>
<!-- Feature for the DbUpdateManager referencing the above component -->
<Feature Id='DbUpdateManager' ConfigurableDirectory='INSTALLDIR'
AllowAdvertise='no' Description='DbUpdateManager' Level='1'
Title='Database Update Manager'>
<ComponentRef Id='DbUpdateManagerComponent'/>
</Feature>
<!-- Custom action for running DbUpdateManager -->
<CustomAction Id='RunDbUpdateManagerAction' FileKey='DbUpdateManagerFile'
ExeCommand='' Return='asyncWait' />
<!-- Calling the custom action in the install sequence -->
<InstallExecuteSequence>
<RemoveExistingProducts After='InstallInitialize' />
<Custom Action='RunDbUpdateManagerAction'
After='InstallFinalize'>&DbUpdateManager=3</Custom>
我继承了这个 WIX,并且它有效 - 但正如我所说 - DbUpdateManager 在该过程中调用得太晚(仅“After=InstallFinalize”),因此服务一开始将无法正常启动(当您手动重新启动它们时,第二次运行良好) DbUpdateManager 运行后)。
我稍微浏览了一下 MSI 文档,发现了一个名为“StartServices”的好步骤,所以我的直觉是将我的自定义操作调用更改为:
<InstallExecuteSequence>
<Custom Action='RunDbUpdateManagerAction'
Before='StartServices'>&DbUpdateManager=3</Custom>
不幸的是,在这种情况下,什么也没有发生 - DbUpdateManager 永远不会被调用。 ..
有什么想法吗? 调试 MSI/WiX 的东西真的非常棘手,我似乎再也见不到树木了……
谢谢! Marc
编辑:“RunDbUpdateManagerAction”被放置在我的 MSI 中 InstallExecuteSequence 表中的正确位置 - 在 InstallServices 之后和 StartServices 之前 - 但它不起作用...... DbUpdateManager (一个 Winforms 实用程序)确实 在安装过程中没有出现:-(
编辑2:现在我的操作似乎已在正确的时间执行 - 不幸的是,我只是没有看到我的向导:-(我看到的是错误代码“返回值 1631”,这意味着“MSI 服务无法启动” - wtf ???
MSI (s) (2C:D8) [20:53:36:383]:执行操作:RunDbUpdateManagerAction 操作 20:53:36:RunDbUpdateManagerAction。 操作于 20:53:36 开始:RunDbUpdateManagerAction。 MSI (s) (2C:D8) [20:53:36:383]:执行操作:StartServices 操作 20:53:36:启动服务。 服务正在启动中 操作于 20:53:36 开始:StartServices。 操作于 20:53:36 完成:RunDbUpdateManagerAction。 返回值1631。
I'm installing a large app, and part of it is a custom written tool called "DbUpdateManager" to mass execute SQL scripts against our target database.
Right now, the WiX 2.x install works - but it has one flaw: during install, I also install a couple of Windows services, which can be optionally started right away. Those however will fail, if the DbUpdateManager hasn't been run yet.
So what I'm trying to accomplish is this:
- Install DbUpdateManager and my services from my MSI
- Run DbUpdateManager BEFORE any of the services start up
My current WiX source looks something like this:
<Directory Id='INSTALLDIR' Name='DbUpdMgr' LongName='DbUpdateManager' >
<!-- DbUpdateManager component with the necessary files -->
<Component Id='DbUpdateManagerComponent' Guid='...' DiskId='1'>
<File Id='DbUpdateManagerFile' LongName='DbUpdateManager.Wizard.exe'
Name='DbUmWz.exe' src='DbUpdateManager.Wizard.exe' KeyPath='no' />
</Component>
<!-- Component to install one of my Windows services -->
<Component Id='InstallServiceComponent' Guid='...' DiskId='1'>
<File Id='InstallServiceFile' LongName='MyService.exe'
Name='MyServic.exe' src='MyService.exe' KeyPath='yes'/>
<ServiceInstall Id='InstallMyService' Name='MyService'
Description='My Service' ErrorControl='normal'
Start='auto' Type='ownProcess' Vital='yes' />
<ServiceControl Id='UninstallMyService' Name='MyService'
Remove='uninstall' Wait='yes' />
</Component>
<!-- Feature for the DbUpdateManager referencing the above component -->
<Feature Id='DbUpdateManager' ConfigurableDirectory='INSTALLDIR'
AllowAdvertise='no' Description='DbUpdateManager' Level='1'
Title='Database Update Manager'>
<ComponentRef Id='DbUpdateManagerComponent'/>
</Feature>
<!-- Custom action for running DbUpdateManager -->
<CustomAction Id='RunDbUpdateManagerAction' FileKey='DbUpdateManagerFile'
ExeCommand='' Return='asyncWait' />
<!-- Calling the custom action in the install sequence -->
<InstallExecuteSequence>
<RemoveExistingProducts After='InstallInitialize' />
<Custom Action='RunDbUpdateManagerAction'
After='InstallFinalize'>&DbUpdateManager=3</Custom>
I inherited this WIX, and it works - but as I said - the DbUpdateManager gets called too late in the process (only "After=InstallFinalize") and thus the services will fail to start up properly at first (the run fine the second time around when you restart them manually after DbUpdateManager has run).
I poked around the MSI documentation a bit and found a nice step called "StartServices", so my hunch was to just change my calling the custom action to this:
<InstallExecuteSequence>
<Custom Action='RunDbUpdateManagerAction'
Before='StartServices'>&DbUpdateManager=3</Custom>
Unfortunately, in this case, nothing at all happens - DbUpdateManager NEVER gets called....
Any ideas why? Debugging the MSI/WiX stuff is really really tricky, and I can't seem to see the forest for the trees anymore....
Thanks!
Marc
EDIT: The "RunDbUpdateManagerAction" is placed in the right position in the InstallExecuteSequence table in my MSI - right AFTER InstallServices and just BEFORE StartServices - and yet it doesn't work.... DbUpdateManager (a Winforms utility) does not show up during installation :-(
EDIT 2: now my action appears to be executed and at the right time - unfortunately, I'm just not seeing my wizard :-( What I'm seeing is an error code "return value 1631" which means something like "MSI Service could not be started" - wtf ???
MSI (s) (2C:D8) [20:53:36:383]: Doing action: RunDbUpdateManagerAction
Action 20:53:36: RunDbUpdateManagerAction.
Action started at 20:53:36: RunDbUpdateManagerAction.
MSI (s) (2C:D8) [20:53:36:383]: Doing action: StartServices
Action 20:53:36: StartServices. Services are being started
Action started at 20:53:36: StartServices.
Action finished at 20:53:36: RunDbUpdateManagerAction. Return value 1631.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
好吧,在每个回复者的帮助下,并通过查阅网络上的一些 WiX 教程和帮助页面,我终于让它工作了。 MSI 安装程序的内容不容易弄清楚和学习......
基本上,我将自定义操作的执行更改为“延迟”(如 Rob 的建议),并将执行顺序中的点移动到“之后=安装文件”。 我还更改了&lt;自定义&gt;中的条件 标记为“未安装”,这在我的场景中似乎工作得很好。
与 Rob 担心的相反,数据库更新管理器及其 UI 通过这种方式表现得非常好,并且更新数据库的过程现在在我们的任何服务(依赖于数据库)启动之前完成。
期待 WiX 3.0(及其未来)的完整 RTM 版本!
感谢大家 - 不幸的是,我只能接受一个答案 - 所有人都应得的。
马克
Well, I finally got it working - with a bit of help from everyone who responded, and by consulting some of the WiX tutorials and help pages out there on the web. MSI installer stuff isn't easy to figure out and learn......
Basically, I changed execution of my custom action to "deferred" (as suggested by Rob) and I moved the point in the sequence where it gets executed to "After=InstallFiles". I also changed the condition in the <Custom> tag to "NOT Installed" which seems to work just fine in my scenario.
Contrary to Rob's fear, the Db Update Manager and its UI come up quite nicely this way, and the process of updating our database is now completed before any of our services (that depend on the database) get started.
Looking forward to a full RTM release of WiX 3.0 (and its future) !
Thanks to everyone - unfortunately, I could only accept one answer - all would have deserved it.
Marc
看来您的 CustomAction 取决于正在安装的“DbUpdateManagerFile”。 这意味着您的 CustomAction 需要在 InstallFiles 执行之后安排。 请记住,InstallExecuteSequence 有两次传递。 首先,执行“立即”(或“计划”或“脚本生成”)操作来构建事务日志(又名:“安装脚本”)。 其次,执行事务日志中的“延迟”操作。
现在,您的 CustomAction 是“立即”(默认),因此它尝试在文件实际复制到计算机之前运行。 InstallFiles 操作位于脚本中的 CustomAction 之前,但尚未执行。
因此,您需要将 CustomAction 标记为“延迟”,以使其在安装文件后运行。
注意:您可能无法显示来自延迟 CA 的 UI。 我不确定你的这个工具是否应该显示用户界面。
PS:抱歉,如果我没有解释清楚,这是漫长的一天。
It appears that your CustomAction depends on the 'DbUpdateManagerFile' being installed. That means that your CustomAction needs to be scheduled after InstallFiles executes. Remember there are two passes to the InstallExecuteSequence. First, the "immediate" (or "scheduled" or "script generation") actions are executed to build the transaction log (aka: "install script"). Second, the "deferred" actions in the transaction log are executed.
Right now your CustomAction is "immediate" (the default) so it is trying to run before the files are actually copied to the machine. The InstallFiles action is in the script before your CustomAction but it hasn't been executed yet.
So, you need to mark your CustomAction "deferred" to get it to run after your files are installed.
Note: you are not probably not able to show UI from a deferred CA. I wasn't sure if this tool of yours was expected to show UI.
PS: sorry if I didn't explain that well, it's been a long day.
尝试获取安装的日志文件,并查找其中的序列顺序以及执行自定义操作的条件值
在命令行中使用:
msiexec /i [msiname] /l*v [文件名]
编辑:阅读您的评论后,请查看此页面 在这里你可以尝试在条件EDIT2中添加NOT INSTALLED
:我发现这个页面 搜索您的错误号 1631
Try getting a log file of the Installation, and look for the sequence order in there and the value of the condition to perform the Custom Action
Use this in the command line:
msiexec /i [msiname] /l*v [filename]
EDIT: After reading your comment have a look at this page here you could try to add NOT INSTALLED in the condition
EDIT2: I found this page Search for your error Number 1631
您可以在 Orca 中打开 .msi 并查看 InstallExecuteSequence 表查看事情实际发生的顺序。这可以让您很好地了解实际发生的情况。
You can open the .msi in Orca and look at the InstallExecuteSequence table to see what order things are actually happening in. This may give you a good idea of what's actually happening when.