Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

C#: How to call native method using LoadLibrary/GetProcAddress?

28 views
Skip to first unread message

Akzhan Abdulin

unread,
Jan 6, 2003, 1:09:55 AM1/6/03
to
Hello,

How to call native method from C# using LoadLibrary/GetProcAddress?
Of course I can import LoadLibrary and GetProcAddress through
DllImportAttribute.

But how to call/invoke method by entry point later?

Details: I need to call DllGetVersion method of some libraries.

PS. Solution using Managed C++ is known, but C#-based solution wanted.

PS. Solution using Version Information known too.

Mattias Sjögren

unread,
Jan 6, 2003, 7:33:31 AM1/6/03
to
Akzhan,

>How to call native method from C# using LoadLibrary/GetProcAddress?

Here are a couple different takes on the problem

http://www.msjogren.net/dotnet/eng/samples/dotnet_dynpinvoke.asp
http://www.codeproject.com/csharp/dyninvok.asp

It's also possible to write a tiny piece of IL code that uses the
calli instruction for this.

Mattias

===
Mattias Sjögren [MVP] mattias @ mvps.org
http://www.msjogren.net/dotnet/
Please reply only to the newsgroup.

Akzhan Abdulin

unread,
Jan 6, 2003, 1:07:56 PM1/6/03
to
Thank You very much! Great links.

Can You send me this small piece of IL code (and how to link it to my
assembly) that solves my problem? (My knowledge of MSIL isn't well yet).

Mattias Sjögren

unread,
Jan 6, 2003, 5:44:51 PM1/6/03
to
Akzhan,

>Can You send me this small piece of IL code (and how to link it to my
>assembly) that solves my problem? (My knowledge of MSIL isn't well yet).

Sure can do. I whipped up this code

// IL Asm code, compile with
// > ilasm /dll CalliDllGetVersion.il
.assembly extern mscorlib {}
.assembly CalliDllGetVersion {}

.class value public sequential DLLVERSIONINFO
{
.field public int32 cbSize
.field public int32 dwMajorVersion
.field public int32 dwMinorVersion
.field public int32 dwBuildNumber
.field public int32 dwPlatformID
}

.class public CalliWrappers
{
.method public static int32 DllGetVersion(native int pfn, valuetype
DLLVERSIONINFO& dvi)
{
ldarg.1 // push dvi
ldarg.0 // push pfn
calli unmanaged stdcall int32(valuetype DLLVERSIONINFO&)
ret
}
}

// C# client code, compile with
// > csc /r:CalliDllGetVersion.dll CalliTest.cs
using System;
using System.Runtime.InteropServices;

class CalliTest
{
[DllImport("kernel32.dll", CharSet=CharSet.Auto)]
static extern IntPtr LoadLibrary(string lpFileName);

[DllImport("kernel32.dll")]
static extern bool FreeLibrary(IntPtr hModule);

[DllImport("kernel32.dll")]
static extern IntPtr GetProcAddress(IntPtr hModule, string
lpProcName);

static void Main()
{
foreach ( string dll in new string[] {"shell32.dll",
"shlwapi.dll", "comctl32.dll", "kernel32.dll"} )
PrintDllVersion( dll );
}

static void PrintDllVersion(string dll)
{
IntPtr hmod = IntPtr.Zero;
DLLVERSIONINFO dvi = new DLLVERSIONINFO();

Console.Write( dll + ": " );

try {
hmod = LoadLibrary( dll );
IntPtr pfn = GetProcAddress( hmod, "DllGetVersion" );
if ( pfn == IntPtr.Zero ) {
Console.WriteLine( "DllGetVersion entrypoint not found" );
return;
}
dvi.cbSize = Marshal.SizeOf( typeof(DLLVERSIONINFO) );
int hr = CalliWrappers.DllGetVersion( pfn, ref dvi );
if ( hr != 0 ) Marshal.ThrowExceptionForHR( hr );
Console.WriteLine( "{0}.{1}.{2}.{3}", dvi.dwMajorVersion,
dvi.dwMinorVersion, dvi.dwBuildNumber, dvi.dwPlatformID );
}
finally {
if ( hmod != IntPtr.Zero ) FreeLibrary( hmod );
}
}
}

The output on my machine is

shell32.dll: 6.0.2600.2
shlwapi.dll: 6.0.2600.1
comctl32.dll: 5.82.2600.2
kernel32.dll: DllGetVersion entrypoint not found

0 new messages