Using ETW Events within a Windows Phone 8 Application
The sample code used in this article can be found
here and is based on the standard “Windows Phone Direct 3D with XAML App” project template from Visual Studio.
Your ETW manifest is an XML file which defines what your events look like so that event viewers can intelligently display your events once you've collected them in a log.
Windows Phone uses the same manifests as Windows, so the regular documentation applies:
The sample manifest that we'll be using can be
If you're developing a regular application you will want to use the developer GUID for your provider:
If you're writing a library you're going to want to select your own GUID that doesn't clash with the standard app developer one and then publicize it so that developers can collect it when they use your library.
Compiling the Manifest
In order to decode your events from the ETL (Event Trace Log) the system needs to read your manifest out of a binary that has your manifest compiled into it as a resource. While you can register arbitrary providers (and their associated manifests) on your
local machine, you can't do this on the Phone, so the Phone won't be able to recognize your events. To work around this we will be post-processing your events on your local machine using an x86 (or x64) resource only dll that includes your manifest.
- First, add a new project to your solution:
File -> Add -> New Project -> Other Languages -> Visual C++ -> Win32 -> Win32 Project
While the name is generally unimportant for clarity sake we’ll go with the name of the provider, In this case "Phone-Direct3DXaml-App"
- In the wizard select an "Application Type" of "DLL", "Empty Project" and clear any other check boxes:
- Add the manifest to your project (so that it appears in your solution and you can edit it in VS)
- Add the following pre-build command (substitute your manifest name:
mc -um Phone-Direct3DXaml-App.man
- Specify the "No Entry Point" option in the linker (since this will be a resource only dll):
- Make sure the project is set to build with everything else by going to Build -> Configuration Manager and selecting "Build" next to your project:
Registering Your Manifest
Registering your manifest on your local machine allows you to decode your events so that they don't show up as "unknown". If you run VS as admin you can have you can do this as part of the compile step, otherwise you can do it manually using the
same commands as below (just expand the paths):
- Right click your project -> Properties -> Config… -> Build Events -> Post-Build Events -> Command Line (hit the little down arrow and click <edit>)
- Paste in the follow lines:
wevtutil um "$(ProjectDir)Phone-Direct3DXaml-App.man"
wevtutil im $(ProjectDir)Phone-Direct3DXaml-App.man /mf:"$(TargetPath)" /rf:"$(TargetPath)"
The above lines unregister your provider (which may, or may not already be registered) and then reregister it providing full paths to your resource dll. Unregistering is required to update your provider with any new changes you may have made.
- Next, make sure that the resource project is set to build first in your solution (so that it generates it's files before anyone can use them) by right clicking on your solution -> Project Build Order -> Dependencies. Under your native project select
the manifest project and then verify in the "Build Order" tab that it will build first.
So we have our resource events, now, let's use them!
- Optional Step - easy header access:
- Add the header file generated from your manfiest to your project. If you are using the above steps to compile your manifest then you should find the header in the root of your manifest project. The file will be added with a small link icon to indicate that
the file is in a different location to the rest of your project files
- In case you ever change anything, and so that you don't have to #include the full path to the header file every time create a EtwEvents.h file that includes your generated header file:
- Add a call to the EventRegister* macro before using any of the marker macros for the first time
- Add a call to the EventUnregister* macro during your shutdown code
- You can now include "EtwEvents.h" wherever needed and simply call EventWrite<func> (you can find the names in your ETW header).
Writing Events from Managed Code
Our first order of business will be creating a WinRT class to expose the events to Managed code:
- Right click on your existing Native WinRT project (or, if you don't have one, add a new one) -> Add -> Class.
- In the wizard give your class whatever name you like (we'll be using Etw)
- Since we need this to be a WinRT class you'll need to sprinkle some WinRT sugar around your class definition (Etw.h) to make it visible to managed code. At the same time we're going to make the constructor private and remove the destructor since the Etw
class won't maintain any state and all of its members will be static.
public ref class
Don’t forget to add the namespace declaration to Etw.cpp as well.
- Now add functions for provider registration and deregistration and a function that represents each event macro in your header (search for "EventWrite").
Recommendation: make your functions static (which matches the private constructor above) so that you don't have to instantiate the
Etw object everywhere.
public ref class
static void RegisterProvider();
static void UnregisterProvider();
static void WriteInitialized();
static void WriteFramerate(float fps);
static void WriteFrameStart();
static void WriteFrameEnd();
Word to the wise: your function names cannot match your task names. In the example above you cannot have a function named simply "Initialized" since that is the same name as one of my tasks (you'll know you've done this when you get Template cast
- Now, in your app constructor / initializer code you can run
Etw.RegisterProvider() and in your shutdown code you can call
And we’re done!