我在DotNet Core中构建了一个与Peter Kottas WindowsServer nuget(https://github.com/PeterKottas/DotNetCore.WindowsService)一起安装的Windows服务。要安装服务,您必须发布代码,在任何地方部署它,运行具有管理员权限的cmd提示符,将目录移动到已部署的代码并执行以下行:" MyService操作:安装"
<CustomAction Id="CallCmd" Value="[SystemFolder]cmd.exe" Directory="MYSERVICE" />
<CustomAction Id="MoveDirectory" Directory="MYSERVICE" ExeCommand="cd C:\Program Files (x86)\MYCOMPANY\MYSERVICE"/>
<CustomAction Id="CA_InstallMyService" Directory="MYSERVICE" ExeCommand="MyService action:install" />
<InstallExecuteSequence>
<Custom Action="CallCmd" After="PublishProduct" />
<Custom Action="MoveDirectory" After="CallCmd" />
<Custom Action="CA_InstallMyService" After="MoveDirectory" />
</InstallExecuteSequence>
在Orca中查看它似乎按正确的顺序排列,因为这些说明在创建之前无法浏览到该文件夹。
但是,在执行MSI并单击&#34;安装&#34;它会中途通过,失败并在安装过程中向后运行。 (我已经尝试过观看&#34; Program Files(x86)&#34;目录,甚至看不到我的Product.wxs中创建的目录文件夹结构。
在事件查看器中进行一些挖掘会显示此错误:
错误1721.此Windows Installer程序包存在问题。一个 无法运行此安装完成所需的程序。 请联系您的支持人员或包装供应商。行动: MoveDirectory,位置:C:\ WINDOWS \ SysWOW64 \ cmd.exe \,命令:cd C:\ Program Files(x86)\ MYCOMPANY \ MYSERVICE
答案 0 :(得分:4)
考虑到Windows Installer(和WiX)内置支持安装服务,以及启动和停止它们以便可以替换或卸载它们,这不是一个好的设计范例。该nuget可能是一个有趣的服务模型,但启动,停止和部署不是使用Windows Installer安装服务的推荐方法。根本不需要运行代码。
请参阅WiX ServiceInstall和ServiceControl元素。
答案 1 :(得分:0)
您必须将CustomActions标记为Execute="Deferred"
InstallExecuteSequence分为两部分,第一部分是计划阶段,它计算出它将要做什么,第二部分是运行刚刚在高架环境中制作的计划脚本。
如果您在InstallExecuteSequence中规划了一些自定义操作但没有将它们标记为延迟,则它们将在执行序列的计划部分期间运行,这是在安装任何文件之前,因为InstallFiles标准操作需要提升并且发生在序列的第二部分运行计划脚本时。
通常,当您需要运行需要安装的属性值的提升自定义操作时,才使用此模式。您可以安排两个自定义操作,一个是延迟操作,一个是非自定义操作,其中非延迟操作实际上设置了一些特殊值,以便延迟操作在执行时使用。
我之前没有使用过CustomActions的Directory属性,因此您可能需要重新编写其中一些操作才能使它们正常工作,我不确定。
如果您需要更改自定义操作的工作方式,那么另一个问题的答案应该有助于解释延迟自定义操作如何在运行时从安装程序的属性获取值。
WiX - commit more than one Property to deferred Custom Action
答案 2 :(得分:0)
虽然我同意PhilDW提供的答案,处理Windows服务的最理想方式是使用WiX提供的功能,这里的问题是DotNetCore设计为多平台,目前不包含任何用于Windows服务的.Net标准程序集,因此我使用Peter Kottas的nuget包来实现Windows服务。解决这个问题的方法可能是使用docker容器 - 但是,这超出了当前版本的范围,所以这就是我如何解决这个问题:
TLDR:当用户退出应用程序时,我通过CustomAction调用了install命令。这需要管理权限,因此在MSI中设置了适当的标志,并且始终使用Bootstrapper(Burn)应用程序运行MSI,以便以用户友好的方式提供这些权限。
首先,我创建了一个自定义操作,以在命令提示符中触发安装命令。
<CustomAction Id="CA_InstallService" Directory="INSTALLDIR" Return="ignore" ExeCommand="cmd /s /c "MyService action:install start-immediately:false"" />
然后我创建了一个新的WiX UI元素。它的WixUI_Mode是“FeatureTree”,我在退出对话框中添加了一个额外的“DoAction”属性,以便在用户单击Finish时调用它。
<Publish Dialog="ExitDlg" Control="Finish" Event="DoAction" Value="CA_InstallService" Order="990"></Publish>
安装程序需要管理员权限来调用它,因此在Product.wxs文件中将Package元素的“InstallPrivileges”属性设置为“elevated”。现在,如果您通过命令提示符使用admin权限调用msi,则会成功调用“action:install”。 或者您可以创建引用wix安装程序的引导程序项目,并在“MsiPackage”上的Bundle.wxs文件中将“ForePerMachine”属性设置为“yes”。
请参阅我自己的一些松散相关的旁注的评论。