C# get the list of unmanaged C dll exports
Asked Answered
W

1

8

I have a C dll with exported functions

I can use the command-line tool dumpbin.exe /EXPORTS to extract the list of exported functions, and then use them in my C# code to (successfully) call these functions.

Is there a way to get this exported-functions-list directly from .NET, without having to use an external command-line tool?

Thanks

Wan answered 15/8, 2013 at 9:8 Comment(5)
Check this out - #12648266Alix
I need it the other way round, not DLLExport but DLLImport, which I use dynamically using LoadLibrary and GetProcAddress win32api's.Wan
The thing is I get DLLs from many sources, and the names of exported functions are not always only the original function names but include all other kinds of stuff like question marks and "@", so I need to get a list of all exported function-names to see which one contains the name I am looking forWan
This is not an option. As a rule, you won't find unhelpful features built into VS. Extracting the names of exported functions is just a small part of the job, you still need to know the types of the arguments and return value.Izolaiztaccihuatl
I know the method-signatures, I just don't know their namesWan
W
12

As far as I know there is no class in the .Net Framework that provides the information you need.

However you can use the platform invocation services (PInvoke) of the .Net platform to use the functions of the Win32 dbghelp.dll DLL. This DLL is part of the Debugging Tools for the Windows platform. The dbghelp DLL provides a function called SymEnumerateSymbols64 which allows you to enumerate all exported symbols of a dynamic link library. There is also a newer function called SymEnumSymbols which also allows to enumerate exported symbols.

The code below shows a simple example on how to use the SymEnumerateSymbols64 function.

[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);
}

In order to keep the example simple I did not use the SymEnumSymbols function. I've also did the example without using such classes as the SafeHandle class of the .Net framework. If you need a example for the SymEnumSymbols function, just let me know.

Wilk answered 15/8, 2013 at 18:53 Comment(3)
Thanks a lot for the elighting information, I have tested it and it seems to be working just fine.Wan
One more thing, though, that is missing for me functionality-wise, is the ability to get the entry-point name for each of the function-names listed, this is because, for instance, the function named "GGT_RecommendMacros" has the entry point named "?GGT_RecommendMacros@@YAPADPBDPAHPAPAPAD@Z"Wan
@ZivF: The ?GGT_RecommendMacros@@.." is the C++ name decoration. This is the entry point of your function. Please see #14085896 link for further explanation.Wilk

© 2022 - 2024 — McMap. All rights reserved.