2013-10-23 3 views
2

기본 플러그인을 사용하는 응용 프로그램이 있습니다. 나는이 플러그인들을 위해 내 자신의 바이너리 형식을 가지고있다. 각 플러그인은 DLL을 프로세스의 공간에 매핑하는 것과 비슷한 방법을 사용하여 런타임에로드됩니다. 즉, 각 플러그인은 자체 ImageBase, .text 또는 .data과 같은 섹션은 기존 DLL과 같은 방식으로 처리됩니다. 유일한 차이점은 플러그인의 이진 형식 (PE 파일이 아닙니다)과 플러그인을 프로세스 공간에 매핑하는 로더 코드입니다.ETW : 기존 공급자를 통해 이벤트 발행

는 지금은 ETW는이 명령 줄하여 추적을 할 때 알고 :

xperf -on latency -stackwalk profile -buffersize 1024 -minbuffers 300 -start tracea1 -on Microsoft-Windows-Win32k:::'stack' 

가 추적 캡처하는 동안 프로세스 환경을 재구성하는 데 사용할 수있는 이벤트를 방출합니다. 즉, "프로세스 추가", "스레드를 프로세스에 추가", "DLL 모듈을 프로세스에 추가"와 같은 이벤트를 방출하므로 xperfview과 같은 도구는 시스템에서 프로세스 상태의 가상 환경을 빌드하고 빌드 할 수 있습니다 현재 프로세스 트리와 같은 정보. 이러한 이벤트는 예를 들어 ImageLoad 이벤트이며 추적 전에 또는로드 중에로드되는 각 DLL에 대한 정보를 제공합니다.

당연히, 내이벤트는 기술적으로 DLL이 아니기 때문에 생성되지 않습니다 (즉, DLL과 동일한 기능으로로드되지는 않지만 기능은 동일 함). 그렇기 때문에 xperfview과 같은 도구는 프로세스 공간에서의 존재에 대해 알지 못합니다. 정상적인 DLL을 나의 플러그인을 해석 할 수 xperfview 및 이와 유사한 도구 그래서 내가하고 싶은 무엇

는 내 플러그인 로더 코드에서 내 자신의 EventWrites을 작성하고, 필요한 정보를이 ImageLoad 이벤트를 방출하는 것입니다. ImageBase 같은 내가 채울 것이다 필요한 정보, ProcessId, ImageSize

이렇게하려면, 나는, ImageLoad 이벤트의 소유자 인 경우 MSNT_SystemTrace 공급자를 등록 이러한 종류의와 함께 이벤트를 구축 할 필요가 있음을 이해 구조 :

<Data Name="ImageBase">0x7FEFDBD0000</Data> 
    <Data Name="ImageSize">0x12D000</Data> 
    <Data Name="ProcessId">  548</Data> 
    ... 
    <Data Name="Reserved0">  0</Data> 
    <Data Name="DefaultBase">0x7FEFDBD0000</Data> 

및 이벤트를 내 보냅니다.

다른 MSNT_SystemTrace을 등록하려고하면이 공급자가 이미 존재하므로 ERROR_ACCESS_DENIED을 가져 오는 것이 문제입니다.

하지만 그 질문은 내가 ETW가 지원하려고 노력하고있는 것입니까?

답변

3

해결책을 찾은 것 같습니다.

실시간으로 기존 공급자를 통해 이벤트를 내보내는 방법을 모르지만 Windows 8에서는 ETL 추적 로그를 수정할 수있는 인터페이스를 제공하므로 이벤트의 ProviderId을 다른 값으로 변경할 수 있습니다. 해당 인터페이스는 ITraceRelogger입니다. 윈도우 8 SDK (c:\Program Files (x86)\Windows Kits\8.0\Include\um\relogger.h)에서

EXTERN_GUID(CLSID_TraceRelogger, 0x7b40792d, 0x05ff, 0x44c4, 0x90, 0x58, 0xf4, 0x40, 0xc7, 0x1f, 0x17, 0xd4); 
DEFINE_GUID(IID_ITraceRelogger, 0xF754AD43, 0x3BCC, 0x4286, 0x80, 0x09,0x9C, 0x5D, 0xA2, 0x14, 0xE8, 0x4E); // {F754AD43-3BCC-4286-8009-9C5DA214E84E} 
DEFINE_GUID(IID_ITraceEventCallback, 0x3ED25501, 0x593F, 0x43E9, 0x8F, 0x38,0x3A, 0xB4, 0x6F, 0x5A, 0x4A, 0x52); // {3ED25501-593F-43E9-8F38-3AB46F5A4A52} 

