65.9K
CodeProject 正在变化。 阅读更多。
Home

托管 ETW 提供程序和 15002 错误

starIconstarIconstarIconstarIconstarIcon

5.00/5 (1投票)

2012年3月16日

CPOL

3分钟阅读

viewsIcon

13501

托管 ETW 提供程序和 15002 错误

最近我一直在玩 ETW(Windows 事件跟踪)。我的目标之一是编写一个托管提供程序,并在我的应用程序中试用 ETW 基础设施。MSDN 上对所有内容都进行了很好的解释,并且实现起来并不难(尤其是在我的简单情况下)。不幸的是,并非所有事情都进展顺利,在这篇文章中,我将向您展示我遇到的一个问题以及诊断损坏的 ETW 提供程序的一些通用路径。

我的提供程序应该尽可能简单,因此我的清单文件只包含所需的字段

<!--?xml version='1.0' encoding='utf-8' standalone='yes'?-->
<?xml version='1.0' encoding='utf-8' standalone='yes'?>
<instrumentationManifest xmlns="http://schemas.microsoft.com/win/2004/08/events">
  <instrumentation
      xmlns:win="http://manifests.microsoft.com/win/2004/08/windows/events"
      xmlns:xs="http://www.w3.org/2001/XMLSchema"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    <events xmlns="http://schemas.microsoft.com/win/2004/08/events">
      <provider guid="{369D265E-BE68-422B-A4DD-8778320F4D26}"
                name="TestAppChannelProvider"
                message="$(string.message.provider)"
                symbol="TestAppChannel"
                resourceFileName="C:\logs\etw\ApplicationChannelProvider.exe"
                messageFileName="C:\logs\etw\ApplicationChannelProvider.exe">

        <channels>
          <importChannel chid="appchnl" name="Application" />
        </channels>
        
        <events>
          <event value="101" 
                 message="$(string.message.event101)"
                 level="win:Informational"
                 channel="appchnl" />
        </events>
      </provider>
    </events>
  </instrumentation>
  <localization>
    <resources culture="en-US">
      <stringTable>
        <string id="message.event101" value="Test message" />
        <string id="message.provider" 
        value="Trace for application channel" />
      </stringTable>
    </resources>
  </localization>
</instrumentationManifest>

如您所见,它定义了一个只发出一个事件 (101) 的提供程序,并且此事件被发送到应用程序通道。通过定义这种提供程序,我想看看这个事件将如何在事件查看器中出现(它的来源和 XML 数据是什么)。编译清单、资源和应用程序后

mc -cs ApplicationChannelProvider ApplicationChannel.man

rc ApplicationChannel.rc

csc /win32res:ApplicationChannel.res 
/debug+ /out:ApplicationChannelProvider.exe ApplicationChannel.cs Program.cs

我将二进制文件复制到目标文件夹

copy ApplicationChannelProvider.* c:\logs\etw

并安装了提供程序

wevtutil im ApplicationChannel.man

新的提供程序出现在 HKLM\Software\Microsoft\Windows\CurrentVersion\WINEVT 注册表中

一个新密钥也被添加到 HKLM\System\CurrentControlSet\Services\Eventlog\Application 中,该密钥将提供程序定义为应用程序事件日志的事件源

通过与其他应用程序分支中的源进行比较,我们可以看到有一个特殊的密钥:ProviderGuid,它将此事件源链接到我的提供程序。这意味着 Windows 事件日志记录基础设施能够从我的提供程序中消费事件,并且它应该启用它。但是,在我安装了提供程序并运行应用程序后,我没有在应用程序日志中看到任何新事件。那么这里出了什么问题?

我开始在系统中寻找任何错误痕迹或任何可能对我有帮助的信息。幸运的是,我发现 ETW 基础设施能够记录自己的操作,甚至为此目的提供了不同的通道。在事件查看器窗口中选择“显示分析和调试日志”后,我在 Microsoft-Windows-Eventlog 子文件夹下发现了两个通道

调试通道似乎非常详细,并在事件数据中提供了一些 guid,我猜想这些 guid 仅对 ETW 开发人员有价值。另一方面,分析通道提供了更有意义的一组信息,并且在启用它之后,我找到了我正在寻找的错误事件

详细的 XML 数据

