如何使用 msbuild 更改检测清单中的属性值?

How to change the value of an attribute in an instrumentation manifest with msbuild?

Microsoft EventRegister Tool 在项目编译期间创建一个检测清单文件和一个资源文件。我想在编译后将这些文件移动到另一个路径,并使用 msbuild 更改检测清单文件中的两个属性。属性的取值都是一样的,每一个都代表伴随资源文件的路径。看来我无法正确使用msbuild修改属性的语法,我认为它与两件事有关。

首先,检测清单文件不包含经典的 xml 文件声明。其次,检测清单包括命名空间。

到目前为止,感谢博客 post "Updating XML files with MSBuild" by Sayed Ibrahim Hashimi,我想到的是:

<PropertyGroup>
    <SourceManifestAssembly>$(OutputPath)Name.etwManifest.dll</SourceManifestAssembly>
    <DestinationManifestAssembly>$(Programdata)\MyCompany\MyProduct.0.0.0\Name.etwManifest.dll</DestinationManifestAssembly>
    <SourceManifest>$(OutputPath)Name.etwManifest.man</SourceManifest>
    <DestinationManifest>$(Programdata)\MyCompany\MyProduct.0.0.0\Name.etwManifest.man</DestinationManifest>
</PropertyGroup>
<ItemGroup>
    <UpdateManifest Include="UpdatemessageFileName">
        <NewValue>$(DestinationManifestAssembly)</NewValue>
        <Namespaces>&lt;Namespace Prefix='x'  Uri='http://schemas.microsoft.com/win/2004/08/events' /&gt;</Namespaces>
        <XPath>//x:events/provider/@messageFileName</XPath>
    </UpdateManifest>
    <UpdateManifest Include="UpdateresourceFileName">
        <NewValue>$(DestinationManifestAssembly)</NewValue>
        <Namespaces>&lt;Namespace Prefix='x'  Uri='http://schemas.microsoft.com/win/2004/08/events' /&gt;</Namespaces>
        <XPath>//x:events/provider/@resourceFileName</XPath>
    </UpdateManifest>
</ItemGroup>
<Target Name="AfterBuild">
    <Copy SourceFiles="$(SourceManifestAssembly)" DestinationFiles="$(DestinationManifestAssembly)" />
    <Copy SourceFiles="$(SourceManifest)" DestinationFiles="$(DestinationManifest)" />
    <XmlPoke XmlInputPath="$(DestinationManifest)" Query="%(UpdateManifest.XPath)" Value="%(UpdateManifest.NewValue)" Namespaces="%(UpdateManifest.Namespaces)" />
</Target>

这会处理复制,但不会更改属性值。

检测清单文件如下所示:

<instrumentationManifest xmlns="http://schemas.microsoft.com/win/2004/08/events">
<instrumentation xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:win="http://manifests.microsoft.com/win/2004/08/windows/events">
    <events xmlns="http://schemas.microsoft.com/win/2004/08/events">
        <provider name="MyCompany-MyProduct-MyLog" guid="{658FE45E-C2D4-4E73-82BB-6441A0348D9B}" resourceFileName="C:\Documents\Visual Studio\Projects\Name\bin\Debug\Name.etwManifest.dll" messageFileName="C:\Documents\Visual Studio\Projects\Name\bin\Debug\Name.etwManifest.dll" symbol="MyCompanyMyProductMyLog">
        </provider>
    </events>
</instrumentation>

需要更改的属性是//provider/@resourceFileName//provider/@messageFileName

在 Windows Installer XML Util 扩展中,元素 EventManifest 用于安装事件清单。此元素会在安装期间安排配置文件更改,这与上面描述的完全相同。在启用安装日志的情况下 运行 安装之后,我简单地查看了日志并检查了 SchedXmlFile 条目。我在那里找到了以下 XPath 表达式:

/*/*/*/*[@messageFileName]

我尝试了这段代码,当您使用以下符号时,似乎可以省略 XPath 名称空间:

<PropertyGroup>
    <SourceManifestAssembly>$(OutputPath)Name.etwManifest.dll</SourceManifestAssembly>
    <DestinationManifestAssembly>$(Programdata)\MyCompany\MyProduct.0.0.0\Name.etwManifest.dll</DestinationManifestAssembly>
    <SourceManifest>$(OutputPath)Name.etwManifest.man</SourceManifest>
    <DestinationManifest>$(Programdata)\MyCompany\MyProduct.0.0.0\Name.etwManifest.man</DestinationManifest>
</PropertyGroup>
<ItemGroup>
    <UpdateManifest Include="UpdatemessageFileName">
        <NewValue>$(DestinationManifestAssembly)</NewValue>
        <XPath>/*/*/*/*/@messageFileName</XPath>
    </UpdateManifest>
    <UpdateManifest Include="UpdateresourceFileName">
        <NewValue>$(DestinationManifestAssembly)</NewValue>
        <XPath>/*/*/*/*/@resourceFileName</XPath>
    </UpdateManifest>
</ItemGroup>
<Target Name="AfterBuild">
    <Copy SourceFiles="$(SourceManifestAssembly)" DestinationFiles="$(DestinationManifestAssembly)" />
    <Copy SourceFiles="$(SourceManifest)" DestinationFiles="$(DestinationManifest)" />
    <XmlPoke XmlInputPath="$(DestinationManifest)" Query="%(UpdateManifest.XPath)" Value="%(UpdateManifest.NewValue)" />
</Target>