Search code examples
c#wixwindows-installerwixsharp

Recursive DirFiles to build MSI using Wix#


I'm exploring the features of Wix# and I'm stunned with it's simplicity in comparison to Wix. We are already using the QT Installer Framework, but our customers are also in need for a MSI installation package.

I already have a directory containing all files for our product and there is simply one package. I tried to include all files in C:\Temp\MyProductFiles into my MSI installer.

using System;
using WixSharp;

class Script
{
    static public void Main(string[] args)
    {
        Compiler.WixLocation= @"C:\WiX-3.7\binaries"; 
        var project = new Project("MyProduct",
                          new Dir(@"C:\Temp\MyProduct", 
                            new DirFiles(@"C:\Temp\MyProductFiles\*.*")
                           )
                      );
        project.UI = WUI.WixUI_Common;

        Compiler.BuildMsi(project);
    }
}

The installer basically worked as expected, but unfortunately C:\Temp\MyProductFiles contains many subdirectories, that I don't want state explicitly every time, as we have several products.

Is there an easy way to automatically include all files and subdirectories using Wix#?

Maybe one can do it also using C#, but I'm not proficient in C# and I really don't know how to start.


Solution

  • As far as I know, there is no in-built mechanism to take all the sub directories, but you can just recursively traverse the tree, and project each entry into DirFiles

    IEnumerable<string> GetSubdirectories(string root)
    {
        string[] subdirectories = Directory.GetDirectories(root);
        foreach (var subdirectory in subdirectories)
        {
            yield return subdirectory;
            foreach (var nestedDirectory in GetSubdirectories(subdirectory))
            {
                yield return nestedDirectory;
            }
        }
    }
    

    Projection can output into an array of DirFiles with mandatory wild-card pattern:

    DirFiles[] dirFiles = GetSubdirectories(rootPath).Select(d => new DirFiles(Path.Combine(d, "*.*"))).ToArray();
    

    Then, it's just matter of passing it:

    var project = new Project("MyProduct", new Dir(@"C:\Temp\MyProduct", dirFiles)));