2016-06-06 4 views
3

C#에서 계층 구조와 친숙한 이름을 가진 모든 Windows 이벤트 로그 (이벤트 뷰어 로그)의 목록을 얻는 방법 몇 가지 문제가 생겼어. 내가 다시 가져온 이름 중 일부는 표시 이름이나 친숙한 이름이 아닙니다. 예를 들어 "Microsoft Office Alerts"의 경우 "OAlerts"만 반환합니다. "OAlerts"에서 전체 "Microsoft Office Alerts"를 어떻게 얻을 수 있습니까?나는 종류의 이벤트 뷰어</p> <p><a href="https://i.stack.imgur.com/YIGEl.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/YIGEl.png" alt="enter image description here"></a></p> <p>I에서 다음과 같은 복제하기 위해 노력하고있어

두 번째 문제는 계층 구조를 파악하는 것입니다. 내가 할 수있는 일은 대시를 파싱하고 일종의 최선의 추측을하는 것입니다. API에서 쉽게 파악할 수있는 방법이없는 것처럼 보입니다. GetLogNames는 당신에게 모든 로그의 단순 목록을 제공

EventLogSession session = new EventLogSession(); 
List<string> logNames = new List<string>(session.GetLogNames()); 
foreach (string name in logNames) 
{ 
    //EventLogConfiguration config = new EventLogConfiguration(name); //looks useful but doesn't give me any of the info i'm looking for. 

    Console.WriteLine(name); 
}   

답변

3

여기이 블로그 :

가 제공하는 EventSourceAttribute의 이름 속성을 사용하여 수행 The EventSource NuGet package and support for the Windows Event Log (Channel Support)가이 상태 드문 EventSource User's Guide 문서에 대한 링크가 있습니다 a 이벤트 소스로 표시되는 ETW 이벤트 공급자의 설명 이름 기본값은 이벤트 소스 유형의 짧은 이름입니다. ETW 제공자 이름이 하나의 컴퓨터 전체 이름 공간을 공유하기 때문에 쉽게 충돌 할 수 있습니다. 좋은 제공자 이름 예 : " <CompanyName>-<Product>-<Component>". 이 세 요소를 따라 규칙을 적용하면 이벤트 뷰어에서 논리 폴더 계층에 이벤트 로그를 표시 할 수 있습니다. “Application and Services Logs/<CompanyName>/<Product>/<Component> ".

대시가 엄격한 요구 사항보다 규칙적임을 나타내는 경향이있는 (그래서 저는 혼자서 파싱 할 수 있다고 생각합니다). 블로그는 여전히 댓글을 달 수 있습니다.

일치하지 않는 이름의 경우 이벤트 뷰어에 표시되는 이름을 얻을 수있는 문서화되지 않은 EvtIntGetClassicLogDisplayName 함수가 있습니다.

static void Main(string[] args) 
    { 
     var session = new EventLogSession(); 
     foreach (string name in session.GetLogNames()) 
     { 
      Console.WriteLine(GetDisplayName(session, name)); 
     } 
    } 

그리고 여기에 지원 코드는 서류 미 비자이기 때문에, 당신의 자신의 위험에 사용합니다 (플러스, 그것은 대부분이 'OAlert'유용 할 것 : 여기 세션 로그 이름으로 사용하는 방법입니다 항목이므로 가치가 있는지 확신 할 수 없습니다.) :

public static string GetDisplayName(EventLogSession session, string logName) 
    { 
     var sb = new StringBuilder(512); 
     int bufferUsed = 0; 
     if (EvtIntGetClassicLogDisplayName(GetSessionHandle(session).DangerousGetHandle(), logName, 0, 0, sb.Capacity, sb, out bufferUsed)) 
      return sb.ToString(); 

     return logName; 
    } 

    private static SafeHandle GetSessionHandle(EventLogSession session) 
    { 
     return (SafeHandle)session.GetType().GetProperty("Handle", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(session); 
    } 

    [DllImport("wevtapi.dll", CharSet = CharSet.Unicode)] 
    private static extern bool EvtIntGetClassicLogDisplayName(IntPtr session, [MarshalAs(UnmanagedType.LPWStr)] string logName, int locale, int flags, int bufferSize, [MarshalAs(UnmanagedType.LPWStr)] StringBuilder displayName, out int bufferUsed); 
+0

감사합니다. Simon. 참으로 위대한 대답입니다. GetDisplayName은 매력처럼 작동합니다 (DangerousGetHandle을 사용하는 것은 무서울지라도 - 이것이 코드 검토를 통과하는지 궁금합니다 :). 그러나 명명 규칙은 제대로 적용되지 않습니다. 위에서 추가 한 스크린 샷에서도 Microsoft-SQLServerDataTools는 Microsoft에 배치되지 않습니다. 또한 GetLogNames()를 호출 할 때 위의 스크린 샷에 Microsoft에서 표시되지 않는 Microsoft-IIS-Configuration이 표시됩니다. 내가 발견 한 것과 같은 또 다른 "숨겨진"API가있을 것이라고 생각합니다. – Mark

+0

비슷한 예는 Microsoft-Rdms-UI 로그입니다. – Mark

+1

Microsoft-SQLServerDataTools는 3 요소 규칙을 따르지 않습니다 (2 부분 만, MS의 일부 사람은 문서를 읽지 않았습니다 ...). 또한 EventViewer의 메뉴 인 View/Show Analytic and Debug Logs를 체크하면 많은 것들이 나타날 것입니다. 이 로그는 "진단"또는 "분석"으로 표시됩니다. Microsoft-IIS-Configuration의 경우 Provider "Microsoft-Windows-IIS-Configuration"에 링크 된 로그입니다 (새 ProviderMetadata ("Microsoft-Windows-IIS-Configuration", session, null을 사용하여 해당 링크를 찾을 수 있습니다.) .LogLinks'). 로그와 공급자 사이의 네임 스페이스가 항상 일정하지는 않습니다 ... –