C#: Hosting Web PI GUI In Own Application

The Microsoft Web Platform Installer (Web PI) is a very cool tool for installing frameworks, programs and web application. It automatically resolves installs dependencies, which makes it my top choice for deploying my own applications. In some cased, I need to install multiple applications and update their local configuration to contain data of other applications (e.g., the web site URL of one application gets written to the web.config of another application). The installer application internally uses Web PI to perform the dependency resolving and the actual installation. The installer application itself performs the cross-application configuration and installs other components not installable via Web PI. This post shows how to integrate Web PI GUI into a custom application.

The Web PI GUI is implemented with Windows Forms. The whole application content that you normally see when running Web PI, i.e. everything inside the window frame, is actually one single Windows Forms control. It is called Microsoft.Web.PlatformInstaller.UI.ManagementFrameFull and is located in the assembly Microsoft.Web.PlatformInstaller.UI.dll. You’ll find that assembly (along with others we’ll need) in %ProgramFiles%\Microsoft\Web Platform Installer or in the GAC. To host that control, it must be instantiated and added to any parent Windows Forms control. The following code shows how.

using Microsoft.Web.PlatformInstaller.UI;

// ..

// First set the parameters...
var contextualEntryProducts = new []{ "WordPress" };
var contextualEntryLanguage = "en";
var applicationOverrideFeed = "http://www.microsoft.com/web/webpi/4.6/webproductlist.xml";
var useIisExpress = true;

// ...then create an instance of Web PI...
var contextualEntryModes = useIisExpress 
                             ? ContextualEntryModes.TargetIisExpress 
                             : ContextualEntryModes.TargetIis;

var hostService = new HostService
{
    AllowIisExpressAppInstall = useIisExpress,
    UseIisExpressForAppInstall = useIisExpress
};

var serviceProvider = new UIHost(hostService, applicationOverrideFeed);
serviceProvider.UseIisExpressForAppInstall(useIisExpress);

// Instantiate the Web PI GUI control
var managementFrame = new ManagementFrameFull(serviceProvider, contextualEntryProducts, contextualEntryFeeds, contextualEntryLanguage, contextualEntryModes);

// Add Web PI control to parent control
form.Controls.Add(managementFrame);
managementFrame.LoadUI();

All objects in the code above are located in the assembly Microsoft.Web.PlatformInstaller.UI.dll, except for HostService. The Web PI API does not provide any public types that implement IHostService, so to be able to create an instance of UIHost, we’ll have to provide our own implementation.

class HostService : IHostService
{
    public Icon ShellIcon { get; private set; }
    public bool ShowProducts { get; private set; }
    public bool AllowIisExpressAppInstall { get; set; }
    public bool UseIisExpressForAppInstall { get; set; }
    public IWin32Window WindowHandle { get; private set; }
    public string ProductForumUri { get; private set; }
    public string ProductTitle { get; private set; }
    public string ProductTitleLong { get; private set; }

    public event EventHandler<FormClosingEventArgs> ShellFormClosing;

    public HostService()
    {
        ShellIcon = Icon.ExtractAssociatedIcon(Assembly.GetExecutingAssembly().Location);
        ShowProducts = false;
        WindowHandle = Control.FromHandle(Process.GetCurrentProcess().MainWindowHandle);
    }

    internal void RaiseShellFormClosing(object sender, FormClosingEventArgs e)
    {
        if (ShellFormClosing != null)
        {
            ShellFormClosing(sender, e);
        }
    }
}

Maybe I haven’t played with Web PI enough, but it seems that even with this approach, you can’t provide a custom feed url. If you need to provide a custom feed, this post shows how to do it.

Freelance full-stack .NET and JS developer and architect. Located near Cologne, Germany.

Leave a Reply

Your email address will not be published. Required fields are marked *