Visual C++ 7.1Visual Studio .NET 2003Windows 2003.NET 1.1Windows 2000Windows XP中级开发Visual StudioWindowsC++.NETC#
调试监视器字符串






4.88/5 (14投票s)
2004年1月1日
1分钟阅读

79612

896
挂钩调试共享内存。
引言
Code Project不仅发布了数百万个编程创意,而且还在减少编码时间。在示例应用程序中已经准备好许多类,可以直接在新的应用程序中使用,可以修改也可以不修改,从而减少了编码时间。
所以,我想贡献我的代码。即使它很简单,也没有什么新意,也许对其他人有用。
如何挂钩调试共享内存
Trace
语句写入 DBWIN_BUFFER
共享文件。它还使用 DBWIN_DATA_READY
和 DBWIN_BUFFER_READY
事件来同步共享内存中的读写操作。要从该共享内存文件读取数据并发出信号,需要以下函数:
SetEvent
ResetEvent
CreateEvent
CloseHandle
CreateFileMapping
MapViewOfFile
UnmapViewOfFile
WaitForSingleObject
这些函数位于 kernel32.dll 中。在托管代码中使用这些函数有两种选择:
- COM 包装器 - 大约 20 条机器指令的开销。
- P/Invoke - 大约 5 条机器指令的开销。
我选择了 P/Invoke,因为它比 COM 包装器更快。
DLLImports
这里是所有的导入签名。
//SET EVENT
[DllImport("Kernel32.dll",CharSet=CharSet.Auto)]
private static extern Boolean SetEvent(IntPtr hEvent);
//RESET EVENT
[DllImport("Kernel32.dll",CharSet=CharSet.Auto)]
private static extern Boolean ResetEvent(IntPtr hEvent);
//OPEN EVENT
[DllImport("Kernel32.dll",CharSet=CharSet.Auto)]
private static extern IntPtr OpenEvent(UInt32
dwDesiredAccess,Boolean bInheritHandle,String lpName);
//GET LAST ERROR
[DllImport("Kernel32.dll",CharSet=CharSet.Auto)]
private static extern UInt32 GetLastError();
//CREATE EVENT
[DllImport("Kernel32.dll",CharSet=CharSet.Auto)]
private static extern IntPtr CreateEvent(IntPtr
lpEventAttributes,Boolean bManualReset,Boolean bInitialState,String lpName);
//CLOSE HANDLE
[DllImport("Kernel32.dll",CharSet=CharSet.Auto)]
private static extern Boolean CloseHandle(IntPtr hObject);
//CREATE FILE MAPPING
[DllImport("Kernel32")]
private static extern IntPtr CreateFileMapping(IntPtr hFile,
IntPtr pAttributes, UInt32 flProtect,UInt32 dwMaximumSizeHigh,
UInt32 dwMaximumSizeLow, String pName);
//MAP VIEW FILE
[DllImport("Kernel32.dll",CharSet=CharSet.Auto)]
private static extern IntPtr
MapViewOfFile(IntPtr hFileMappingObject,
UInt32 dwDesiredAccess,UInt32 dwFileOffsetHigh,
UInt32 dwFileOffsetLow,UInt32 dwNumberOfBytesToMap);
//UNMAP VIEW FILE
[DllImport("Kernel32.dll",CharSet=CharSet.Auto)]
private static extern Boolean UnmapViewOfFile(IntPtr lpBaseAddress);
//WAIT FOR SINGLE OBJECT
[DllImport("Kernel32.dll",CharSet=CharSet.Auto)]
private static extern UInt32 WaitForSingleObject(IntPtr hHandle,
Int32 dwMilliseconds);
Hook
这是创建同步事件和映射内存文件的代码
public bool Initialize(out String szError){
bool bResult = false;
szError = "";
//create ready event
m_hReady = m_oNative.win32CreateEvent(IntPtr.Zero,
false,false,"DBWIN_DATA_READY");
if(m_hReady != IntPtr.Zero)
{
//create ack event
m_hAck = m_oNative.win32CreateEvent(IntPtr.Zero,
false,false,"DBWIN_BUFFER_READY");
if(m_hAck != IntPtr.Zero)
{
//create shared file
m_hSharedFile =
m_oNative.win32CreateFileMapping(CWin32.InvalidHandleValue,
IntPtr.Zero,CWin32.PAGE_READWRITE,0,1024,"DBWIN_BUFFER");
if(m_hSharedFile != IntPtr.Zero)
{
//map shared file
m_hShareAddress =
m_oNative.win32MapViewOfFile(m_hSharedFile,
CWin32.FILE_MAP_READ,0,0,512);
if(m_hShareAddress != IntPtr.Zero)
{
bResult = true;
}
else
{
szError = "Error to map file";
}
}
else
{
szError = "Error to create memory map file DBWIN_BUFFER";
}
}
else
{
szError = "Error to create event DBWIN_BUFFER_READY";
}
}
else
{
szError = "Error to create event DBWIN_DATA_READY";
}
return bResult;
}
等待数据
public staticvoid Run()
{
m_oNative.win32SetEvent(m_hAck);
while(fRunning)
{
m_oNative.win32WaitForSingleObject(m_hReady,-1);
UInt32 nApp = (UInt32)Marshal.ReadInt32(m_hShareAddress);
Byte[] data = new Byte[2000];
for(int i =0; i < 2000; i++)
{
Byte temp = Marshal.ReadByte(m_hShareAddress,i+4);
if(temp == 13 || temp == 0)
break;
data[i] = temp;
}
System.Text.Encoding myASCII = System.Text.Encoding.ASCII;
String szData = myASCII.GetString(data);
int nIndex = szData.IndexOf("\0");
if(nIndex != -1)
szData = szData.Substring(0,nIndex);
szData = szData.Trim();
DebugDataEventArgs args = new DebugDataEventArgs(nApp,szData);
CDebugHelper.DbgHandler(args);
m_oNative.win32SetEvent(m_hAck);
}
}
取消挂钩
public bool DeInitialize()
{
bool bResult = false;
//Close ready event handle
if(m_oNative.win32CloseHandle(m_hReady))
{
//Close ack event handle
if(m_oNative.win32CloseHandle(m_hAck))
{
//Unmap view file
if(m_oNative.win32UnmapViewOfFile(m_hShareAddress))
{
bResult = true;
}
}
}
return bResult;
}
测试
包含三个测试应用程序。
- ConDms.exe - 调试监视器字符串的控制台版本。
- WinDms.exe - 调试监视器字符串的 Windows 版本。
- Test.exe - 发送跟踪字符串的测试程序。