WiX - trying to figure out install sequences

18,922

Solution 1

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

Solution 2

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

Solution 3

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.

Solution 4

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.

Share:
18,922
marc_s
Author by

marc_s

Note to all SO beginner: please absolutely read Jon Skeet's helpful hints on how to write a good question (or at least his short version here) - one that has a chance that someone can answer it. A senior C# / SQL Server / Entity Framework backend developer for line-of-business applications (mostly ASP.NET / ASP.NET Core).

Updated on June 16, 2022

Comments

  • marc_s
    marc_s over 1 year

    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:

    1. Install DbUpdateManager and my services from my MSI
    2. 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'>&amp;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'>&amp;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.