<?xml version="1.0" encoding="UTF-8"?>
<Events>
   <Event xmlns="http://schemas.microsoft.com/win/2004/08/events/event">
      <System>
         <Provider Name="Microsoft-Windows-Eventlog" 
         Guid="{fc65ddd8-d6ef-4962-83d5-6e5cfe9ce148}" />
         <EventID>102</EventID>
         <Version>0</Version>
         <Level>2</Level>
         <Task>101</Task>
         <Opcode>0</Opcode>
         <Keywords>0x800000000020000</Keywords>
         <TimeCreated SystemTime="2012-03-14T06:24:55.730708200Z" />
         <EventRecordID>6</EventRecordID>
         <Correlation />
         <Execution ProcessID="1052" ThreadID="4596" 
         ProcessorID="0" KernelTime="0" UserTime="0" />
         <Channel>Microsoft-Windows-EventLog/Analytic</Channel>
         <Computer>Sebastian-HP</Computer>
         <Security UserID="S-1-5-19" />
      </System>
      <UserData>
         <EventPublisherMetaDataFailure 
          xmlns="http://manifests.microsoft.com/win/2004/08/windows/eventlog" 
          xmlns:auto-ns3="http://schemas.microsoft.com/win/2004/08/events">
            <Error Code="15002" />
            <EventID>0</EventID>
            <PublisherName>TestAppChannelProvider</PublisherName>
            <PublisherGuid>{369D265E-BE68-422B-A4DD-8778320F4D26}</PublisherGuid>
            <ProcessID>0</ProcessID>
         </EventPublisherMetaDataFailure>
      </UserData>
   </Event>
</Events>

15002 是一个 Windows 错误代码,根据 MSDN,表示“发布者元数据在资源中找不到”。至少我对从哪里开始搜索有了一些线索。不幸的是,关于 Internet 上此错误的资料也不多。最后,我偶然发现了 Naveen 的博客,其中包含 一篇关于编写托管 ETW 提供程序的优秀教程。我按照那里描述的步骤操作,仅将通道更改为应用程序通道,令我惊讶(和欣慰:),新事件出现在应用程序日志中。因此,我开始逐个检查清单的哪个元素在我的情况下丢失了。我发现问题在于缺少一个 template 标签。添加它(空的!)后,事件开始出现在应用程序日志中,并且没有记录错误。所以我的最终清单如下所示(添加的行已突出显示)

<?xml version='1.0' encoding='utf-8' standalone='yes'?>
<instrumentationManifest xmlns="http://schemas.microsoft.com/win/2004/08/events">
  <instrumentation
      xmlns:win="http://manifests.microsoft.com/win/2004/08/windows/events"
      xmlns:xs="http://www.w3.org/2001/XMLSchema"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    <events xmlns="http://schemas.microsoft.com/win/2004/08/events">
      <provider guid="{369D265E-BE68-422B-A4DD-8778320F4D26}"
                name="TestAppChannelProvider"
                message="$(string.messageprovider)"
                symbol="TestAppChannel"
                resourceFileName="C:\logs\etw\ApplicationChannelProvider.exe"
                messageFileName="C:\logs\etw\ApplicationChannelProvider.exe">

        <channels>
          <importChannel chid="appchnl" name="Application" />
        </channels>
        
        <templates>
          <template tid="t1">
          </template>
        </templates>
        
        <events>
          <event value="101" 
                 message="$(string.messageevent101)"
                 level="win:Informational"
                 template="t1"
                 channel="appchnl" />
        </events>
      </provider>
    </events>
  </instrumentation>
  <localization>
    <resources culture="en-US">
      <stringTable>
        <string id="messageevent101" 
        value="Test message" />
        <string id="messageprovider" 
        value="Trace for application channel" />
      </stringTable>
    </resources>
  </localization>
</instrumentationManifest>

您可以从 我的博客示例页面 下载清单和应用程序。

作为一般结论,如果您在使用 ETW 时遇到任何问题,请检查 Microsoft-Windows-Eventlog/分析通道(有时也可能检查调试),并尝试从 MSDN 错误描述 中推断原因,或在 Internet 上搜索。并且记住在您的托管提供程序中为您的事件添加模板!:)

归档于:CodeProject, ETW, 追踪

© . All rights reserved.