【问题标题】:How to get local path for payload in WiX/Burn Managed Bootstrapper Application?如何在 WiX/Burn Managed Bootstrapper Application 中获取有效负载的本地路径?
【发布时间】:2014-09-25 10:20:27
【问题描述】:

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

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

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

我首先对 BootstrapperApplicationData.xml 文件进行反序列化,这样我就有了关于可能安装了哪些 MSI 的信息,但它仍然不能帮助我确定 MSI 的来源。

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

编辑:这是我如何引用所有安装程序的示例:

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

【问题讨论】:

  • 负载下载是已经存在于松散文件中、嵌入到分离的容器中还是嵌入到附加的容器中?请显示 MsiPackage 和 Container 元素。
  • 我附上了我用来引用上面安装程序的 XML。谢谢!
  • 你有什么想法吗?

标签: wix windows-installer burn


【解决方案1】:

cache.cppGetLastUsedSourceFolder函数中,可以看到引擎从WixBundleLastUsedSource变量中获取源文件夹,如果WixBundleLastUsedSource未设置,则为WixBundleOriginalSource变量的父目录。

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

【讨论】:

  • 谢谢!实际上我昨天就想出了答案,但这正是我所做的!
【解决方案2】:

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

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

    }

}

【讨论】:

  • 如果您阅读我的帖子,您会发现我的 MSI 没有嵌入,
  • 我刚刚尝试了这段代码,因为我现在确实需要提取 MSI。我收到一个错误,因为在运行时找不到“winterop.dll”。有什么想法吗?
  • winterop.dll 文件是 WiX SDK 的一部分(位于 WIX 安装的 /bin 文件夹中)。您需要将它与其他依赖程序集一起包含在您的 &lt;PayloadGroup&gt; 片段中。
  • 谢谢!不敢相信你这么快就回答了这么老的问题!
  • 我使用的是 wix 3.10,似乎在任何地方都找不到 Unbinder 类。您引用什么文件才能访问 Unbinder 类?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-04-08
  • 1970-01-01
  • 2014-01-26
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多