Large Number of files to add

Apr 14, 2015 at 2:50 PM
I have a large number of files that I need to add to my installer.... is there a programmatically to add the large number of files i.e a wild card or how would I include heat output into my project?

thanks
Apr 14, 2015 at 3:51 PM
I had the same requirement so I wrote this wrapper class to do this.
Basically you just instantiate the class, and call SetFiles(..., ...) passing the source directory and the destination directory. When the MSI file gets created it will include all the files/directories from the source. Please let me know if this can be improved in any way...
I'm just picking this up so it may be far from perfect...

using Microsoft.Deployment.WindowsInstaller; //required in addition to WixSharp
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using WixSharp;
using System.Windows.Forms;
public class xWix
{
    public xWix(string projectName, Guid guid = new Guid())
    {
        Project.Name = projectName;
        Project.GUID = guid;
        Project.OutFileName = projectName;
    }

    public Project Project = new Project();
    public Guid Guid = new Guid();

    /// <summary>
    /// Include a source directory to be deployed as part of the MSI file.
    /// </summary>
    /// <param name="sourceDir"></param>
    /// <param name="projectInstallDir"></param>
    public void SetFiles(string sourceDir, string installDir = @"%ProgramFiles%\My Company\My Product")
    {
        SetFiles(new DirectoryInfo(sourceDir), installDir);
    }

    /// <summary>
    /// Include a source directory to be deployed as part of the MSI file.
    /// </summary>
    /// <param name="sourceDir"></param>
    /// <param name="installDir"></param>
    public void SetFiles(DirectoryInfo sourceDir, string installDir = @"%ProgramFiles%\My Company\My Product")
    {
        Dir projectInstallDir = new Dir(installDir);
        PopulateDir(sourceDir, ref projectInstallDir);
        Project.Dirs = new[] { projectInstallDir };
    }

    public void PopulateDir(DirectoryInfo sourceDir, ref WixSharp.Dir targetDir)
    {
        PopulateDir(sourceDir, sourceDir, ref targetDir);
    }

    public void PopulateDir(DirectoryInfo rootSourceDir, DirectoryInfo sourceDir, ref WixSharp.Dir targetDir)
    {
        //Example:
        //sourceDir = "C:\Users\xxx\Documents\Visual Studio 2013\Projects\MSI_Setup"
        //targetDir = "C:\TargetDir"

        List<WixSharp.File> msiFiles = new List<WixSharp.File>();
        List<WixSharp.Dir> msiDirs = new List<WixSharp.Dir>();

        FileInfo[] files = sourceDir.GetFiles();
        foreach (FileInfo file in files)
        {
            //Files must be fully qualified from the root - e.g:  new WixSharp.File(@"Files\myFile.txt")

            string msiFilePath = file.FullName;
            msiFilePath = xString.Replace(msiFilePath, rootSourceDir.FullName, rootSourceDir.Name, StringComparison.InvariantCultureIgnoreCase);

            WixSharp.File msiFile = new WixSharp.File(msiFilePath);
            msiFiles.Add(msiFile);

            Debug.WriteLine("msiFilePath=" + msiFilePath);
        }

        targetDir.Files = msiFiles.ToArray();


        DirectoryInfo[] dirs = sourceDir.GetDirectories();
        foreach (DirectoryInfo dir in dirs)
        {
            WixSharp.Dir msiDir = new WixSharp.Dir(dir.Name);
            msiDirs.Add(msiDir);

            Debug.WriteLine("dir.Name=" + dir.Name);
            PopulateDir(rootSourceDir, dir, ref msiDir);    //recursive call
        }

        targetDir.Dirs = msiDirs.ToArray();

    }

    public void CreateMSI()
    {
        //Compiler.PreserveTempFiles = true;

        Compiler.BuildMsi(Project);

        // Also create the .wxs file so we can see what was sent to WiX to build the MSI
        Compiler.BuildWxs(Project);
    }
}
Coordinator
Apr 15, 2015 at 12:56 AM
No. There is nothing wrong with your code. The ability to use the all power of a proper programming language for composing your deployment definition is exactly what makes Wix# so different comparing to other solutions.

Though in your case you may find that the existing Wix# functionality may meet your requirements quite well. Wix# allows inclusion of the files (and the whole file tree) based on the wildcard path definition. There are two complete code samples included into downloadable package.

The topic described in details in this Wiki section Including files dynamically (working with wild card source location)

Rgerdas,
Oleg
Apr 15, 2015 at 3:21 AM
Oleg and jeanmarc123,
When following your directions using the wild card I get the following error:

Error 26 The File/@Source attribute's value, '.', is not a valid long name because it contains illegal characters. Legal long names contain no more than 260 characters and must contain at least one non-period character. Any character except for the follow may be used: \ ? | > < : / * ".


I am also int the processing of trying out jeanmarc123 recommendations...
Apr 15, 2015 at 1:25 PM
Edited Apr 15, 2015 at 8:13 PM
fall95_3,

Oleg's solution is much better than mine. I just did not see it when I wrote my own implementation.
I just changed my implementation to this:
        wixProject.SourceBaseDir = @"C:\Users\xxx\Documents\Visual Studio 2013\Projects\ORPOS_Setup\MSI_Setup";
        string targetPath = @"C:\TargetDir";

        Files files = new Files(wixProject.SourceBaseDir + @"\*.*", f => true);

        Dir rootDir = new Dir(targetPath, files);
        wixProject.Dirs = new[] { rootDir };
That's much better...

Jean-Marc
Coordinator
Apr 16, 2015 at 3:55 AM
Edited Apr 16, 2015 at 4:06 AM
You can even skip the last param :)
Files files = new Files(wixProject.SourceBaseDir + @"\*.*");
In fact even the following should be OK:
Files files = new Files("*.*");
Apr 20, 2015 at 3:15 AM
Cool,
Sorry for the late response .. but thanks