Click here to Skip to main content
15,867,453 members
Articles / Programming Languages / C#
Article

Debug Monitor string

Rate me:
Please Sign up or sign in to vote.
4.88/5 (15 votes)
31 Dec 20031 min read 77.6K   892   37   9
Hooking to debug shared memory.

Sample screenshot

Sample screenshot

Introduction

Code Project is not only distributing millions of programming ideas but it also is reducing coding time. There are a number of classes ready in sample applications which can be used directly in your new application with or without modification, thus it is reducing the time in coding.

So, I thought let me contribute my code also. Even though it is simple and nothing new, may be it will be useful for others.

How to hook into debug shared memory

Trace statement writes in DBWIN_BUFFER shared file. It also uses DBWIN_DATA_READY and DBWIN_BUFFER_READY events to sync read and write operations in shared memory. To read from this shared memory file and signal event, followings function are required.

  1. SetEvent
  2. ResetEvent
  3. CreateEvent
  4. CloseHandle
  5. CreateFileMapping
  6. MapViewOfFile
  7. UnmapViewOfFile
  8. WaitForSingleObject

These functions are in kernel32.dll. There are two options to use this function in managed code.

  • COM wrapper - around 20 machine instructions overhead.
  • P/Invoke - around 5 machine instructions overhead.

I chose P/Invoke because it is faster compared to COM wrapper.

DLLImports

Here are all the import signatures.

C#
//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

Here is the code to create sync events and to map memory file:

C#
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;
}

Wait for Data

C#
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);
    }
}

UnHook

C#
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; 
}

Testing

There are three test applications included with this.

  • ConDms.exe - console version of debug monitor string.
  • WinDms.exe - windows version of debug monitor string.
  • Test.exe - test program to send trace string.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
Web Developer
United States United States
Senior Software Er.
Aspect Communication
San Jose USA CA


Comments and Discussions

 
QuestionFrom web service Pin
Crazy Joe Devola26-Mar-08 16:35
Crazy Joe Devola26-Mar-08 16:35 
GeneralDebug when .exe was open Pin
Vitoto20-Oct-05 16:28
Vitoto20-Oct-05 16:28 
GeneralThank for the code, it is not easy to get this kind of info Pin
CastorTiu12-Oct-05 13:34
CastorTiu12-Oct-05 13:34 
GeneralIts Good Logic Pin
M_Rizwan16-Aug-05 20:41
M_Rizwan16-Aug-05 20:41 
GeneralThanks! Pin
Marc Clifton22-Jun-05 10:48
mvaMarc Clifton22-Jun-05 10:48 
GeneralRe: Thanks! Pin
ashvin2-Aug-05 13:56
ashvin2-Aug-05 13:56 
GeneralDebug .Net application automatic Pin
autodebug8-May-04 18:25
autodebug8-May-04 18:25 
QuestionWhat does it do? Pin
Broken God1-Jan-04 5:13
Broken God1-Jan-04 5:13 
AnswerRe: What does it do? Pin
ashvin1-Jan-04 7:12
ashvin1-Jan-04 7:12 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.