Question

Is there anyway to check to see if a service is installed, and if so, stop it and uninstall it when my application is being uninstalled using WiX 3.7? I don't want WiX to install the service though - just uninstall it.

I have WiX setup to install several application components, but the application itself CAN spawn a Windows Service (depending on features selected during install). I'm not really sure what the best way to clean that up is - I guess just to have my setup check if that service exists and remove it upon uninstall.

I'm not sure if I would need a CustomAction for that. I'm fairly familiar with installing services with WiX, but not JUST removing them (if it exists).

Here is my setup project. Just to give a little additional background on this, this is an auto-updater/launcher application. It takes a series of XML files to tell it how to update/prepare an application. If you choose the "MyApp Printer" feature, for example, it would install an extra XML file that tells my application how to hash check the local files against a web service and then install and start the "MyApp Printer" Windows Service for that component. The Windows Service that is located inside my actual WiX Setup Project is something completely different, and that works fine when uninstalling so please disregard that one.

<?xml version="1.0" encoding="UTF-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
  <Product Id="*" Name="MyApp ID" Language="1033" Version="1.0.0.0" Manufacturer="MyApp ID" UpgradeCode="932dbe1f-e112-4bd0-8f60-b81850fb465b">
    <Package InstallerVersion="200" Compressed="yes" InstallScope="perMachine" />

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

    <WixVariable Id="WixUILicenseRtf" Value="EULA.rtf" />

    <Feature Id="ProductFeature" Title="MyApp ID Setup Core" Level="1" Absent="disallow" Display="expand">
      <ComponentGroupRef Id="ProductComponents" />
      <ComponentRef Id="MyAppStartMenuFolderRemove" />

      <Feature Id="MyAppClientFeature" Title="MyApp ID Windows Client" Level="1" Absent="allow">
        <ComponentGroupRef Id="MyAppClientComponents" />
        <ComponentRef Id="MyAppStartMenuIcon" />
      </Feature>

      <Feature Id="MyAppPrinterFeature" Title="MyApp ID Printer App" Level="2" Absent="allow">
        <ComponentGroupRef Id="MyAppPrinterComponents" />
        <ComponentRef Id="PrinterStartMenuIcon" />
      </Feature>
    </Feature>


    <UIRef Id="WixUI_FeatureTree" />
    <UIRef Id="WixUI_ErrorProgressText" />
  </Product>

  <Fragment>
    <Directory Id="TARGETDIR" Name="SourceDir">
      <Directory Id="ProgramFilesFolder">
        <Directory Id="MyAppBaseFolder" Name="MyAppID">
          <Directory Id="INSTALLFOLDER" Name="MyAppLauncher">
            <Directory Id="UPDATESCRIPTSFOLDER" Name="Scripts" />
          </Directory>
        </Directory>
      </Directory>
      <Directory Id="ProgramMenuFolder">
        <Directory Id="ApplicationProgramsFolder" Name="MyApp ID"/>
      </Directory>
    </Directory>
  </Fragment>

  <Fragment>
    <DirectoryRef Id="ApplicationProgramsFolder">
      <Component Id="PrinterStartMenuIcon">

        <Shortcut Id="PrinterStartMenuShortcut"
                  Name="MyApp ID Printer UI"
                  Description="Manage the MyApp ID Printer Service"
                  Icon="MyAppPrinterIcon"
                  Target="[INSTALLFOLDER]AutoUpdater.exe"
                  Arguments="MyAppPrinter"
                  WorkingDirectory="INSTALLFOLDER">
          <Icon Id="MyAppPrinterIcon" SourceFile="$(var.AutoUpdater.Launcher.TargetDir)\Resources\MyApp_printer_white.ico" />
        </Shortcut>

        <RegistryValue Root="HKCU" Key="Software\Microsoft\MyApp.CardPrinter.Service" Name="installed" Type="integer" Value="1" KeyPath="yes"/>
      </Component>
      <Component Id="MyAppStartMenuIcon">
        <Shortcut Id="MyAppStartMenuShortcut"
                  Name="MyApp ID"
                  Description="Run the MyApp ID Windows Client software"
                  Target="[INSTALLFOLDER]AutoUpdater.exe"
                  Arguments="MyAppClient"
                  WorkingDirectory="INSTALLFOLDER"/>

        <RegistryValue Root="HKCU" Key="Software\Microsoft\MyApp.WindowsClient" Name="installed" Type="integer" Value="1" KeyPath="yes"/>
      </Component>
      <Component Id="MyAppStartMenuFolderRemove">
        <RemoveFolder Id="ApplicationProgramsFolder" On="uninstall"/>
        <RegistryValue Root="HKCU" Key="Software\Microsoft\MyApp.WindowsClient" Name="installedFolder" Type="integer" Value="1" KeyPath="yes"/>
      </Component>
    </DirectoryRef>
  </Fragment>


  <Fragment>
    <ComponentGroup Id="ProductComponents" Directory="INSTALLFOLDER">
      <Component Id="LibrariesComponent" Guid="7ED3B3B3-A984-44ED-9BA3-841F53CEA114">
        <File Source="$(var.AutoUpdater.Foundation.TargetPath)" Vital="yes" KeyPath="yes" />
        <File Source="$(var.AutoUpdater.Module.TargetPath)" Vital="yes" />
        <File Source="$(var.AutoUpdater.Module.WebService.TargetPath)" Vital="yes" />
      </Component>
      <Component Id="ServiceComponent" Guid="CAB8D997-5798-4B9D-8CA0-78AACE58932E">
        <File Source="$(var.AutoUpdater.Service.TargetPath)" Vital="yes" KeyPath="yes" />
        <File Source="$(var.AutoUpdater.Service.TargetDir)\AutoUpdater.Service.exe.config" Name="AutoUpdater.Service.exe.config" Vital="yes" />
        <ServiceInstall Name="ServiceComponentInstall" Id="ServiceComponentInstall" DisplayName="MyApp ID Launcher" Account="LocalSystem" ErrorControl="normal" Type="ownProcess" Start="auto" Vital="yes" />
        <ServiceControl Name="ServiceComponentInstall" Id="ServiceComponentControl" Start="install" Stop="both" Remove="uninstall" Wait="yes" />
      </Component>
      <Component Id="LauncherComponent">
        <File Source="$(var.AutoUpdater.Launcher.TargetPath)" Vital="yes" />
        <File Source="$(var.AutoUpdater.Launcher.TargetDir)\Resources\MyApp_printer_white.ico" Name="MyApp_printer_white.ico" />
      </Component>
    </ComponentGroup>
  </Fragment>

  <Fragment>
    <ComponentGroup Id="MyAppClientComponents" Directory="UPDATESCRIPTSFOLDER">
      <Component Id="MyAppClientXml">
        <File Source="$(var.AutoUpdater.Service.TargetDir)\Scripts\MyAppClient.xml" Name="MyAppClient.xml" />
      </Component>
    </ComponentGroup>
  </Fragment>

  <Fragment>
    <ComponentGroup Id="MyAppPrinterComponents" Directory="UPDATESCRIPTSFOLDER">
      <Component Id="MyAppPrinterXml">
        <File Source="$(var.AutoUpdater.Service.TargetDir)\Scripts\MyAppPrinter.xml" Name="MyAppPrinter.xml" />
      </Component>
    </ComponentGroup>
  </Fragment>
</Wix>

I hope that wasn't too confusing :). Thanks in advance!

EDIT:

Thank you Rob, the solution was to add the <ServiceControl> element to the last Fragment:

  <Fragment>
    <ComponentGroup Id="MyAppPrinterComponents" Directory="UPDATESCRIPTSFOLDER">
      <Component Id="MyAppPrinterXml">
        <File Source="$(var.AutoUpdater.Service.TargetDir)\Scripts\MyAppPrinter.xml" Name="MyAppPrinter.xml" />
        <ServiceControl Id="NukeMyAppPrinterService" Name="MyApp ID Printer Service" Remove="uninstall" Stop="uninstall" />
      </Component>
    </ComponentGroup>
  </Fragment>

It will work whether or not that "MyApp ID Printer Service" is installed or not. I love the easy solutions!

Was it helpful?

Solution

Can't say I've done this myself (this is a pretty unique scenario) but the ServiceControl element should do the work just fine:

<ServiceControl Id='NukeService' Name='YourServiceName'
                Remove='uninstall' Stop='uninstall' />
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top