6

Wix で XML ファイルを編集しようとしています。Wix 3.7 にバンドルされている WixUtilExtension を使用しています。xml ファイルは、C# アプリケーション用に Visual Studio 2010 で作成された設定ファイルです。このファイルでは、複数の文字列値を配列に格納するために使用される要素を使用しています。これは、変更されていない設定ファイルの内容です。

<configuration>
    <applicationSettings>
        <AppName.Properties.Settings>
            <setting name="StringArray" serializeAs="Xml">
                <value>
                    <ArrayOfString xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                        xmlns:xsd="http://www.w3.org/2001/XMLSchema">
                    </ArrayOfString>
                </value>
            </setting>
        </AppName.Properties.Settings>
    </applicationSettings>
</configuration>

このファイル<string>の要素に要素を追加したい。<ArrayOfString>これを行う 1 つの方法は<XmlConfig>、wix/UtilExtension 名前空間の要素を使用することです。この要素を、次のように構成ファイルを保持するコンポーネントに追加しました。

<Component Id="ProductComponent" Guid="$(var.ConfigGuid)">
    <File Source="SettingsFile.exe.config" KeyPath="yes" Id="FILE_config" />
    <util:XmlConfig
      Name="string"
      Value="My value"
      File="[INSTALLFOLDER]SettingsFile.exe.config"
      Id="String1"
      On="install"
      Action="create"
      Node="element"
      ElementPath="/configuration/applicationSettings/AppName.Properties.Settings/setting[\[]@name='StringArray'[\]]/value/ArrayOfString"
      Sequence="100"
      />
</Component>

これにより、<string>要素に 1 つの要素が追加され<ArrayOfString>ます。設定ファイルに別の要素を追加する<string>には、別の XmlConfig 要素を<Component>セットアップ プロジェクトの要素に追加する必要があります。別の Id 属性と、次のように Sequence 属性により高い値を指定します。

<util:XmlConfig
    Name="string"
    Value="My second value"
    File="[INSTALLFOLDER]SettingsFile.exe.config"
    Id="String2"
    On="install"
    Action="create"
    Node="element"
    ElementPath="/configuration/applicationSettings/AppName.Properties.Settings/setting[\[]@name='StringArray'[\]]/value/ArrayOfString"
    Sequence="101"
/>

msi のインストール後<ArrayOfString>、設定ファイルの要素は次のようになります。

<ArrayOfString xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                            xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<string>My value</string><string>My second value</string></ArrayOfString>

<XmlConfig>次のように、属性の Value 属性をプロパティの値に設定できることがわかりました。

<Property Id="STRING1VALUE" Value="My value" />
<util:XmlConfig Value="[STRING1VALUE]" ... />

これはいい。<string>可変量の要素を設定ファイルに追加できるように、ユーザーがインストール プロセスで複数の値を動的に追加できるようにしたいと考えています。私の最初のアプローチは、次の<?foreach?>ようなステートメントを使用することでした。

<?define values="My value;My second value"?>
<?foreach value in $(var.values)?>
    <util:XmlConfig
        Name="string"
        Value="$(var.value)"
        File="[INSTALLFOLDER]SettingsFile.exe.config"
        Id="String$(var.value)"
        On="install"
        Action="create"
        Node="element"
        ElementPath="/configuration/applicationSettings/AppName.Properties.Settings/setting[\[]@name='StringArray'[\]]/value/ArrayOfString"
        Sequence="101"
    />
<?endforeach?>

このアプローチにはいくつかの問題があります。

  1. foreach ステートメントは、プロパティの値に設定できないプリプロセッサ変数を使用しています。
  2. Sequence 属性の値は変わりません。

ユーザーに、値をセミコロンで区切るプロパティに文字列要素の値を格納してから、次のような foreach ステートメントでそれらを解析してもらいたいと思います。

<Property Id="VALUES" Value="My value;My second value" />
<?foreach value in [VALUES]?>
    <util:XmlConfig
        Name="string"
        Value="$(var.value)"
        File="[INSTALLFOLDER]SettingsFile.exe.config"
        Id="String$(var.value)"
        On="install"
        Action="create"
        Node="element"
        ElementPath="/configuration/applicationSettings/AppName.Properties.Settings/setting[\[]@name='StringArray'[\]]/value/ArrayOfString"
        Sequence="101"
    />
<?endforeach?>

これにより、次のエラーがスローされます。

The util:XmlConfig/@Id attribute's value, 'String[VALUES]', is not a legal identifier. 
Identifiers may contain ASCII characters A-Z, a-z, digits, underscores (_), or periods (.). 
Every identifier must begin with either a letter or an underscore.

XmlFile または XmlConfig 要素を使用して可変量の要素を作成する方法はありますか? この問題の唯一の解決策は CustomAction ですか?

4

2 に答える 2

3

Rob の回答に基づいて、Wix を使用して複数の要素を XML 構成ファイルに追加する新しいアプローチを次に示します。私は C++ コードを書きたくなかったので、CustomAction でDTFを使用しました。

区切り記号を使用して複数の要素を含む文字列を複数の XML 要素に変換する方法について説明します。

最初に、区切られた文字列を含むセットアップ ファイルにプロパティが必要です。

<Property Id="STRINGARRAY" Value="string1;string2;string3" />

