Im trying to get a value of a string exported by an unmanaged dll.
The string in the dll is declared as
extern "C" __declspec(dllexport) const char* _Version = "0.1";
The code I'm using to get the value is below. I get the address for the variable from the call to GetProcAddress
but Marshal.PtrToStringAuto
returns garbage...
Whats wrong?
public string GetDllVersion()
{
IntPtr lib = LoadLibrary(@"some.dll");
if(lib == IntPtr.Zero)
throw new Win32Exception(Marshal.GetLastWin32Error());
IntPtr procAddress = GetProcAddress(lib, "_Version");
var ver2 = Marshal.PtrToStringAuto(procAddress);
if(!FreeLibrary(lib))
throw new Win32Exception(Marshal.GetLastWin32Error());
return ver2;
}
[DllImport("kernel32", SetLastError = true, CharSet = CharSet.Unicode)]
static extern IntPtr LoadLibrary(string lpFileName);
[DllImport("kernel32", CharSet = CharSet.Ansi, ExactSpelling = true, SetLastError = true)]
static extern IntPtr GetProcAddress(IntPtr hModule, string procName);
[DllImport("kernel32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool FreeLibrary(IntPtr hModule);
You have to use Marshal.PtrToStringAnsi() here.
"Auto" means "operating system default". With Windows 98 and ME on the endangered species list, that's very likely Unicode on your machine. Your string isn't const wchar_t*.
Here is my solution; checked-it, it works.
IntPtr procAddress = GetProcAddress(lib, "_Version");
IntPtr verAddress = Marshal.ReadIntPtr(procAddress);
var ver2 = Marshal.PtrToStringAnsi(verAddress);
Fixed this by dereferencing the pointer from GetProcAddress:
procAddress = Marshal.ReadIntPtr(GetProcAddress(lib, "_Version"));
Also changed the way to read the string per suggestion from Hans Passant (other answer):
var ver2 = Marshal.PtrToStringAnsi(procAddress);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With