欢迎使用金字塔普通技术服务论坛,您可以在相关区域发表技术支持贴。
我司技术服务人员将优先处理 VIP客服论坛 服务贴,普通区问题处理速度慢,请耐心等待。谢谢您对我们的支持与理解。


金字塔客服中心 - 专业程序化交易软件提供商金字塔软件高级功能研发区 → 请问怎么在金字塔中运行这个debug 的程序啊

   

欢迎使用金字塔普通技术服务论坛,您可以在相关区域发表技术支持贴。
我司技术服务人员将优先处理 VIP客服论坛 服务贴,普通区问题处理速度慢,请耐心等待。谢谢您对我们的支持与理解。    


  共有6259人关注过本帖树形打印复制链接

主题:请问怎么在金字塔中运行这个debug 的程序啊

帅哥哟,离线,有人找我吗?
xzhero
  1楼 | 信息 | 搜索 | 邮箱 | 主页 | UC


加好友 发短信
等级:新手上路 帖子:10 积分:164 威望:0 精华:0 注册:2010/7/23 10:39:04
请问怎么在金字塔中运行这个debug 的程序啊  发帖心情 Post By:2010/8/26 11:47:14 [只看该作者]

http://www.codeproject.com/KB/vb/VisualTraceListener.aspx

 

Introduction

I was tooling around in the documentation pertaining to the TraceListener class and I found that "..where no trace listeners are attached, trace messages are output using the OutputDebugString API..."

This got me thinking - an application that can receive these OutputDebugString messages can allow you to view the trace messages of an application without having to stop and restart it to add a trace listener.

To receive this output you need to attach to the running process as a debugger and then whenever the process needs a trace message your debugger will receive an OUTPUT_DEBUG_STRING_EVENT event and you can get the string from that.

Writing a rudimentary debugger

There are a couple of API calls used in Windows NT for creating a debugger application:

DebugActiveProcess which attaches to the process to start debugging it:

Collapse | Copy Code
<DllImport("kernel32", CallingConvention:=CallingConvention.Winapi, _
           EntryPoint:="DebugActiveProcess", _
           ExactSpelling:=True, SetLastError:=True)> _
Public Shared Function DebugActiveProcess( <InAttribute()> _
              ByVal ProcessHandle As Int32) As Boolean

End Function

WaitForDebugEvent which pauses the caller until the process being debugged reaches a debug event:

Collapse | Copy Code
<DllImport("kernel32", CallingConvention:=CallingConvention.Winapi, _
           EntryPoint:="WaitForDebugEvent", _
           ExactSpelling:=True, SetLastError:=True)> _
Public Shared Function WaitForDebugEvent( _
           <OutAttribute(), MarshalAs(UnmanagedType.LPStruct)> _
           ByVal DebugEvent As DebugApi.Structures.DEBUG_EVENT, _
           <InAttribute()> ByVal dwMilliseconds As Int32) As Boolean

End Function

and ContinueDebugEvent which resumes the debugee:

Collapse | Copy Code
<DllImport("kernel32", CallingConvention:=CallingConvention.Winapi, _
           EntryPoint:="ContinueDebugEvent", _
           ExactSpelling:=True, SetLastError:=True)> _
Public Shared Function ContinueDebugEvent( _
           <InAttribute()> ByVal dwProcessId As Int32, _
           <InAttribute()> ByVal dwThreadId As Int32, _
           <InAttribute(), MarshalAs(UnmanagedType.U4)> _
           ByVal dwContinueStatus As DebugAPIConstatnts.DebugStates) As Boolean

End Function

To debug an application you need to attach to the process and then run a loop that waits for a debug event, handles the debug event and then resumes the debuggee.

Attaching to the process

The .NET Process class has a member Id which you pass to the DebugActiveProcess API to start debugging that process.

Waiting for a debug event

Calling the WaitForDebug event will block until a debug event occurs. When it does occur the details needed to handle it will be held in the structure DEBUG_EVENT passed back.

Collapse | Copy Code
<StructLayout(LayoutKind.Sequential)> _
Public Class DEBUG_EVENT
    <MarshalAs(UnmanagedType.U4)> Public DebugEventCode _
      As DebugApi.DebugAPIConstatnts.DebugEventTypes
    Public ProcessId As Int32
    Public ThreadId As Int32
    Public lpDebugStringData As UInt32
    Public IsUnicode As Int16
    Public DebugStringLength As Int16
End Class

