I recently had the pleasure of trying to get SQLExpress 2005 to install, on request, during my application’s install, according to various parameters specified by the user during the UI portion of my install. Phew. Yeah, it’s hard enough to say, much less code.
Anyway, the basic problem is that you can’t nest MSI installs. And since an “MSI Install” is considered to be the portion of the install that runs during the EXECUTE sequence of the MSI logic, this means you can’t just execute SQLEXPR32.EXE at some point during the EXECUTE sequence of your install.
This is normally what you’d want to do because then, that action would happen regardless of whether your installation was running silently (ie no UI) or not.
Ok, that’s off the table. Hey, Microsoft! Believe it or not, nesting installs is something real world apps have to do in order to get all those nifty libraries of yours out there onto client machines! Sigh.
Fortunately, in my case (and in many others I’m guessing), not being able to run the SQL Express installer during a silent install is not a deal breaker. More than likely, if my installation is being rolled out silently, whoever’s rolling it out is using some sort of automated rollout tool to do it, and it’s likely they’ll just automate the rollout of SQLExpress as well.
But, what about when a user is simply trying to run my installation to get the product on their machine. In this situation, you want a no fuss, no muss process that has a user up and running with a little decision-making as possible. The last thing I want a user being prompted for is the instance name to use for the SQL Server that’s about to get installed. Sheesh.
Well, I can’t nest MSIs, technically, but I can execute SQLEXPR32.EXE from the UI sequence of the install.
Aha! Success! Except that, as well documented by any number of posts online, it doesn’t work consistently. Often, you’ll get an MSI error 110 indicating that SQL can’t access a file (usually sqlncli.msi) that it needs to complete the install.
******* CommandLine: **********
MSI (s) (18:00) [12:59:55:555]: Machine policy value 'DisableUserInstalls' is 0
MSI (s) (18:00) [12:59:55:575]: Note: 1: 1309 2: 5 3: C:\23661fc1e2705da3b45f5b05\setup\sqlncli.msi
MSI (s) (18:00) [12:59:55:595]: MainEngineThread is returning 110
The system cannot open the device or file specified.
Trouble is, the file is there, exactly where the log says it isn’t.
The problem is clearly an issue with the SQLExpress installer. I can say that pretty confidently because you can nest all of SQL’s prerequisite installs just fine, including:
- MSXML6.MSI (The XML 6.0 libraries)
- SQLCNLI.MSI (SQL Native Client)
- SQLServer2005_XMO.msi (SQL Server management objects installer)
- And even VSTOR.EXE (the Visual Studio Tools for Office)
Just not the SQLEXPR32.EXE itself.
One possible solution that I found mentioned online was to extract all the SQLEXPR32.EXE files, then actually include them directly in your installation and at the end of your installation (in the UI sequence) launch the SETUP.EXE that starts the SQLExpress installation.
So I extracted them all:
SQLEXPR32.EXE /x:c:\SQLEXPR
Ouch. And I mean owwwwwwwwwchaaaaaa. 400+ files scattered over dozens of directories. The InstallShield Component Wizard choked trying to add them all as components and there was simply no way I was going to manually set up all that felgercarb in my install. Yeah, I went there<g>
Then it struck me. The extraction process (that /x command line arg) isn’t actually an msi install, so I should be able to nest it just fine. And if that’s the case, then I could extract all the files from SQLEXPR.EXE dynamically after installing the exe, and then fire up SQL’s setup.exe directly, just as I’d tried launching the SQLEXPR32.exe before (but that failed with the 110 error).
So, first, make sure you install the SQLEXPR32.EXE along with the rest of your application’s files.
Then, set up a Custom Action in your MSI project, in the EXECUTE sequence, that extracts all the files from SQLEXPR32.EXE to some folder (usually inside your INSTALLDIR somewhere):
(note the use of /q; that will keep the extraction process quiet, including suppressing a rather bothersome “Extraction process done” message box when it finishes, Also note that this adds substantially to your app footprint so you may need to accommodate that in available space calculations).
Next, create another Custom Action to execute the SQL Express SETUP.EXE that was extracted in the previous step.
Set this CA to execute towards the end of the UI sequence (because this is an MSI setup and this action can’t be started from the EXECUTE sequence of your installation, no getting around that one).
I set a command line of /qb to use the basic install ui for SQL Express, but you might also want to include other command line parameters, like:
- ADDLOCAL
- INSTANCENAME
- SECURITYMODE
- SAPWD
- DISABLENETWORKPROTOCOLS
or any of the other options you can specify. More info about the command line options for SQLEXPR32 are pretty easy to find online.
And finally, to keep your installation from looking like it just hung during the extraction part above, be sure to author a row in the ACTIONTEXT table for that custom action, and give it some text, like “Extracting SQL Server files…”. The text will show up over the progress bar that normally displays during an InstallShield-authored installation.
Let me know if this works for you, or if I’ve missed some esoteric combination in InstallShield that prevents it from working.
As always, YMMV.