【问题标题】:how to populate a text box in wix toolset using xml file included in the msi?如何使用 msi 中包含的 xml 文件填充 wix 工具集中的文本框?
【发布时间】:2019-08-07 12:44:59
【问题描述】:

我的安装程序中包含一个名为 App.xml 的文件(将安装在客户端计算机上),我想从中加载数据并将其显示给用户,以便他可以操作将要安装的内容/如何安装使用系统。

我尝试使用 Xml 文件扩展/自定义操作,在线检查,找不到加载嵌入在安装程序中的源文件的方法。

我的文件是: <App> <Text>bla bla</text></App>

我希望安装程序显示“bla bla”文本,并且用户可以更改它,以后可以像往常一样通过扩展程序保存它..

谢谢!

【问题讨论】:

    标签: c# xml wix installation wix-extension


    【解决方案1】:

    我遇到了类似的问题。寻找一个允许您在 InstallUISequence 期间使用 XML 文件的解决方案,在安装文件之前,您似乎需要将自定义表添加到您的 WiX 定义中,如 here 所述。

    基本上,您在 .wxs 文件中创建一个 CustomTable 元素,例如:

    <CustomTable Id="App">
        <Text>bla bla</Text>
    </CustomTable>
    

    然后您可以在 c# 自定义操作中通过创建视图查询来读取它以查找所需的属性:

    using (View view = session.Database.OpenView("SELECT 'Text' FROM 'App'"))
    {
        view.Execute();
        // access view properties and turn them into some object you want to manipulate
    }
    

    我承认对于该视图对象将拥有的内容有些无知,但我知道您可以遍历其记录或获取各个列,在属性中四处寻找最终应该会找到您想要的值。 下一步是使用值填充组合框元素

    <Control Id="DropdownSelectLabel" Type="Text" X="50" Y="65" Width="200" Height="15" TabSkip="no" Text="&amp;Select a value:">
    </Control>
    <Control Id="DropdownSelect" Type="ComboBox" Height="16" Width="200" X="60" Y="80" Property="MY_PROPERTY_KEY" ComboList="yes">
        <ComboBox Property="MY_PROPERTY_KEY">
            <!-- Optional prepopulate value-->
            <ListItem Text="[dummy_text]" Value="[dummy_value]" />
        </ComboBox>
    </Control>
    

    我正在使用在 InstallUISequence 期间运行的自定义 c# 操作填充它,通过 Visual Studio 构建

    <!-- Custom action for populating the combobox -->
    <CustomAction Id="CA_PopulateComboBox" BinaryKey="BIN_CustomActions" DllEntry="PopulateComboBox" Execute="firstSequence" />
    
    <!-- Binaries for the custom action -->
    <Binary Id="BIN_CustomActions" SourceFile="..\PATH-TO-YOUR-CUSTOM-ACTION-BIN-RELEASE.CA.dll" />
    
    <!-- Schedule the custom action -->
    <InstallUISequence>
        <Custom Action="CA_PopulateComboBox" Before="LaunchConditions" />
    </InstallUISequence>
    

    自定义操作如下所示:

    public class CustomActions
    {
        /// <summary>
        /// Populates the ComboBox UI Element.
        /// </summary>
        /// <param name="session">The session.</param>
        [CustomAction]
        public static void PopulateComboBox(Session session)
        {
            session.Log("Populating the combobox with certificates");
    
            // Clear the combobox (unecessary if it starting empty)
            View view = session.Database.OpenView("DELETE FROM ComboBox WHERE ComboBox.Property='MY_PROPERTY_KEY'");
            view.Execute();
    
            view = session.Database.OpenView("SELECT * FROM ComboBox");
            view.Execute();
    
            List<ComboBoxRecordWrapper> valuesToAdd = PopulateValuesObjects(session); // Add the logic to read your xml values from the session object here
    
            var index = 1;
            foreach (ComboBoxRecordWrapper valueObject in valuesToAdd)
            {
                session.Log($"Adding value to the combobox: {valueObject.Text} - {valueObject.Value} {Environment.NewLine}Order: {valueObject.Order}");
    
                view.Modify(ViewModifyMode.InsertTemporary, recordWrapper.ToRecord());
                view.Execute();
                index++;
            }
    
            view.Close();
        }
    }
    
    /// <summary>
    /// Class ComboBoxRecordWrapper. Wraps objects that should be represented in a combobox element in the installer
    /// </summary>
    public class ComboBoxRecordWrapper
    {
        /// <summary>
        /// Gets or sets the property that this element's value will be stored as if the element is selected
        /// </summary>
        /// <value>The property.</value>
        public string Property { get; set; }
    
        /// <summary>
        /// Gets or sets the order that this element appears in the combobox
        /// </summary>
        /// <value>The order.</value>
        public int Order { get; set; }
    
        /// <summary>
        /// Gets or sets the value of the combobox option. This is what will be available to the UI element as a returned value
        /// </summary>
        /// <value>The value.</value>
        public string Value { get; set; }
    
        /// <summary>
        /// Gets or sets the text that will be displayed for this element
        /// </summary>
        /// <value>The text.</value>
        public string Text { get; set; }
    
        /// <summary>
        /// Initializes a new instance of the <see cref="ComboBoxRecordWrapper"/> class.
        /// </summary>
        /// <param name="property">The property.</param>
        /// <param name="order">The order.</param>
        /// <param name="value">The value.</param>
        /// <param name="text">The text.</param>
        public ComboBoxRecordWrapper(string property, int order, string value, string text)
        {
            this.Property = property;
            this.Order = order;
            this.Value = value;
            this.Text = string.IsNullOrEmpty(text) ? value : text;
        }
    
        /// <summary>
        /// Converts to a record to add to the MSI database.
        /// </summary>
        /// <returns>Record.</returns>
        public Record ToRecord()
        {
            var record = new Record(4);
            record.SetString(1, this.Property);
            record.SetInteger(2, this.Order);
            record.SetString(3, this.Value);
            record.SetString(4, this.Text);
            return record;
        }
    }
    
    

    【讨论】:

    • 关于自定义操作的重要说明,您需要使用 projectname.CA.dll 让 Visual Studio 自动包含您在自定义操作中引用的任何额外依赖项(例如 Json.NET)跨度>
    【解决方案2】:

    这将是您必须通过自定义操作提供的自定义功能。从高级设计中,我看到您在命令行上传递了 xml 文件的路径。在运行时,您的自定义操作将读取文件中的节点并设置文本框正在使用的适当属性。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-02-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多