Handling the OUTPUT_DEBUG_STRING event

When we receive an OUTPUT_DEBUG_STRING event there are three properties that we need to retrieve the actual string: lpDebugStringDate is a pointer to the memory address of the string, IsUnicode is true if the string is in Unicode format and DebugStringLength tells you how long the string is...but there is a slight hitch: the address in lpDebugStringData is a memory address in the debuggee application's address space.

Getting a string from another application's memory

To get at the data in another application's memory we need to use the ReadProcessmemory API call:

Collapse | Copy Code
<DllImport("kernel32", CallingConvention:=CallingConvention.Winapi, _
           EntryPoint:="ReadProcessMemory", _
           ExactSpelling:=True, SetLastError:=True)> _
Public Shared Function ReadProcessMemory( _
                   <InAttribute()> ByVal hProcess As Int32, _
                   <InAttribute()> ByVal lpBaseAddress As UInt32, _
                   <OutAttribute()> ByVal lpBuffer As IntPtr, _
                   <InAttribute()> ByVal nSize As Int32, _
                   <OutAttribute()> ByRef lpNumberOfBytesRead As UInt32 _
                            ) As Boolean

End Function

For a bit of OO design I have implemented this as a function in the DEBIG_EVENT class:

Collapse | Copy Code
Public Function GetString(ByVal ProcessHandle As Int32) As String

    Dim sRet As String
    Dim hProcess As Int32

    If DebugStringLength.Equals(0) OrElse lpDebugStringData.Equals(0) Then
        sRet = ""
    Else

        hProcess = _
          DebugApiDeclarations.OpenProcess(_
          DebugAPIConstatnts.ProcessAccessPriviledges.PROCESS_VM_READ,_
          False, Me.ProcessId)
        If hProcess <> 0 Then

            Dim bytesReturned As UInt32
            Dim lpBuffer As IntPtr
            'Allocate enough space to put the string into
            If Not IsUnicode Then
                lpBuffer = Marshal.AllocHGlobal(DebugStringLength)
            Else
                lpBuffer = Marshal.AllocHGlobal(DebugStringLength * 2)
            End If

            If DebugApiDeclarations.ReadProcessMemory(hProcess, _
                       lpDebugStringData, lpBuffer, _
                       DebugStringLength, bytesReturned) Then
                'Make this buffer into a string...
                If IsUnicode Then
                    sRet = Marshal.PtrToStringUni(lpBuffer, DebugStringLength)
                Else
                    sRet = Marshal.PtrToStringAnsi(lpBuffer, DebugStringLength)
                End If
                Marshal.FreeHGlobal(lpBuffer)
                Call DebugApiDeclarations.CloseHandle(hProcess)
            Else
                If Not lpBuffer.Equals(IntPtr.Zero) Then
                    Marshal.FreeHGlobal(lpBuffer)
                End If
                Throw New Win32Exception
            End If
        Else
            Throw New Win32Exception
        End If

        End If
        Return sRet

End Function

And with that you have a basic debugger that can watch an application and take note of its trace messages...

<!-- Main Page Contents End -->

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author


 回到顶部
帅哥哟,离线,有人找我吗?
xzhero
  2楼 | 信息 | 搜索 | 邮箱 | 主页 | UC


加好友 发短信
等级:新手上路 帖子:10 积分:164 威望:0 精华:0 注册:2010/7/23 10:39:04
  发帖心情 Post By:2010/8/26 11:49:03 [只看该作者]

???????

 回到顶部
帅哥哟,离线,有人找我吗?
wattwei
  3楼 | 信息 | 搜索 | 邮箱 | 主页 | UC


加好友 发短信
等级:论坛游侠 帖子:574 积分:3167 威望:0 精华:0 注册:2009/10/10 11:13:01
  发帖心情 Post By:2010/8/26 12:26:09 [只看该作者]

 不懂,帮顶

 回到顶部
帅哥哟,离线,有人找我吗?
ch3coohqb
  4楼 | 信息 | 搜索 | 邮箱 | 主页 | UC


加好友 发短信
等级:黑侠 帖子:628 积分:2193 威望:0 精华:0 注册:2010/5/27 11:25:08
  发帖心情 Post By:2010/8/30 23:42:28 [只看该作者]

看了第一行

<DllImport("kernel32", CallingConvention:=CallingConvention.Winapi, _
就知道你这个程序用不了...需要调用的DLL你弄的到么?


 回到顶部