C#获取未管理的C dll导出列表

8

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

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

是否有一种方法可以直接从.NET获取这个导出函数列表,而不必使用外部的命令行工具?

谢谢。


1
看看这个 - https://dev59.com/-2jWa4cB1Zd3GeqPwP8g - Rohit Vats
我需要相反的方式,不是使用DLLExport而是使用DLLImport,我使用LoadLibrary和GetProcAddress win32api动态地加载。 - ZivF
问题是我从许多来源获取DLL,导出函数的名称不总是仅包含原始函数名称,而是包括各种其他内容,如问号和“@”,因此我需要获取所有导出函数名称的列表,以查看哪个包含我正在寻找的名称。 - ZivF
这不是一个选项。通常情况下,你不会在VS中找到无用的功能。提取导出函数的名称只是工作的一小部分,你仍然需要知道参数和返回值的类型。 - Hans Passant
我知道方法签名,只是不知道它们的名称。 - ZivF
1个回答

12
据我所知,.Net Framework中没有提供您需要的信息的类。
但是,您可以使用.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函数。我也没有使用.Net框架的SafeHandle类等类来完成该示例。如果你需要SymEnumSymbols函数的示例,请告诉我。


非常感谢您提供的有益信息,我已经测试过了,看起来一切都正常。 - ZivF
还有一件事,就是在功能方面我觉得还缺少一个能够获取每个函数名称的入口点名称的功能。例如,名为“GGT_RecommendMacros”的函数具有名为“?GGT_RecommendMacros@@YAPADPBDPAHPAPAPAD@Z”的入口点。 - ZivF
1
@ZivF:"?GGT_RecommendMacros@@.."是C++的名称修饰。这是您函数的入口点。请参见http://stackoverflow.com/questions/14085396/dumpbin-shows-strange-method-name-generating-exporting-function-in-ms-visual-c链接以获取更多解释。 - Hans

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接