0
votes

I am currently working in a WiX/Burn Managed Bootstrapper Application and cannot figure out how to get the local path for a payload (MSI).

I let the user select which applications they want to install in my custom UI, and I want to not show applications for which the MSI is missing. I also need to see information in the MSI's database.

I know I can determine missing payloads by handling "ResolveSource" but that doesn't happen until right before the application in installed.

I deserialize the BootstrapperApplicationData.xml file first thing so I have information about which MSIs MIGHT be installed, but it still doesn't help me determine the source of the MSIs.

Does anyone know how to determine the local path to a payload?

EDIT: Here is an example for how I reference all the installers:

<MsiPackage Id="AppName"
      SourceFile="$(var.ProjectName.TargetDir)ProjectName.msi"
      Name="MSI\ProjectName.msi"
      Compressed="no"/>
2
Are the payloads downloads, already present in loose file, embedded in a detached container or embedded in the attached container? Please show the MsiPackage and Container elements.Tom Blodget
I attached the XML I used to reference the installer above. Thank you!dspiegs
Do you have any ideas?dspiegs

2 Answers

1
votes

In the GetLastUsedSourceFolder function in cache.cpp, you can see that the engine gets the source folder from the WixBundleLastUsedSource variable, and the parent directory of the WixBundleOriginalSource variable if WixBundleLastUsedSource isn't set.

You can use this along with the Name attribute of the WixPayloadProperties element in the BootstrapperApplicationData.xml file to predetermine where the engine will look for a payload. Note that the engine will actually look in the cache first.

1
votes

The MSI files are embedded into the bundle .exe and aren't extracted from the bundle until right before the application is installed, which corresponds to when the ResolveSource event fires. However, if you really want to get this information, you can programatically extract the MSI files yourself and inspect them using the WiX DTF library (wix.dll in the /bin folder of your WiX install).

using Microsoft.Tools.WindowsInstallerXml;

private void ExtractEmbeddedMsiInstallers()
{

    var tmpFolder = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName());
    var bundlePath = Engine.StringVariables["WixBundleOriginalSource"];

    Unbinder unbinder = null;

    try
    {
        unbinder = new Unbinder();

        //The next line will extract the MSIs into the tmpFolder in a subfolder named "AttachedContainer"
        unbinder.Unbind(bundlePath, OutputType.Bundle, tmpFolder);
    }
    finally
    {
        if (null != unbinder)
            unbinder.DeleteTempFiles();
    }

}

You also mentioned needing to inspect data in the MSI database. Here's a sample of how to do that:

using (var database = new InstallPackage(msiFilePath, DatabaseOpenMode.Transact) { WorkingDirectory = _someTempFolder })
{

    if (database.Tables.Contains("CustomAction"))
    {
        using (View view = database.OpenView("SELECT `Action`, `Type`, `Source`, `Target` FROM `CustomAction`"))
        {
            view.Execute();
            foreach (Record rowRecord in view)
                using (rowRecord)
                {
                    var actionName = rowRecord.GetString(1);
                    var actionType = rowRecord.GetInteger(2);
                    var binaryName = rowRecord.GetString(3);
                    var methodName = rowRecord.GetString(4);

                    //Do something with the values
                }
        }

    }

}