Search code examples
c#pinvokeloadlibrary

How to debug LoadLibraryEx when used from C#


I am trying to load a win32 dll in C# using the LoadLibraryEx.

It is not working - I get a message stating in visual studio "vshost32.exe has stopped working". No exceptions or any clue as to why it doesn't work.

I don't believe it is a dependency problem because if I alter the search paths for the dependencies I get a message box stating "xyz.dll could not be found".

I am wondering if there is a way I can find out why it doesn't load properly. The program stops working on the line:

IntPtr pDll = LoadLibraryEx(@"C:\Program Files\XXX\XXX.dll", IntPtr.Zero, flags);

[UnmanagedFunctionPointer(CallingConvention.StdCall)]
    private delegate void ImportResults();

    [DllImport("kernel32.dll", SetLastError = true)]
    public static extern IntPtr LoadLibraryEx(string dllToLoad, IntPtr hFile, LoadLibraryFlags flags);

    [DllImport("kernel32.dll", SetLastError = true)]
    public static extern IntPtr GetProcAddress(IntPtr hModule, string procedureName);

    [DllImport("kernel32.dll", SetLastError = true)]
    public static extern bool FreeLibrary(IntPtr hModule);

    [System.Flags]
    public enum LoadLibraryFlags : uint
    {
        DONT_RESOLVE_DLL_REFERENCES = 0x00000001,
        LOAD_IGNORE_CODE_AUTHZ_LEVEL = 0x00000010,
        LOAD_LIBRARY_AS_DATAFILE = 0x00000002,
        LOAD_LIBRARY_AS_DATAFILE_EXCLUSIVE = 0x00000040,
        LOAD_LIBRARY_AS_IMAGE_RESOURCE = 0x00000020,
        LOAD_WITH_ALTERED_SEARCH_PATH = 0x00000008,
        LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR = 0x00000100,
        LOAD_LIBRARY_SEARCH_SYSTEM32 = 0x00000800,
        LOAD_LIBRARY_SEARCH_DEFAULT_DIRS = 0x00001000
    }

    public void Import()
    {
        LoadLibraryFlags flags = LoadLibraryFlags.LOAD_LIBRARY_SEARCH_DEFAULT_DIRS |
                                 LoadLibraryFlags.LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR;

        IntPtr pDll = LoadLibraryEx(@"C:\Program Files\XXX\XXX.dll", IntPtr.Zero, flags);

        IntPtr pAddressOfFunctionToCall = GetProcAddress(pDll, "ImportResults");


        ImportResults import = (ImportResults)Marshal.GetDelegateForFunctionPointer(pAddressOfFunctionToCall,
                                                                               typeof(ImportResults));
        import();

        bool result = FreeLibrary(pDll);

    }

Update:

I have downloaded the windows sdk and am attempting to use the cdb.exe to debug the problem using the process described here: http://blogs.msdn.com/b/junfeng/archive/2006/11/20/debugging-loadlibrary-failures.aspx

When running the utility I am using this command line:

"C:\Program Files (x86)\Windows Kits\8.1\Debuggers\x86\cdb.exe" loadlib "C:\Program Files\XXX\XXX\XXX.DLL"

But I get this error: Error

The file definitely exists so I am unsure what I am doing wrong here.


Solution

  • I installed the windows debugging tools: https://msdn.microsoft.com/en-US/windows/desktop/bg162891

    I then downloaded the Windows Symbol packages: https://msdn.microsoft.com/en-us/windows/hardware/gg463028.aspx

    Then set an environment variable to tell the debugger where to look for symbols:

    _NT_SYMBOL_PATH = SRV*C:\dev\symbols*http://msdl.microsoft.com/download/symbols;C:\Symbols
    

    (I installed the symbol package to C:\Symbols)

    Then I started my application and attached the debugger with this command:

    "C:\Program Files (x86)\Windows Kits\8.1\Debuggers\x86\cdb.exe" -pb -p <pid>
    

    -pb means it won't break on exceptions -p is the pid of the thread you want to debug

    From this I have been able to determine where the error is happening. Still haven't figured out why it's happening though.