Access content of packaged XML file within custom action during installer's UI phase

让人想犯罪 __ 提交于 2021-02-11 14:53:06

问题


I am maintaining a WiX installer that already has a working UI and that executes a couple of custom actions during the UI phase. The current and working state depends on a number of property values being hardcoded in the .wxs file. I would like to change this: Instead of hardcoding the values I would like to gather them dynamically at installation time.

I need this to happen already while the UI is being shown, because the property values impact the UI logic. Now the problem is that fragments of the property values should come from an XML file that is packaged inside the installer. The XML file will also be installed on the target machine when the UI phase is complete.

The only way I have found so far how I can access a file packaged in the installer from within a custom action is by getting its path with Session.GetTargetPath() as shown in this C# snippet:

[CustomAction]
public static ActionResult GetInfoFromXml(Session session)
{
    string xmlFolderPath = session.GetTargetPath("XmlFolder");

    [...]  // deserialize and process the file
}

This fails with the following message in the installer log:

Exception thrown by custom action:
System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. ---> System.ArgumentException: The directory name is invalid. XmlFolder
   at Microsoft.Deployment.WindowsInstaller.Session.GetTargetPath(String directory)

After some thinking the failure seems predictable: The custom action is executed in the installer's UI phase, so nothing has been installed yet and GetTargetPath therefore cannot return anything useful yet.

So the question is: How can I access the content of the XML file from within my custom action that is executed during the installer's UI phase?

If I can achieve my goal by packaging the XML file twice, let's say once for getting it installed onto the target machine, and a second time just for getting it processed by the custom action, that would be fine. I don't know how to do that or if it's possible at all, I'm still too much of a WiX beginner.

Note: I have also looked into "harvesting" the content of the XML file at build time, i.e. how to generate a .wxs snippet from the XML file at build time, but there seems to be no easy way built into WiX to do that.


回答1:


The solution to my problem was

  1. Add the XML file to the Binary table of the installer.
  2. Obtain the data from the Binary table in the custom action, convert the data to a string, then deserialize from that string.

Here is the Binary table entry from the .wxs:

<Binary Id="XmlFile" SourceFile="foo.xml" />

This is the custom action part:

[CustomAction]
public static ActionResult GetInfoFromXml(Session session)
{
    string xmlFileContent = GetStringDataFromBinaryTable(
        session,
        "XmlFile");

    [...]  // deserialize and process the XML file content
}

And here is a generic reusable method I wrote that extracts string data from the Binary table:

using Microsoft.Deployment.WindowsInstaller;
using System.IO;

public static string GetStringDataFromBinaryTable(Session session, string binaryTableEntryId)
{
  const string BinaryTableName = "Binary";
  const string NameColumnName = "Name";
  const string DataColumnName = "Data";

  Database db = session.Database;

  string selectQuery = string.Format(
    "SELECT `{2}` FROM `{0}` WHERE `{0}`.`{1}` = '{3}'",
    BinaryTableName,
    NameColumnName,
    DataColumnName,
    binaryTableEntryId);
  View view = db.OpenView(selectQuery);
  view.Execute();

  Record record = view.Fetch();

  Stream stream = record.GetStream(DataColumnName);
  StreamReader streamReader = new StreamReader(stream);
  string dataAsString = streamReader.ReadToEnd();

  view.Close();

  return dataAsString;
}


来源:https://stackoverflow.com/questions/60945888/access-content-of-packaged-xml-file-within-custom-action-during-installers-ui-p

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!