7

So I'm creating my first Wix project and I seem to be having a problem executing a custom action. I'm not sure that it's being included in the msi and I'm not quite sure what I'm doing wrong. The following is my Wix file:

<?xml version="1.0" encoding="UTF-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
    <Product Id="*" Name="ExactaDynamicManifest" Language="1033" Version="1.0.0.0" Manufacturer="Bastian Software Solutions" UpgradeCode="274ff2d9-e291-4706-a8db-ce80ccd91538">
      <Package InstallerVersion="200" Compressed="yes" InstallScope="perMachine"/>

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

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

      <Icon Id="exacta.ico" SourceFile="icons\exacta.ico"/>
      <Property Id="ARPPRODUCTICON" Value="exacta.ico" />

    </Product>

    <Fragment>
        <Directory Id="TARGETDIR" Name="SourceDir">
            <Directory Id="ProgramFilesFolder">
        <Directory Id="ExactaFolder" Name ="Exacta">
                  <Directory Id="INSTALLFOLDER" Name="ExactaExactaDynamicManifest" />
        </Directory>
            </Directory>
        </Directory>
    </Fragment>

    <Fragment>
      <CustomAction Id="InstallService" FileKey="ExactaDynamicManifest.exe" ExeCommand="install"/>
      <InstallExecuteSequence>
        <Custom Action="InstallService" After="InstallFinalize"/>
      </InstallExecuteSequence>
    </Fragment>
</Wix>

The last fragment contains my custom action which what I hoped would do is the following on the command line after all files have been placed in the directory:

ExactaDynamicManifest.exe install

One thing to note is that exe is actually coming from a ComponentGroupRef defined above. Not sure if this is a problem or not but thought I'd mention it. Any help would be appreciated.

Cole W
  • 15,123
  • 6
  • 51
  • 85

2 Answers2

8

I finally got something that is working. My initial problem of the CustomAction not loading seemed to be due to it being in a different <fragment>. I consolidated all of the code into a single fragment and it seemed to run.

After battling with user permissions etc I finally ended up with this solution:

<?xml version="1.0" encoding="UTF-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
    <Product Id="*" Name="ExactaDynamicManifest" Language="1033" Version="1.0.0.0" Manufacturer="Bastian Software Solutions" UpgradeCode="274ff2d9-e291-4706-a8db-ce80ccd91538">
      <Package InstallerVersion="200" Compressed="yes" InstallScope="perMachine"/>

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

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

      <Icon Id="exacta.ico" SourceFile="icons\exacta.ico"/>
      <Property Id="ARPPRODUCTICON" Value="exacta.ico" />

    </Product>

    <Fragment>
      <Directory Id="TARGETDIR" Name="SourceDir">
        <Directory Id="ProgramFilesFolder">
          <Directory Id="ExactaFolder" Name ="Exacta">
            <Directory Id="INSTALLFOLDER" Name="ExactaExactaDynamicManifest" />
          </Directory>
        </Directory>
      </Directory>

      <CustomAction Id="RunTopShelfServiceInstall" Directory="INSTALLFOLDER" Execute="deferred" Return="ignore" Impersonate="no" ExeCommand="[INSTALLFOLDER]ExactaDynamicManifest.exe install"/>
      <CustomAction Id="RunTopShelfServiceUninstall" Directory="INSTALLFOLDER" Execute="deferred" Return="ignore" Impersonate="no" ExeCommand="[INSTALLFOLDER]ExactaDynamicManifest.exe uninstall"/>

      <InstallExecuteSequence>
        <Custom Action="RunTopShelfServiceInstall" After="InstallFiles">
          NOT Installed
        </Custom>
        <Custom Action="RunTopShelfServiceUninstall" After='InstallInitialize'>
          (NOT UPGRADINGPRODUCTCODE) AND (REMOVE="ALL")
        </Custom>
      </InstallExecuteSequence>

    </Fragment>
</Wix>
Oliver Nicholls
  • 1,342
  • 12
  • 24
Cole W
  • 15,123
  • 6
  • 51
  • 85
  • You can also further decouple your service.exe's name from your wix code via: ExeCommand="[INSTALLFOLDER]$(var.YourServiceProjectName.TargetName) install" assuming you have added the project as a reference to your wix project. – Sean B Jan 12 '17 at 21:46
  • You saved my ass, with that! ;) – Vico Aug 25 '22 at 19:13
0
  1. Are you going to register a service using a custom action? You also have to handle uninstall, repair actions. It's much simpler to use standard MSI feature to install services: http://wixtoolset.org/documentation/manual/v3/xsd/wix/serviceinstall.html

  2. If you want to use custom actions for this purpose and UAC is enabled your service won't be installed due to permissions. You have to use deferred and not impersonated custom action scheduled before InstallFinalize (after InstallFinalize custom actions can't be scheduled).

leshy84
  • 680
  • 5
  • 13
  • Yes I'm installing the service via a CustomAction. I'm not using the standard service install in Wix because it's NOT a standard service. I'm using a framework called Topshelf (http://topshelf-project.com/). Also I do plan on handling uninstall and repair but first things first ... I need to install the service. – Cole W Jan 20 '14 at 12:54
  • We also use Topshelf for our services, it does not contradict using standard MSI features. If your service does something specific during installation, you can do it during the first start. – leshy84 Jan 20 '14 at 14:09
  • That's interesting because most of the articles I've read online that refer to installing Topshelf services recommend using CustomActions to do so. I have seen an article that says to create an Installer class like a normal windows service but at that point I question why I'm even using Topshelf. So are you creating this installer class to be able to utilize the standard functionality in Wix? – Cole W Jan 20 '14 at 14:19
  • 3
    Wix can be used to install topshelf service. You just have to make sure that service name in wix file _exactly_ match service name in call to topshelf's SetServiceName(). – Vasily Redkin Sep 09 '15 at 09:44
  • @VastlyRedskin if you got it working why not post a simple example with both the topshelft setup code and the wix source? – Peter Apr 04 '17 at 14:59
  • @Peter In case anyone is still wondering, this worked for me: Suppose you have something like this in your wix config: ` ` Then in your topshelf the service name must be exactlythe same: `configure.SetServiceName("AwesomeService");` – Daan Jul 13 '18 at 09:25