relogger.h 파일 : 이러한 GUID가 필요합니다. 원본 relogger.h은 일부 외부 기호를 참조하기 때문에 어떻게 든 부러진 것으로 보입니다. 그러나 보완 할 LIB 파일이없는 것으로 보입니다. 나는 당신이 이것을 해결할 수있을 것이라고 확신합니다!그것을 사용하려면

, 단순히으로 인스턴스를 생성 :

#include <windows.h> 
#include <cguid.h> 
#include <atlbase.h> 
#include <comdef.h> 
... 
CComBSTR input = "input.etl"; 
CComBSTR output = "output.etl"; 
... 
hres = relog->AddLogfileTraceStream(input, NULL, & trace); 
... 
hres = relog->SetOutputFilename(output); 

는 그런 다음 이벤트 수정을 처리 할 콜백을 등록해야합니다

ITraceRelogger *relog = NULL; 
hres = CoCreateInstance(CLSID_TraceRelogger, 0, CLSCTX_INPROC_SERVER, IID_ITraceRelogger2, (LPVOID *)& relog); 

당신에게 input.etloutput.etl 파일을 추가 할 수 있습니다. 이벤트 콜백의 구현 예는이 대답의 끝에 있습니다. 여기에 현재 ITraceRelogger와 함께 사용하는 방법에 대한 코드는 다음과 같습니다

EventCallback *ec = new EventCallback(); 
hres = relog->RegisterCallback(ec); 
... 
hres = relog->ProcessTrace(); 

경고 : 당신이 어떤 콜백을 등록하지 않은 경우 ProcessTrace()가 오류를 반환합니다.

는 다음 작업 콜백의 예 :

class EventCallback: public ITraceEventCallback { 
private: 
    DWORD ref_count; 
    DWORD64 evno; 

public: 
    EventCallback() { 
     ref_count = 0; 
     evno = 0; 
    } 

    STDMETHODIMP QueryInterface(const IID& iid, void **obj) { 
     if(iid == IID_IUnknown) { 
      *obj = dynamic_cast<IUnknown *>(this); 
     } else if(iid == IID_ITraceEventCallback) { 
      *obj = dynamic_cast<ITraceEventCallback *>(this); 
     } else { 
      *obj = NULL; 
      return E_NOINTERFACE; 
     } 

     return S_OK; 
    } 

    STDMETHODIMP_ (ULONG) AddRef(void) { 
     return InterlockedIncrement(& ref_count); 
    } 

    STDMETHODIMP_ (ULONG) Release() { 
     ULONG ucount = InterlockedDecrement(& ref_count); 
     if(ucount == 0) { 
      delete this; 
     } 

     return ucount; 
    } 

    HRESULT STDMETHODCALLTYPE OnBeginProcessTrace(ITraceEvent *HeaderEvent, ITraceRelogger *Relogger) { 
     return S_OK; 
    } 

    HRESULT STDMETHODCALLTYPE OnEvent(ITraceEvent *Event, ITraceRelogger *Relogger) { 
     // Your main method. 
     evno++; 
     Relogger->Inject(Event); 
    } 


    HRESULT STDMETHODCALLTYPE OnFinalizeProcessTrace(ITraceRelogger *Relogger) { 
     return S_OK; 
    } 
}; 

Relogger->Inject 출력 파일에 현재 Event를 복사합니다. ITraceRelogger에 대한 MSDN을 사용하여 원하는 이벤트 속성을 변경할 수있는 메서드를 확인할 수 있습니다. 내가 관심을 보인 방법은 SetProviderId()입니다.

은 Windows 7에서 사용할 수 있다는 것을 기억하십시오. Windows 7에서이 클래스를 인스턴스화 할 수 없으므로 MSDN에서이 주제에 대한 잘못된 정보를 가질 수 있습니다.

+0

이 업데이트를 설치 한 후 : http://support.microsoft.com/kb/2882822, Win7에서이 클래스를 사용할 수 있습니다. – antonone

관련 문제