c# - DbgHelp.dll : calling SymGetModuleInfo64 from C#

标签 c# api pinvoke native

我从 C# 代码调用 SymGetModuleInfo64 的行为非常奇怪。我总是使用 Marshal.GetLastWin32Error() 得到 ERROR_INVALID_PARAMETER (87)。我已经阅读了很多关于 IMAGEHLP_MODULE64 结构频繁更新问题的文章,我刚刚下载了最新的调试Tools For Windows (x86) ,从该位置加载了 dbghelp.dll,我非常确定它会起作用。尽管如此,我还是遇到了同样的错误。有人能指出我这里出了什么问题吗?

IMAGEHLP_MODULE64 结构在我的代码中定义如下:

[StructLayout(LayoutKind.Sequential)]
  public struct IMAGEHELP_MODULE64
  {
   //************************************************
   public int SizeOfStruct;
   public long BaseOfImage;
   public int ImageSize;
   public int TimeDateStamp;
   public int CheckSum;
   public int NumSyms;
   public SymType SymType;
   [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
   public string ModuleName;
   [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
   public string ImageName;
   [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
   public string LoadedImageName;
   //************************************************
   //new elements v2
   //*************************************************
   [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
   public string LoadedPdbName;
   public int CVSig;
   [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 780)]
   public string CVData;
   public int PdbSig;
   public GUID PdbSig70;
   public int PdbAge;
   public bool PdbUnmatched;
   public bool DbgUnmatched;
   public bool LineNumbers;
   public bool GlobalSymbols;
   public bool TypeInfo;
   //************************************************
   //new elements v3
   //************************************************
   public bool SourceIndexed;
   public bool Publics;
   //************************************************
   //new elements v4
   //************************************************
   public int MachineType;
   public int Reserved;
   //************************************************
  }

实际调用SymGetModuleInfo64的代码如下:

public void GetSymbolInfo(IntPtr hProcess,long modBase64,out bool success)
  {
   success = false;
   DbgHelp.IMAGEHELP_MODULE64 moduleInfo = new DbgHelp.IMAGEHELP_MODULE64();
   moduleInfo.SizeOfStruct = Marshal.SizeOf(moduleInfo);

   try
   {
    success = DbgHelp.SymGetModuleInfo64(hProcess, modBase64, out moduleInfo);

    if (success)
    {
     //Do the stuff here
    }
   }
   catch (Exception exc)
   {
   }
  }

我被困在这里...总是出现错误 87。请有人指出我正确的方向。

顺便说一下,modBase64 是之前填充的值:

modBase64 = DbgHelp.SymLoadModule64(_handle, IntPtr.Zero, fileName, null, baseAddress, size);

其中 _handle 是正在调试的进程的进程句柄,fileName 是当前加载模块的路径,baseAddress 是当前加载模块的地址基址,size 当然是当前加载模块的大小。当我得到 LOAD_DLL_DEBUG_EVENT 时,我调用此代码。 编辑:

抱歉,我忘了提及 SymGetModuleInfo64 签名是这样的:

[DllImport("dbghelp.dll", SetLastError = true)]
    public static extern bool SymGetModuleInfo64(IntPtr hProcess, long ModuleBase64, out IMAGEHELP_MODULE64 imgHelpModule);

首先感谢您的回答。

1.检查SymType,它的底层类型确实是int。 2.将GUID结构更改为System.Guid 3.在IMAGEHELP_MODULE64结构体的定义中添加CharSet=CharSet.Auto。 4.评论最后两个字段。 5.使用Marshal.SizeOf(instance_of_the_struct)检查结构体的大小,为3264字节(Unicode)和1672字节(Ansi)。

dbghelp.dll 是从 %windir%\system 32 文件夹加载的,我使用的是 Windows Server 2008 enterprise,但仍然没有成功。我仍然收到相同的错误 - 87。

在第二次尝试中,我取消了最后两个字段的注释,并使用了 Windows 调试工具 (x86) 目录中的 dbghelp.dll,因为我几天前下载了最新版本,并且在 SDK\inc 中有 dbghelp.h 文件,其中表示结构使用最后两个字段 (v4),如以下代码片段所示:

//
// module data structure
//

typedef struct _IMAGEHLP_MODULE64 {
    DWORD    SizeOfStruct;           // set to sizeof(IMAGEHLP_MODULE64)
    DWORD64  BaseOfImage;            // base load address of module
    DWORD    ImageSize;              // virtual size of the loaded module
    DWORD    TimeDateStamp;          // date/time stamp from pe header
    DWORD    CheckSum;               // checksum from the pe header
    DWORD    NumSyms;                // number of symbols in the symbol table
    SYM_TYPE SymType;                // type of symbols loaded
    CHAR     ModuleName[32];         // module name
    CHAR     ImageName[256];         // image name
    CHAR     LoadedImageName[256];   // symbol file name
    // new elements: 07-Jun-2002
    CHAR     LoadedPdbName[256];     // pdb file name
    DWORD    CVSig;                  // Signature of the CV record in the debug directories
    CHAR     CVData[MAX_PATH * 3];   // Contents of the CV record
    DWORD    PdbSig;                 // Signature of PDB
    GUID     PdbSig70;               // Signature of PDB (VC 7 and up)
    DWORD    PdbAge;                 // DBI age of pdb
    BOOL     PdbUnmatched;           // loaded an unmatched pdb
    BOOL     DbgUnmatched;           // loaded an unmatched dbg
    BOOL     LineNumbers;            // we have line number information
    BOOL     GlobalSymbols;          // we have internal symbol information
    BOOL     TypeInfo;               // we have type information
    // new elements: 17-Dec-2003
    BOOL     SourceIndexed;          // pdb supports source server
    BOOL     Publics;                // contains public symbols
    // new element: 15-Jul-2009
    DWORD    MachineType;            // IMAGE_FILE_MACHINE_XXX from ntimage.h and winnt.h
    DWORD    Reserved;               // Padding - don't remove.
} IMAGEHLP_MODULE64, *PIMAGEHLP_MODULE64;

我没有成功使用这两个版本的结构,并且我没有更多的想法。 至于我传递的地址,我很确定它没问题,因为我从 SymLoadModule64 函数获取它,正如我之前所说。

希望有人知道这里发生了什么。

最佳答案

尝试将最后一个参数 (imgHelpModule) 从 out 更改为 ref。对于 out 参数,CLR 不会将任何数据编码到函数中,因此 API 将看不到您放入 SizeOfStruct 中的值。

关于c# - DbgHelp.dll : calling SymGetModuleInfo64 from C#,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4705299/

相关文章:

c# - 面试谜语: accessing a private data member

c# - 尝试调用具有 out 参数的函数时出现问题

javascript - 自 1.0 以来,有没有办法在新的 Spotify API 中将轨道添加到现有播放列表

c# - 是否有用于访问Excel文件的免费API?

c# - 将 C++ 字符串 vector 编码到 C#

c# - 几个嵌套的if条件

c# - 在 Asp.net core 中间件中访问 ModelState

c# - 给定目录中的 ASP.Net core 1 列表文件

c# - PInvoke 编码返回字符串数组 C#

C 应用程序 (Linux) 的 C# (Mono) 测试意外修改属性