Search code examples
c++visual-studiowixinstrumentationetw

Customize the event instrumentation manifest of a "base" project to match the needs of "derived" projects


I'm working on two different C++ DLL-projects that share most of their code. So, I have one base project that compiles to Base.lib and two "derived" projects that compile to Derived1.dll and Derived2.dll and link against Base.lib. Those derived DLLs shall be shipped independently. The user does not even know that they are related.

Now I want both of my DLLs to be windows event providers. All events that I want to be logged occur in Base.lib. So, I added an Instrumentation.man to that project and made it part of the build. Its content looks roughly like this:

<?xml version="1.0" encoding="UTF-16"?>
<instrumentationManifest xsi:schemaLocation="http://schemas.microsoft.com/win/2004/08/events eventman.xsd" xmlns="http://schemas.microsoft.com/win/2004/08/events" xmlns:win="http://manifests.microsoft.com/win/2004/08/windows/events" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:trace="http://schemas.microsoft.com/win/2004/08/events/trace">
  <instrumentation>
    <events>
      <provider name="Company-Provider-Base" guid="{12345678-1234-1234-1234-1234567890ABCD}" symbol="provider" resourceFileName="some/path/to.dll" messageFileName="some/path/to.dll" message="$(string.provider.message)">
        <events>
            ...
        </events>
      </provider>
    </events>
  </instrumentation>
  <localization>
    <resources culture="en-US">
      <stringTable>  
        <string id="provider.message" value="Base Provider" />
        ...
      </stringTable>
    </resources>
  </localization>
</instrumentationManifest>

I use mc.exe to compile this to a resource file and a header file. The header file is being included by other source files of my Base project.

Now this works surprisingly well! All events are logged properly for both of the DLLs.

However, of course, both DLLs now share the same provider with the same name, guid, and message.

So, my actual question is this: How can I make the provider element in Instrumentation.man customizable in a way that my DLL-projects can fill in their own name, guid, and message attributes?

I'm using WiX to create my Setup kits. WiX allows me to customize the resourceFileName and messageFileName attributes of the provider element (both point to dummies in the original file) just when the DLLs are deployed on the target system so that they can be referenced properly. However, WIX doesn't offer a similar way (at least I don't see it) to alter the other attributes just as smoothly, which would be exactly what I want.

I also noticed that WiX offers to customize the parameterFileName attribute. Unfortunately, I cannot find any information how these parameters work. I understand that I can put %%n into the strings in the manifest and then the parameter with the identifier n will be inserted. But I don't understand where and how to declare those parameters plus, I don't know if I can use them in the attributes I want to customize so that they wouldn't help me at all.


Solution

  • I ended up writing my own XML modification tool (in C# as described here, but any other language will do, too) that takes the manifest file and the solution name and replaces the attribute values accordingly.

    To make this work automatically, I added a Pre-Build Event to the Base project that calls this tool and passes it the manifest file and the $(SolutionName).

    This solution is neither pretty nor easily scalable, but it works.