使用c#中的指针偏移量
本文关键字:指针 偏移量 使用 | 更新日期: 2023-09-27 17:51:24
我一直在开发一个使用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;
}
我的readdeventlog函数声明为:
[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++中使用的代码片段(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。因为需要。net 4.0。无论如何,我不是p/invoke方面的专家。谢谢。
如果您使用Marshal.PtrToStructure()将数据块的第一部分复制到EVENTLOGRECORD,那么您应该能够像这样做:
EVENTLOGRECORD record;
... Copy the ptr into record ...
IntPtr pStrings = IntPtr.Add(pRecord, (record.StringOffset * 2));
我很乐意为你做这个,但是我太懒了,不能做所有其他的p/invoke位,因为能够使readdeventlog调用。
经过一段时间的编码清理大脑,我终于有了一个解决方案。我错误地使偏移量太大,因为我正在取结构体(EVENTLOGRECORD)的大小,将其添加到StringOffset,然后将其添加到现有对象中。我真正需要做的就是将偏移量添加到现有的IntPtr (pRecord)中。我不知道为什么以前没有。
所以简单地做:
int offset = ((int)(((EVENTLOGRECORD)o).StringOffset));
IntPtr pStrings = IntPtr.Add(pRecord, offset);
string sString = Marshal.PtrToStringAuto(pStrings);
Console.WriteLine("string : {0}'n", sString);
. .足以得到字符串。谢谢你的助攻。我显然没有资格把建议标记为有用的。我想我只是需要远离这一切。
现在问可能太晚了。为什么不使用。net的System.Diagnostics.EventLog类?据我所知,你有问题与EventLog类。你有没有尝试过EventLogReader类,它适用于Windows版本Vista和更高版本?
使用Reflector,您还可以了解它们是如何进行封送的。看起来不可能让编组程序完成全部工作。他们将数据读入一个简单的字节数组,并将其存储在EventLogEntry类中,该类直接从字节数组中读取所需的数据。
在EventLogEntry类中读取替换字符串。databuf成员是来自原生readdeventlog调用的字节数组。
[MonitoringDescription("LogEntryReplacementStrings")]
public string[] ReplacementStrings
{
get
{
string[] strArray = new string[this.ShortFrom(this.dataBuf, this.bufOffset + 0x1a)];
int index = 0;
int offset = this.bufOffset + this.IntFrom(this.dataBuf, this.bufOffset + 0x24);
StringBuilder builder = new StringBuilder();
while (index < strArray.Length)
{
char ch = this.CharFrom(this.dataBuf, offset);
if (ch != ''0')
{
builder.Append(ch);
}
else
{
strArray[index] = builder.ToString();
index++;
builder = new StringBuilder();
}
offset += 2;
}
return strArray;
}
}
你的,阿洛伊斯•克劳斯