1

Windows Installer XML (WiX) を操作する PowerShell スクリプトを作成しています。これを行うために、.NET 3.5 の新しい XML API を使用しています。これは、DOM よりも操作が簡単な API であることがわかったからです。次のスクリプト フラグメントは、きっぱりと動作を拒否しています。

[System.Reflection.Assembly]::LoadWithPartialName("System.Xml.Linq") | Out-Null

# Basic idea: Iterate through en.wxl's l10ns, get string for each l10n, search all wxs files for that value.

pushd "C:\temp\installer_l10n"
$wxlFileName = "${pwd}\en.wxl"
$wxl = [System.Xml.Linq.XDocument]::Load($wxlFileName)
$strings = $wxl.Descendants("String")
$strings
$strings | foreach {
    $_
}
popd

スクリプトは、各 <String> タグを別々の行に出力する必要があります。このバグが解決されたら、もっと面白いことをするようにします;-)

XML ドキュメントは、標準の WiX ローカリゼーション ファイルです。

<?xml version="1.0" encoding="utf-8" ?>
<WixLocalization Culture="en-US" xmlns="http://schemas.microsoft.com/wix/2006/localization">
   <String Id="0">Advertising published resource</String>
   <String Id="1">Allocating registry space</String>
   ...
</WixLocalization>

$strings は $null ではなく (明示的にテストしました)、$wxl を書き込みホストにすると、ドキュメントが読み込まれていることがわかります。$strings を Get-Member にパイプすると、「get-member にオブジェクトが指定されていません」というエラーが返され、write-host $strings は何もしません。$wxl.Descendants("WixLocalization") も試してみましたが、同じ結果が得られました。$wxl.Root や $wxl.Nodes などは期待どおりに機能します。PowerShell ISE でデバッグすると、予想される IEnumerable<XElement> ではなく、$strings が IEnumerator に設定されていることがわかります。IEnumerator を 1 つの MoveNext でテストし、次に Current でテストすると、"Current = "、おそらく $null であることが示されます。

奇妙なことに、以前のスクリプトでも同じ手法が機能していました。まったく同じコードですが、変数名と文字列リテラルが異なります。そして、そのスクリプトも(動作を確認するために)デバッグしようとしたところ、同じ動作を表示しているようです。

4

2 に答える 2

5

この問題に興味をそそられたので、いろいろと調べてみました。PowerShell をいじり、Web を検索した後、解決策を見つけました。

実際のコードは Jamie Thomson の功績によるものです。 http://dougfinke.com/blog/index.php/2007/08/07/using-xmllinq-in-powershell/

欠けている部分は、XML ファイルで名前空間を処理することです。これがあなたのために働くはずのコードです:

[System.Reflection.Assembly]::LoadWithPartialName("System.Xml.Linq") | Out-Null
# Basic idea: Iterate through en.wxl's l10ns, get string for each l10n, search all wxs files for that value.

$wxlFileName = "${pwd}\en.wxl"
$wxl = [System.Xml.Linq.XDocument]::Load($wxlFileName)
$ns = [System.Xml.Linq.XNamespace]”http://schemas.microsoft.com/wix/2006/localization”
$strings = $wxl.Descendants($ns + "String")
foreach ($string in $strings) {
    $string
}
于 2009-02-09T07:06:05.277 に答える
1

DOMを使用したくないとおっしゃっていましたが、これが機能しない理由はありますか?

[xml]$test = gc .\test.wml                                                                                        
$test                                                                                                             
$test.WixLocalization                                                                                             
$test.WixLocalization.String

これは以下を出力します:

PS> $ test.WixLocalization.String

Id #text-------
0
公開されたリソースのアドバタイズ
1レジストリスペースの割り当て

その時点でそれをForeachすることはそれほど難しいことではないはずです。

于 2009-02-06T18:52:07.857 に答える