【问题标题】:C# get the list of unmanaged C dll exportsC# 获取非托管 C dll 导出列表
【发布时间】:2013-08-17 10:59:54
【问题描述】:

我有一个带有导出函数的 C dll

我可以使用命令行工具 dumpbin.exe /EXPORTS 来提取导出函数的列表,然后在我的 C# 代码中使用它们来(成功)调用这些函数。

有没有办法直接从 .NET 获取这个导出的函数列表,而无需使用外部命令行工具?

谢谢

【问题讨论】:

  • 我需要它,而不是 DLLExport 而是 DLLImport,我使用 LoadLibrary 和 GetProcAddress win32api 动态使用它。
  • 问题是我从许多来源获得 DLL,导出函数的名称并不总是原始函数名称,还包括所有其他类型的东西,如问号和“@”,所以我需要获取所有导出函数名称的列表,查看哪个包含我要查找的名称
  • 这不是一个选项。通常,您不会发现 VS 内置的无用功能。提取导出函数的名称只是工作的一小部分,您仍然需要知道参数和返回值的类型。
  • 我知道方法签名,只是不知道它们的名字

标签: c# c dll interop cdecl


【解决方案1】:

据我所知,.Net 框架中没有类 提供您需要的信息。

但是,您可以使用 .Net 平台的平台调用服务 (PInvoke) 来 使用 Win32 dbghelp.dll DLL 的功能。此 DLL 是 Windows 平台的调试工具。 dbghelp DLL 提供 一个名为SymEnumerateSymbols64 的函数,它允许您枚举所有 动态链接库的导出符号。还有一个 较新的函数称为SymEnumSymbols,它还允许枚举 导出符号。

下面的代码显示了如何使用SymEnumerateSymbols64 的简单示例 函数。

[DllImport("dbghelp.dll", SetLastError = true, CharSet = CharSet.Unicode)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool SymInitialize(IntPtr hProcess, string UserSearchPath, [MarshalAs(UnmanagedType.Bool)]bool fInvadeProcess);

[DllImport("dbghelp.dll", SetLastError = true, CharSet = CharSet.Unicode)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool SymCleanup(IntPtr hProcess);

[DllImport("dbghelp.dll", SetLastError = true, CharSet = CharSet.Unicode)]
public static extern ulong SymLoadModuleEx(IntPtr hProcess, IntPtr hFile,
     string ImageName, string ModuleName, long BaseOfDll, int DllSize, IntPtr Data, int Flags);

[DllImport("dbghelp.dll", SetLastError = true, CharSet = CharSet.Unicode)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool SymEnumerateSymbols64(IntPtr hProcess,
   ulong BaseOfDll, SymEnumerateSymbolsProc64 EnumSymbolsCallback, IntPtr UserContext);

public delegate bool SymEnumerateSymbolsProc64(string SymbolName,
      ulong SymbolAddress, uint SymbolSize, IntPtr UserContext);

public static bool EnumSyms(string name, ulong address, uint size, IntPtr context)
{
  Console.Out.WriteLine(name);
  return true;
}    

static void Main(string[] args)
{
  IntPtr hCurrentProcess = Process.GetCurrentProcess().Handle;

  ulong baseOfDll;
  bool status;

  // Initialize sym.
  // Please read the remarks on MSDN for the hProcess
  // parameter.
  status = SymInitialize(hCurrentProcess, null, false);

  if (status == false)
  {
    Console.Out.WriteLine("Failed to initialize sym.");
    return;
  }

  // Load dll.
  baseOfDll = SymLoadModuleEx(hCurrentProcess,
                              IntPtr.Zero,
                              "c:\\windows\\system32\\user32.dll",
                              null,
                              0,
                              0,
                              IntPtr.Zero,
                              0);

  if (baseOfDll == 0)
  {
    Console.Out.WriteLine("Failed to load module.");
    SymCleanup(hCurrentProcess);
    return;
  }

  // Enumerate symbols. For every symbol the 
  // callback method EnumSyms is called.
  if (SymEnumerateSymbols64(hCurrentProcess,
      BaseOfDll, EnumSyms, IntPtr.Zero) == false)
  {
    Console.Out.WriteLine("Failed to enum symbols.");
  }

  // Cleanup.
  SymCleanup(hCurrentProcess);
}

为了保持示例简单,我没有使用 SymEnumSymbols 函数。我也做了这个例子 不使用诸如SafeHandle 之类的类 .Net 框架。如果你需要一个例子 SymEnumSymbols 函数,请告诉我。

【讨论】:

  • 非常感谢您提供的信息,我已经测试过了,它似乎工作得很好。
  • 不过,我在功能方面缺少的另一件事是能够获取每个列出的函数名称的入口点名称,这是因为,例如,名为“GGT_RecommendMacros”的函数具有名为“?GGT_RecommendMacros@@YAPADPBDPAHPAPAPAD@Z”的入口点
  • @ZivF: ?GGT_RecommendMacros@@.." 是 C++ 名称装饰。这是您的函数的入口点。请参阅stackoverflow.com/questions/14085396/… 链接以获取更多说明。
猜你喜欢
  • 1970-01-01
  • 2010-11-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-09-18
  • 2011-06-04
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多