もちろん、このプロパティはユーザーがダイアログで設定できます。

次に、CustomAction を記述する必要があります。DTF を利用するには、Microsoft.Deployment.WindowsInstaller.dll への参照を C# CustomAction プロジェクトに追加する必要があります。名前空間 Microsoft.Deployment.WindowsInstaller は、そのプロジェクトの using ディレクティブと共に含める必要があります。私の CustomAction は次のようになります。

[CustomAction]
public static ActionResult Insert(Session session)
{
    string strings = session["STRINGARRAY"];
    string[] stringArray = strings.Split(';');
    Database db = session.Database;
    View view = db.OpenView("select * from `XmlConfig`");
    string xpath = "/configuration/applicationSettings/AppName.Properties.Settings/setting[\\[]@name='StringArray'[\\]]/value/ArrayOfString";
    for (int i = 0; i < stringArray.Length; i++)
    {
        string id = String.Format("String{0}", i);
        int sequence = 100 + i;
        string value = stringArray[i].Trim();
        Record rec = new Record(
            id,
            "[INSTALLFOLDER]SettingsFile.exe.config",
            xpath,
            null,
            "string",
            value,
            273,
            "ProductComponent",
            sequence);
        view.InsertTemporary(rec);
    }
    db.Close();
    return ActionResult.Success;
}

ここでは、最初に Property StringArray がローカル変数に読み込まれ、文字列配列に変換されます。次の行は、インストーラーが使用する現在のデータベースへの接続を確立します。テーブル XmlConfig のハンドルが作成されます。これは、XML 要素が追加されるテーブルです。そのテーブルに正しい値を挿入するには、そのようなテーブルを含むインストーラー ファイルを作成し、orca や InstEd などのエディターでそのテーブルを確認することをお勧めします。

xpath では、二重のバックスラッシュを使用してバックスラッシュをエスケープする必要があります。id 変数は、単純な文字列と数値を使用して一時レコードの名前を保持し、問題なく機能します。要素ごとにシーケンスをインクリメントする必要があります。flags 列の値に関するドキュメントは見つかりませんでしたが、作成された要素の値は 273 に設定され、削除された要素の値は 289 に設定されていることがわかりました。

レコードに正しい値が入力されると、ビュー オブジェクトの InsertTemporary メソッドを使用して XmlConfig テーブルに追加されます。これは、区切られた文字列で見つかった各要素に対して行われます。

私が遭遇した問題は、XmlConfig テーブルが存在しない場合、この CustomAction が失敗することです。この問題に対処するために、セットアップ ファイルに次のコードを追加しました。これにより、要素が XML ファイルに追加され、その要素がすぐに削除されます。よりクリーンなソリューションがあると思いますが、これが私にとって最も簡単なソリューションでした。

<util:XmlConfig
    Name="string"
    Value="Dummy"
    File="[INSTALLFOLDER]SettingsFile.exe.config"
    Id="DummyEntry"
    On="install"
    Action="create"
    Node="element"
    ElementPath="/configuration/applicationSettings/AppName.Properties.Settings/setting[\[]@name='StringArray'[\]]/value/ArrayOfString"
    Sequence="1" />
<util:XmlConfig
    On="install"
    Action="delete"
    Id="DeleteDummyEntry"
    Node="element"
    File="[INSTALLFOLDER]SettingsFile.exe.config"
    VerifyPath="/configuration/applicationSettings/AppName.Properties.Settings/setting[\[]@name='StringArray'[\]]/value/ArrayOfString/string"
    ElementPath="/configuration/applicationSettings/AppName.Properties.Settings/setting[\[]@name='StringArray'[\]]/value/ArrayOfString"
    Sequence="2" />

最後に、CustomAction をセットアップ プロジェクトに追加する必要があります。セットアップ プロジェクトに CustomAction プロジェクトへの参照を追加することで、バイナリの場所を次のように指定できます。

<Binary Id="XmlCustomActionDLL" SourceFile="$(var.XmlCustomAction.TargetDir)XmlCustomAction.CA.dll" />

CustomAction はすぐに実行する必要があります。そうしないと、セッション変数にアクセスできません。

<CustomAction Id="CA_XmlCustomAction" BinaryKey="XmlCustomActionDLL" DllEntry="Insert" Execute="immediate" Return="check" />
<InstallExecuteSequence>
  <Custom Action="CA_XmlCustomAction" Before="RemoveRegistryValues" />
</InstallExecuteSequence>

インストール シーケンスにおける CustomAction の適切な位置を決定するために、 Bob Arnson によるこの記事に依存しました。

于 2013-04-04T10:17:42.887 に答える
0

はい、可能ですが、インストール時にこれを決定したい場合は、プリプロセッサはオプションではありません。プリプロセッサは、ビルド プロセス中に実行されます。

XmlConfig必要なものを取得するには、任意の長さのユーザー データ セットを取得し、一時的な行をテーブルに追加する別のカスタム アクションを作成する必要があります。のWcaAddTempRecord()関数src\ca\wcautil\wcawrap.cppはその作業を行うことができます。これは、テーブルに行を追加するためsrc\ca\wixca\dll\RemoveFoldersEx.cppに使用する非常に良い例です。同様にやりたいと思うでしょう。WcaAddTempRecord()RemoveFile

于 2013-04-03T12:58:17.413 に答える