如何在WiX / Burn Managed Bootstrapper应用程序中获取有效负载的本地路径?

时间:2014-09-17 23:51:04

标签: wix windows-installer burn

我目前正在使用WiX / Burn Managed Bootstrapper应用程序,无法弄清楚如何获取有效负载(MSI)的本地路径。

我让用户选择要在我的自定义用户界面中安装哪些应用程序,并且我想显示缺少MSI的应用程序。我还需要在MSI的数据库中查看信息。

我知道我可以通过处理“ResolveSource”确定丢失的有效负载,但直到安装应用程序之前才会发生。

我首先对BootstrapperApplicationData.xml文件进行反序列化,因此我可以获得有关可能安装哪些MSI的信息,但它仍无法帮助我确定MSI的来源。

有谁知道如何确定有效载荷的本地路径?

编辑:以下是我引用所有安装程序的示例:

<MsiPackage Id="AppName"
      SourceFile="$(var.ProjectName.TargetDir)ProjectName.msi"
      Name="MSI\ProjectName.msi"
      Compressed="no"/>

2 个答案:

答案 0 :(得分:1)

cache.cpp中的GetLastUsedSourceFolder函数中,您可以看到引擎从WixBundleLastUsedSource变量获取源文件夹,以及WixBundleOriginalSource变量的父目录WixBundleLastUsedSource未设置。

您可以将此与BootstrapperApplicationData.xml文件中Name元素的WixPayloadProperties属性一起使用,以预先确定引擎在哪里查找有效负载。请注意,引擎实际上会首先查看缓存。

答案 1 :(得分:1)

MSI文件嵌入到.exe文件中,直到安装应用程序之前才从包中提取,这与ResolveSource事件触发时相对应。但是,如果确实想要获取此信息,您可以自己以编程方式提取MSI文件,并使用WiX DTF库(WiX安装的/ bin文件夹中的wix.dll)检查它们。 / p>

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();
    }

}

您还提到需要检查MSI数据库中的数据。以下是如何执行此操作的示例:

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
                }
        }

    }

}