views:

2331

answers:

4

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.

+2  A: 

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.

jeffamaphone
Thanks - I'll give that a try!
marc_s
Yup, the sequencing is fine; InstallServices is 5800, RunDbUpdateManagerAction is 5899, StartServices is 5900 - and still it doesn't work ....
marc_s
jeffamaphone
@Jeff: Look at the link in my answer for the conditions prefixes
CheGueVerra
+1  A: 

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

CheGueVerra
Excellent point - in the logs, I find "MSI (s) (A0:94) [20:06:59:961]: Skipping action: RunDbUpdateManagerAction (condition is false)" - now I only need to understand what exactly that condition is, why it's false, or how to change it........
marc_s
Condition seems to be okay now - action seems to get kicked off judging from the logs - but the wizard UI never shows up, and I'm getting a "return value 1631" error in the logs....
marc_s
+2  A: 

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.

Rob Mensching
Thanks Rob - you explained it very well indeed. My dilemma is: the tool *IS* a wizard which shows a UI - so marking it "deferred" probably won't help :-( My other idea was to just simply move the "StartServices" step to later in the process, after my DB Update Manager has run - but can I move StartServices past the "InstallFinalize" ?
marc_s
Well, now I finally got my custom action to work - it's scheduled to "After=InstallFinalize" again (seems the only chance when I don't make it deferred). That worked fine - but then when trying to execute the StartServices step even after that, I get: DEBUG: Error 2762: Unable to schedule operation. The action must be scheduled between InstallInitialize and InstallFinalize.So I'm doomed one way or another - deferred = no UI, not deferred --> can't start services....
marc_s
+4  A: 

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

marc_s
I'll +1 everyone cool glad it works ...
CheGueVerra

related questions