0

I have some older code that doesn't appear to work on 64bit Windows 7. Not tried 32bit Windows 7, but definitely works on 32bit XP.

The code was originally derived from this article http://www.codeproject.com/KB/cs/DynamicInvokeCSharp.aspx

I've read this question which states that kernel32.dll still exists.

[DllImport("kernel32.dll", EntryPoint = "LoadLibrary")]
private static extern int LoadLibrary([MarshalAs(UnmanagedType.LPStr)] string lpLibFileName);

[DllImport("kernel32.dll", EntryPoint = "GetProcAddress")]
private static extern IntPtr GetProcAddress(int hModule, [MarshalAs(UnmanagedType.LPStr)] string lpProcName);

[DllImport("kernel32.dll", EntryPoint = "FreeLibrary")]
private static extern bool FreeLibrary(int hModule);

[DllImport("kernel32.dll")]
private static extern bool SetDllDirectory([M

arshalAs(UnmanagedType.LPStr)] string lpPathName);

And this is how it is used:

public void Init(string dllName)
{
    DllName = dllName;
    SetDllDirectory(Path.GetDirectoryName(dllName));
    hModule = LoadLibrary(Path.GetFileName(dllName));
    if (hModule == 0)
        throw new Exception("Cannot load dll " + dllName);
}

The problem I get is that LoadLibrary always returns 0 for the handle.

I have also tried hModule = LoadLibrary(dllName);

Can anyone throw any light on why it might not work, or what I should be doing instead?

Community
  • 1
  • 1
weston
  • 54,145
  • 21
  • 145
  • 203
  • Try compiling and running the application in 32-bit mode on the 64-bit machine. This is only a guess; but I'm thinking that there is a problem P/Invoking a 32-bit dll from a 64-bit .net application. – Alxandr Mar 28 '12 at 10:06
  • @Alxandr Thanks, I forgot to mention that all of the project's assemblies are already on x86. – weston Mar 28 '12 at 10:09
  • It's possibly a problem trying to load an x86 dll from an x64 program, or a missing dll, but try adding `SetLastError = true` to your `DllImport` statement and then calling `Marshal.GetLastWin32Error()` to get the error from `LoadLibrary` – jeffora Mar 28 '12 at 10:10
  • You can actually change the exception to `throw new Win32Exception(Marshal.GetLastWin32Error())` – jeffora Mar 28 '12 at 10:10
  • @jeffora Thanks, I get 1114 which appears to be ERROR_DLL_INIT_FAILED "A dynamic link library (DLL) initialization routine failed." So I presume that means the problem is acutally in the dll, and it's that that is unhappy with Windows 7 in some way. – weston Mar 28 '12 at 10:14

1 Answers1

1

(As per comments on the answer)

The majority of Windows API functions call a routine called SetLastError() to indicate failure reasons. When using DllImport from .NET you can add a property to the attribute to explicitly indicate a function should preserve this last error (I'm not 100% sure on the default behaviour, but being explicit guarantees it will happen).

Eg:

[DllImport("kernel32.dll", EntryPoint = "LoadLibrary", SetLastError = true)]
private static extern int LoadLibrary([MarshalAs(UnmanagedType.LPStr)] string lpLibFileName);

You can then get the error code from managed code by calling Marshal.GetLastWin32Error(), or get a slightly more useful exception by throwing a Win32Exception as such throw new Win32Exception(Marshal.GetLastWin32Error())

jeffora
  • 4,009
  • 2
  • 25
  • 38