4

So I am trying to install an application built using TopShelf, the application itself runs well and has no problems. The problem I run into is when I try to install the service. The TopShelf service is installed (from an administrator command line) using the myapp.exe install <options> instruction. I have wrapped the instruction in a custom action (see below). This runs, in that I can see a black box pop-up on install. The service fails to install, however. When I run the msi install from an administrator command line, the service installs correctly. I have included all Administrator related parameters in the WiX file (see below also). I am completely out of ideas and in need of help, can anyone see anything in the WiX files or does anyone have any idea what is preventing the service from installing?

What I have tried:

Topshelf - Custom Action in Wix Not Executing

Add Coffee and Shake Well - TopShelf

I have also tried wrapping the call to the topshelf app in a separate WiX custom Action project to execute and this also fails for the same reason.

<Product Id="*" Name="PackageName"
         Language="1033"
         Version="1.0.0.0"
         Manufacturer="Manufacturer"
         UpgradeCode="e7780903-3cf9-4ecc-b65a-45bc18b500df">
  <Package InstallerVersion="200" 
           Compressed="yes" 
           InstallScope="perMachine"  
           InstallPrivileges="elevated" 
           Platform="x64" />

  <Property Id="MSIUSEREALADMINDETECTION" Value="1" />

  <MajorUpgrade AllowSameVersionUpgrades="yes"
              DowngradeErrorMessage="A newer version of [ProductName] is already installed." 
              Schedule="afterInstallInitialize" />
  <MediaTemplate  EmbedCab="yes"/>

  <Feature Id="ProductFeature" Title="FeatureName" Level="1">
    <ComponentGroupRef Id="ProductComponents" />
  </Feature>

  <CustomAction Id="InstallService" 
                FileKey="MyApp.exe" 
                ExeCommand="install" 
                Impersonate="yes"
                Execute="immediate" />
  <CustomAction Id="StopService" 
                FileKey="MyApp.exe" 
                ExeCommand="stop"
                Execute="immediate"  />
  <CustomAction Id="UninstallService" 
                FileKey="MyApp.exe" 
                ExeCommand="uninstall"
                Execute="immediate"  />

  <InstallExecuteSequence>
    <Custom Action="InstallService" After="InstallFinalize" >
      NOT Installed AND NOT REMOVE
    </Custom>
    <Custom Action="StopService" After="InstallInitialize" >
      (NOT UPGRADINGPRODUCTCODE) AND (REMOVE="ALL")
    </Custom>
    <Custom Action="UninstallService" After="StopService">
      (NOT UPGRADINGPRODUCTCODE) AND (REMOVE="ALL")
    </Custom>
  </InstallExecuteSequence>
</Product>
Community
  • 1
  • 1
Chris Watts
  • 822
  • 1
  • 9
  • 27

2 Answers2

1

There are a couple of problems with your custom actions. One is that the InstallService CA is immediate which means 1) It's before the files are installed and 2) it won't run with elevation. It needs to be deferred and before InstallFinalize.

If this is just an ordinary Windows service, then you should use a ServiceInstall node to install it (and uninstall it) as well as ServiceControl to stop, start, and delete it.

PhilDW
  • 20,260
  • 1
  • 18
  • 28
  • Thanks for your comments, shall try the deferrered finalize change when i get a moment later on. The topshelf ecosystem is worth a look, it wraps up the windows service start stop and configuration, so that a windows service project can be run from debug without wrapping it as a console app, and also can install it from the main app with a switch without recompiling etc. Definitely worth looking at, my explanation hasnt been great! – Chris Watts Apr 07 '17 at 05:15
  • Brill, you are correct, changing the CA to have: `Impersonate="no"`, `Execute="deferred"` and set Execute `Before="InstallFinalize"` thanks for your help! just got to figure out the uninstall now! Never had so much trouble! – Chris Watts Apr 07 '17 at 08:04
  • However, you are also correct that the service install node/service config and service control also work and can be used with topshelf, making life a lot easier! Thanks very much for your help! Can stop tearing my hair out now! – Chris Watts Apr 07 '17 at 10:13
  • @ChrisWatts: It's well worth noting PhilDW's point about using ServiceInstall and ServiceControl if possible. The custom actions you describe will not roll back on failures, potentially resulting in an installed service after a failed installation, or an uninstalled service after a failed uninstallation. The ServiceInstall/ServiceControl method should not result in those cases. If it is not applicable, you should author rollback actions. – Michael Urman Apr 07 '17 at 13:06
  • 1
    @MichaelUrman i tried and succeeded using the service install and control tags, i realised mid-morning that the application, topshelf or not, still has to provide the standard interface for windows services. Just glad as like you say it has rollback, in addition to being discrete and in the background rather than command prompt windows opening everywhere. – Chris Watts Apr 07 '17 at 20:20
  • @Chris Watts, you should really update your question with how you fixed the issue – JohnChris Apr 12 '18 at 11:16
  • 1
    @JohnChris, I will do as you have asked, I hadn't updated as it was all in the comments, but shall update when I am back I'm the office tomorrow. – Chris Watts Apr 12 '18 at 18:43
0

I solved this problem using the following code

<CustomAction Id="InstallService" FileKey="MyApp.exe" ExeCommand="install start" Impersonate="no" Execute="deferred" />
<CustomAction Id="UninstallService" FileKey="MyApp.exe" ExeCommand="stop uninstall" Impersonate="no" Execute="deferred" />

<InstallExecuteSequence>
  <Custom Action="InstallService" Before="InstallFinalize">
    NOT Installed AND NOT REMOVE
  </Custom>
  <Custom Action="UninstallService" Before="RemoveFiles">
    (NOT UPGRADINGPRODUCTCODE) AND (REMOVE="ALL")
  </Custom>
</InstallExecuteSequence>
Surendra Shrestha
  • 1,035
  • 12
  • 21
  • dont know why but i only got a notification of this response today..! as in the comments above, this is *not* the recommended pattern as it does not handle failure/rollback scenarios. A Topshelf service is a windows service still and therefore can be installed using the traditional WiX service installation methods. Manual intervention like the answer above should be avoided without excellent justification :) – Chris Watts Dec 19 '22 at 13:36