ISWIX, LLC View Christopher Painter's profile on LinkedIn profile for Christopher Painter at Stack Overflow, Q&A for professional and enthusiast programmers

July 07, 2008

Dynamic Windows Installer UI

I was reading a discussion on Dynamic UI for Windows Installer recently and I came across a post where there was some confusion over what MSI can internally do without the help of an external UI handler. I know in the past I've written custom actions to dynamically generate content for ListBoxes so I thought, why not be able to do it for other UI controls?

Fortunately DTF makes this kind of coding really, really easy. Here is a quick example:

using System;
using Microsoft.Deployment.WindowsInstaller;
 
namespace dynamicui
{
    public class CustomActions
    {
        [CustomAction]
        public static ActionResult DynamicUI(Session session)
        {
           InsertRecord(session, "CheckBox", new object[] { "DYNAMICPROPERTY", "1"});
           InsertRecord(session, "Control", new object[] { "CustomerInformation", "CheckBox1", "CheckBox",
                                                           144, 181, 198, 22, 3, "DYNAMICPROPERTY",
                                                           "Dynamic CheckBox", "", "" });
           return ActionResult.Success;
        }
 
        private static void InsertRecord( Session session, string tableName, Object[] objects)
        {
            Database db = session.Database;
            string sqlInsertSring = db.Tables[tableName].SqlInsertString + " TEMPORARY";
            View view = db.OpenView(sqlInsertSring );
            view.Execute(new Record(objects));
            view.Close();
 
        }
    }
}



In this example we insert 2 temp records into the MSI tables prior to displaying the CustomerInformation dialog. One record defines a CheckBox control on the CustomerInformation and associates it to the public property DYNAMICPROPERTY. Another record says that when the CheckBox is checked, that the property should have the value of 1. Otherwise it has a value of not-set.



Now I should note that in real life this would be a little more complicated. I intentionally did not subscribe to a tab order because I would have to do additional queries to be able to know how to inject myself into the tab order. Caution would also be highly advised since my new table records haven't gone through ICE validation processing. The normal way of doing things here is to have a bunch of static/disabled controls that you dynamically enable at runtime using ControlConditions. However, I could see a scenario where more flexibility is required so this pattern could be of help one day.

For additional fun, here is a half baked - off the cuff thought: This example is like reflection emitting (.NET IL ) instad of CodeDom ( language aware ). It would be interesting if DTF had a pattern that was aware of WiX XSD schema and could dynamically generate temporary MSI records based on WiX source inputs.

2 comments:

Unknown said...

Christopher,

You should consider posting screenshots of code as PNGs rather than JPEGs - the artifacts around the text are a bit unpleasant.

-John

Christopher Painter said...

I can try that. What I really need is see if this will work for me:

http://manoli.net/csharpformat/