dbgHelp.dll:从C#调用SymGetModuleInfo64 - c#

我从C#代码调用SymGetModuleInfo64时遇到了非常奇怪的行为。我总是通过Marshal.GetLastWin32Error()得到ERROR_INVALID_PARAMETER(87)。我已经阅读了很多有关IMAGEHLP_MODULE64结构的频繁更新的问题的帖子,并且我刚刚下载了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是当前加载的模块的地址基,大小当然是当前加载的模块的大小。当我获得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。

在第二次尝试中,我未注释最后两个字段,并从Debugging Tool For 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;

使用这两个版本的struct我都没有成功,也没有更多的想法。
至于我要传递的地址,我很确定这是可以的,因为我是从前面提到的SymLoadModule64函数获取的。

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

参考方案

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

从线程调用ActiveX DLL - c#

我有一个ActiveX(COM)DLL,它可以进行Windows系统调用(例如ReadFile()和WriteFile())。我的GUI(使用Python或C#)在主GUI线程中创建DLL的实例。但是,为了从线程对其进行调用,无论使用C#还是Python,都必须在每个线程中创建DLL的新实例。 (作为一个补充说明,可以从C#中的线程调用原始实例,但这会阻塞主…

加载/卸载带有C#问题的C dll - c#

我在使用外部本机DLL时遇到问题。我正在ASP.NET 1.1 Web应用程序上工作,并具有通过DLLImport指令加载的此DLL。这就是我映射DLL函数的方式: [DllImport("somedllname", CallingConvention=CallingConvention.StdCall)] public static e…

使用存储在与主程序不同的文件夹中的参考库(dll)? - c#

(这可能是一个很明显的问题,但我不确定该问Bing / Google是什么)在VS2008(C#Winforms)项目中,有大量引用的第三方库。该项目使用“ Copy Local = True”,以便使各种DLL文件最终与已编译的应用程序位于同一文件夹中。为了清理问题,我想修改程序,使库都在子文件夹下。例如:C:\ MyProgram \->主程序文件…

通过引用将具有双成员数组的结构的C#数组传递给C DLL - c#

我们在c#和c dll之间编组了以下代码。但是,当打印C dll函数中的值时,与双精度数组属性关联的值均为0.0000000。我对有问题的代码添加了一些注释。我们是否错过任何配置编组行为的事情?using System; using System.Collections.Generic; using System.Linq; using System.Tex…

如何从.Net DLL获取公共出口列表? - c#

我可以使用“ dumpbin”和“ dll export”之类的工具来查看标准win32 DLL的公共入口点(“ exports”),例如Windows \ SYSTEM32 \ GDI32.dll。但是,当我在.Net DLL上使用这些相同的工具时,我看到的仅仅是 2000 .reloc 2000 .rsrc 48000 .text 我有一个C#/。Net…