Stopping a Web Site to Remove Locked Log Files During a WiX Uninstall
So for my employer, Skiviez, I’ve created a WiX installer for the Web site. It’s pretty sweet: just double-click the MSI, and insto presto, you have a Web site installed, with the directories created, permissions set correctly, and IIS configured correctly.
The Web site uses log4net for logging, and it uses the RollingFileAppender to log information in a Logs directory for the Web site. In WiX, this behavior is specified in the usual way:
<Directory Id="DirectoryLogs" Name="Logs"> <Component Id="ComponentCreateFolderLogs" Guid="{DAB6113C-83BA-422d-9D77-43F112BE7EF7}"> <CreateFolder> <Permission GenericRead="yes" GenericWrite="no" GenericExecute="no" Read="yes" User="Authenticated Users" /> <Permission GenericAll="yes" User="NT AUTHORITY\NETWORK SERVICE" /> </CreateFolder> <RemoveFile Id="RemoveFileLogsAll" Name="*.*" On="uninstall" /> </Component> <Component Id="ComponentConfigWebLogs" Guid="{82B14CA7-96B1-4c92-8E6E-846C8E17ED02}"> <File Id="FileConfigWebLogs" Name="Web.config" Source="$(var.Skiviez.Armadillo.UI.Web.ProjectDir)Logs\" KeyPath="yes" /> </Component> </Directory>
There is nothing particularly exotic going on here. I tell Windows Installer to create the Logs folder, set some permissions on it so that NETWORK SERVICE (which the Web site runs as) can read and write to the folder and so that I (as an Authenticated User can easily read it), copy in a Web.config that locks down the folder from being served by IIS, and tell Windows Installer to remove all of the log files during uninstall. I’ve written this a bazillion times before and it works fine for most programs.
But when I tried to uninstall while the Web site was still running, the uninstallation would fail because the log file was still locked by the Web site. This is because WiX’s custom action that finagles with IIS runs after the standard RemoveFiles action in Windows Installer. Some poor soul seemed to be having my exact same problem, but no answers there.
Since this is the only Web site running on the server, an easy solution is to use another built-in WiX custom action to stop IIS during uninstallation and then start it back up again afterward. This has the advantage of spinning down the ASP.NET worker process so that the lock on the file is released, RemoveFiles completes successfully, the WiX IIS custom action removes the Web site, and finally IIS is gracefully started back up again.
I’m not sure why it wasn’t obvious to me; took me a good 45 minutes to figure this out.
Just drop this in the same Component that your Web site is defined in:
<ServiceControl Id="ServiceControlWebSiteMain" Name="W3SVC" Start="both" Stop="both" Wait="yes" />
(Side note: Windows Installer’s architecture is completely insane. I reckon I’ll save that rant for another post. Perhaps the most amusing bit is that when uninstallation fails for some reason, such as the situation described in this post, Windows Installer will happily re-install everything back to the way it was! Ha!)
Happy uninstalling!






While I agree there are some pretty crazy things in the Windows Installer, the rollback mechanism really makes sense. The goal is to ensure that the machine always ends up in a “known state”. That means either the software is fully installed or fully uninstalled. If something causes the transformation between states to fail then the transformation is rolledback to its original state.
Rob,
Ha! I don’t disagree. But I found it quite unexpected and amusing the first time that it happened to me.
Have you considered just shutting down the associated app pool instead of brining down all of IIS? On a production server, that could really other tenants off.
@Christopher
If my application weren’t the only Web application running on a dedicated server, I’d probably explore it. Since WiX doesn’t have a built-in custom action for controlling the start and stop of application pools, to my knowledge, writing my own or figuring out to shell out to some IIS VBS script would have been developer gold-plating that would be tangential to my deployment goal.
Still, it’s a good suggestion for those who would intend for their Web application to be deployed in a less controlled environment. In that case, I guess a few exec’s out to iisapp.vbs would do the trick.