The previous post explained how to host the Microsoft Web Platform Installer (WPI) in an own Windows Forms application. It’s nice that we can do that, but it only really makes sense when you need to perform special actions depending on the parameters determined by WPI during installation.
Consider this: WPI and Microsoft Web Deploy don’t seem to set the app pool default settings, especially the .NET runtime version. So when using WPI to install a .NET 4.0 based web application to an IIS server that has the app pool default runtime version set to “v2.0”, WPI encounters an error and cancels installation of the web applcation. An administrator must set the default .NET version manually before running WPI. In many cases, this is less than optimal.
Another example: Suppose you are installing web application A which depends on web application B. Now suppose that after installing both applications, you would like to write the address of application B in the web.config of application A. Maybe I just didn’t find any documentation of how to do it, but it seems to me that you can’t do this with WPI.
To resolve issues like these, you would probably think of hosting the WPI GUI in a custom installer application and react to events raised by WPI during installation and read the runtime data of the product installations run by WPI. The bad news is: WPI does not provide a public interface for this. The good news is: these events and properties exist interally in WPI GUI assembly Microsoft.Web.PlatformInstaller.UI.dll and we can access them via reflection. Of course, accessing internal members of other people’s assemblies is risky, because you never know when they are going to change their code. On the other hand, implementing a full blown installer like the WPI GUI with all the parameter forms and settings dialogs is a huge load of hard work. You might consider the amount of work needed to catch up with changes in the WPI code as much less work. Well, I guess I do.
But enough chit chat, let’s get to the code. The Web Platform Installer API provides the InstallManager class which has the events we need. But unfortunately, there is no public access to the internally used InstallManager when you use the Web PI GUI.
In the previous post, the following code line is used to create an object internally used by WPI to resolve services that encapsulate certain functionalities.
var serviceProvider = new Microsoft.Web.PlatformInstaller.UI.UIHost(hostService, applicationOverrideFeed);
The services used in this post is Microsoft.Web.PlatformInstaller.UI.InstallerService. We need an instance of InstallerService because it has a internal property that contains the InstallManager we want. To get the InstallManager and subscribe to its events, we do the following:
// Create a service provider var serviceProvider = new Microsoft.Web.PlatformInstaller.UI.UIHost(hostService, applicationOverrideFeed); // Query service provider for internal InstallerService var type = Type.GetType("Microsoft.Web.PlatformInstaller.UI.InstallerService, Microsoft.Web.PlatformInstaller.UI"); var installerService = serviceProvider.GetService(type); // Call internal property &quot;InstallManager&quot; to get InstallManager var property = installerService.GetType().GetProperty(&quot;InstallManager&quot;, BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.FlattenHierarchy); var installManager = property.GetValue(installerService, null) as InstallManager; // Subscribe to installation events installManager.InstallCompleted += OnInstallCompleted; installManager.InstallerStatusUpdated += OnInstallerStatusUpdated;
I won’t go through the code above becaus I think it is fairly simple. After executing the code above, you will get event notification during and at the end of product installations performed by WPI. The following post will show how to get product and installation information using those event notifications.