【发布时间】:2011-04-22 17:17:29
【问题描述】:
我一直在开发一个使用 API 从 Windows 事件日志中获取事件的应用程序。我现在被指针偏移量困住了。我正在使用的特定结构是 EVENTLOGRECORD(请参阅:http://msdn.microsoft.com/en-us/library/aa363646(v=vs.85).aspx)。我的 C# 结构定义为:
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto, Pack = 1)]
internal struct EVENTLOGRECORD
{
internal UInt32 Length;
internal UInt32 Reserved;
internal UInt32 RecordNumber;
internal UInt32 TimeGenerated;
internal UInt32 TimeWritten;
internal UInt32 EventID;
internal UInt16 EventType;
internal UInt16 NumStrings;
internal UInt16 EventCategory;
internal UInt16 ReservedFlags;
internal UInt32 ClosingRecordNumber;
internal UInt32 StringOffset;
internal UInt32 UserSidLength;
internal UInt32 UserSidOffset;
internal UInt32 DataLength;
internal UInt32 DataOffset;
}
我的 ReadEventLog 函数声明为:
[DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Auto, EntryPoint = "ReadEventLog")]
internal static extern Boolean ReadEventLog(IntPtr hEventLog, EVT_READ_FLAGS dwReadFlags, UInt32 dwRecordOffset, IntPtr lpBuffer, UInt32 nNumberOfBytesToRead, out UInt32 pnBytesRead, out UInt32 pnMinNumberOfBytesNeeded);
我能够获取填充数据的结构,并且可以使用 IntPtr.Add 访问 SourceName 和 ComputerName 部分。示例:
IntPtr pSrc = IntPtr.Add(pRecord, Marshal.SizeOf(typeof(EVENTLOGRECORD)));
string sSrc = Marshal.PtrToStringAuto(pSrc);
Console.WriteLine("source: {0}\n", sSrc);
IntPtr pComp = IntPtr.Add(pSrc, (sSrc.Length * 2) + 2);
string sComp = Marshal.PtrToStringAuto(pComp);
Console.WriteLine("computer: {0}\n", sComp);
我的问题是尝试从结构中获取字符串部分。我似乎无法弄清楚正确的偏移量是多少。我可以在 C++ 中做到这一点,但我似乎无法让它在 C# 中工作。这是我在 C++ 中使用的 sn-p(elr 是 (EVENTLOGRECORD*)pRecord):
char* strings = (LPSTR)((LPBYTE) elr + elr->StringOffset);
while (elr->NumStrings)
{
wprintf(L"String: %s\n", strings);
strings += (wcslen((wchar_t*)strings) * sizeof(wchar_t)) + sizeof(wchar_t);
elr->NumStrings--;
}
希望有人可以帮助解释我所缺少的。我也很好奇是否有 IntPtr.Add 的替代品,因为这需要 .NET 4.0。无论如何,我都不是 p/invoke 方面的专家。谢谢。
【问题讨论】:
-
这是作为练习吗?为什么不使用 System.Diagnostics.EventLog 类来读取条目?
-
没有。实际上它是由于 .NET 框架中的一个错误而完成的:connect.microsoft.com/VisualStudio/feedback/details/654644/… 我提交了那个,显然这确实是一个问题。否则,我会在 EventLog 类中到处都是。这要容易得多。
-
我真的不明白为什么写入错误(似乎是 Connect 链接)会阻止您使用内置类从日志中读取事件。
-
@Will Dean - 你不得不说两次?我的最终目标是监控事件。您不能在框架中使用 EntryWritten 可靠地做到这一点。所以我已经使用 API 来提供所需的功能。