Update: edited final example thanks to comments (changed first “after” to “before”)

Sometimes it is necessary to run a command line action from WiX in order to complete the configuration of the deployment. And though there is an extension for IIS called the WebAppPool Element, the features available do not completely cover all the functionality that you may want to configure in the installer. For example, you can set how often you want the app recycled in minutes, but you can’t define when you want it done (say at 5am). Defining the app to recycle every 1440 minutes isn’t the same, as you’re constricted to installing at the time you want the 24 hour refresh to occur.

Fortunately we can leverage the use of running command line via a custom action in our installer. You need a reference to WiXUtilExtension to do this, which helpfully is not written anywhere explicitly on the SourceForge page. The documentation for WiX shows us how to write a custom action to run the Quiet Execution CustomAction (qtexec custom action) that can run arbitrary command lines.

So now we can use the app.cmd.exe to configure IIS exactly how we like, once every 24 hours at 5am (keep an eye out for square bracket formatting, it will cause an ICE03 error).


<Property Id="QtExecCmdLine" Value=""[WindowsFolder]system32\inetsrv\APPCMD.EXE" set AppPool /apppool.name:ServiceHostAppPool /recycling.periodicRestart.time:00:00:00"/>
<CustomAction Id="QtExec" BinaryKey="wixca" DllEntry="CAQuietExec" Execute="immediate" Return="check"/>
<Binary Id="wixca" src="wixca.dll"/>

<InstallExecuteSequence>
<Custom Action="QtExec" After="InstallFinalize"/>
</InstallExecuteSequence>

But so far this command will only set the refresh in minutes to 0, which means switching it off totally. Now we need to write another command to set it to 5am. You’d think that writing something like what I have below would work:


<Property Id="QtExecCmdLine" Value=""[WindowsFolder]system32\inetsrv\APPCMD.EXE" set AppPool /apppool.name:ServiceHostAppPool /+recycling.periodicRestart.schedule.[\[]value='05:00:00'[\]]" />
<CustomAction Id="QtExec" BinaryKey="wixca" DllEntry="CAQuietExec" Execute="immediate" Return="check"/>
<Binary Id="wixca" src="wixca.dll"/>

<InstallExecuteSequence>
<Custom Action="QtExec" After="InstallFinalize"/>
</InstallExecuteSequence>

however you get all manner of errors:

confusedbuild_png

Consulting the documentation, it states that:


<CustomAction
Id="RecyclingAppPoolsRestart_Cmd"
Property="RecyclingAppPoolsRestart"
Execute="immediate"
Value=""[WindowsFolder]system32\inetsrv\APPCMD.EXE" set AppPool /apppool.name:DefaultAppPool /recycling.periodicRestart.time:00:00:00" />

<CustomAction
Id="RecyclingAppPoolsSchedule_Cmd"
Property="RecyclingAppPoolsSchedule"
Execute="immediate"
Value=""[WindowsFolder]system32\inetsrv\APPCMD.EXE" set AppPool /apppool.name:DefaultAppPool/+recycling.periodicRestart.schedule.[\[]value='05:00:00'[\]]" />

<CustomAction
Id="RecyclingAppPoolsRestart"
BinaryKey="WixCA"
DllEntry="CAQuietExec"
Execute="deferred"
Return="check"
Impersonate="no"/>

<CustomAction
Id="RecyclingAppPoolsSchedule"
BinaryKey="WixCA"
DllEntry="CAQuietExec"
Execute="deferred"
Return="check"
Impersonate="no"/>

<InstallExecuteSequence>
<Custom Action="RecyclingAppPoolsRestart_Cmd" Before="InstallFinalize">NOT REMOVE</Custom>
<Custom Action="RecyclingAppPoolsSchedule_Cmd" After="RecyclingAppPoolsRestart_Cmd">NOT REMOVE</Custom>
<Custom Action="RecyclingAppPoolsRestart" After="RecyclingAppPoolsSchedule_Cmd">NOT REMOVE</Custom>
<Custom Action="RecyclingAppPoolsSchedule" After="RecyclingAppPoolsRestart">NOT REMOVE</Custom>
</InstallExecuteSequence>

The InstallSequence is then the commands followed by the referenced CustomActions.

Summary

Now we’re beginning to see why people complain that the documentation for WiX is not great. Maybe I’m being too harsh there, however we can see that there is no reference to the fact that we need to add a reference to WiXUtilExtension to get this to work and we’ve got a confusing explanation with no example! Plus when compared to running cmdline in MSBuild, it seems unnecessary convoluted process to get two lines of cmdline executed. And how much use is the WebAppPool element when it fails to adequately cover the work that we need done. But I cannot deny that it is possible to run app.cmd and leverage all the functionality that is available. Even then however, there were some things that happened in the MSI that did not occur when running the commands manually through cmdline: after every “:” I left a space when running manually, This is fine when running like this, but through when running the Installer it bombed out because the custom command did not like the space, something I was not aware of until deployment. So be warned that your executes will not be validated when compiling the WiX project.

Sources