我正在编写一个 PowerShell 脚本来操作一些 Windows Installer XML (WiX)。我正在使用 .NET 3.5 中的新 XML API 来执行此操作,因为我发现它比 DOM 更易于使用。以下脚本片段断然拒绝工作:
[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 进行调试,我看到 $strings 已设置为 IEnumerator,而不是预期的 IEnumerable<XElement>。使用单个 MoveNext 和 Current 测试 IEnumerator 指示“Current =”,大概是 $null。
奇怪的是,相同的技术在以前的脚本中也有效。完全相同的代码,但具有不同的变量名和字符串文字。并且刚刚尝试调试该脚本(以验证行为),它现在似乎也显示相同的行为。