C#: Getting Installer Product Data From Hosted Web PI GUI

The previous post explained how to get event notification from a running Web PI GUI window that is hosted in our own application. This post will describe how to get information about the products being installed by Web PI and about the installation status itself.

In the previous post, the class InstallerServiceProxy was introduced. We will use it now to hook up into the installation process.

using System;
using System.Collections.Generic;
using System.Reflection;
using Microsoft.Web.PlatformInstaller;

class RuntimDataCollector
{
    public Dictionary<string, InstalledProduct> Products { get; private set; }

    public RuntimDataCollector(IServiceProvider serviceProvider)
    {
        // This code is explained in the previous post at http://bit.ly/1oS8xoE
        var type = Type.GetType("Microsoft.Web.PlatformInstaller.UI.InstallerService, Microsoft.Web.PlatformInstaller.UI");
        var installerService = serviceProvider.GetService(type);
        var property = installerService.GetType().GetProperty("InstallManager", BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.FlattenHierarchy);
        var installManager = property.GetValue(installerService, null) as InstallManager;
        
        installManager.InstallerStatusUpdated += OnInstallerStatusUpdated;
        installManager.InstallCompleted += OnInstallCompleted;

        Products = new Dictionary<string, InstalledProduct>(StringComparer.OrdinalIgnoreCase);
    }

    private void OnInstallerStatusUpdated(object sender, Microsoft.Web.PlatformInstaller.InstallStatusEventArgs e)
    {
        var installerContext = e.InstallerContext;
        var msDeployPackage = e.InstallerContext.Installer.MSDeployPackage;
        InstalledProduct product;

        if (!Products.TryGetValue(installerContext.ProductName, out product))
        {
            product = new InstalledProduct()
            {
                Name = installerContext.ProductName,
                ProductId = installerContext.Id
            };

            Products.Add(installerContext.ProductName, product);
        }

        if (msDeployPackage != null)
        {
            // We have a web application that is deployed with MsDeploy.
            product.IsWebSite = true;
            product.Parameters = msDeployPackage.SetParameters;
            product.Site = msDeployPackage.Site;
            product.AppPath = msDeployPackage.AppPath;
        }
        
        product.Message = e.InstallerContext.ReturnCode.DetailedInformation;

        switch (e.InstallerContext.ReturnCode.Status)
        {
            case InstallReturnCodeStatus.Success:
                break;
            case InstallReturnCodeStatus.SuccessRebootRequired:
                product.RequiresReboot = true;
                break;
            case InstallReturnCodeStatus.Failure:
                product.HasError = true;
                break;
            case InstallReturnCodeStatus.FailureRebootRequired:
                product.RequiresReboot = true;
                product.HasError = true;
                break;
            case InstallReturnCodeStatus.None:
                break;
        }
    }

    private void OnInstallCompleted(object sender, EventArgs e)
    {
        // When installation completes, we have a list of 
        // all installed products. We could get the URLs and
        // physical paths of the installed web applications
        foreach (var product in Products.Where(p => p.IsWebSite && !p.HasError))
        {
            // TODO: get web application properties from web server
        }
    }
}

The code above collects data from the running product installation. When installation completes, we know which products and web application were installed and what data was used during installation. What we don’t know are the physical path and the URL of the installed products. For the sake of completion, the class InstalledProduct used above looks as following:

class InstalledProduct
{        
    public string ProductId { get; set; }
    public string Name { get; set; }
    public bool IsWebSite { get; set; }
    public string Message { get; set; }
    public bool HasError { get; set; }
    public bool RequiresReboot { get; set; }
    public string Site { get; set; }
    public string AppPath { get; set; }
    public string Url { get; set; }
    public string PhysicalPath { get; set; }
    public Dictionary<string, string> Parameters { get; set; }
}

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

2 thoughts on “C#: Getting Installer Product Data From Hosted Web PI GUI

  1. Hi there. This looks like excellent work. Where did you find documentation on using the WebPI Dll? I have written an app to extract the necessary information from the feed and execute the installation myself but if I could have WebPI do it id feel better about it. Thanks for any information.

  2. OMG I’m so sorry for not answering your question. I haven’t seen your comment until today. The thing is, there was no documentation what so ever and I had to decompile WebPI and look inside it. Again, I’m terribly sorry for this very late answer.

Leave a Reply

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