Click here to Skip to main content
Click here to Skip to main content

Late binding on native DLLs with C#

By , 12 Nov 2001
 

Sample Image - DynInvok.gif

Introduction

Consider the situation where the native, Win32 DLL is unknown at compile time. Perhaps its name or location is stored in the Windows Registry, or is selected by the user from a FileOpen dialog. How can we call a function exported from this library, but only resolved at runtime? The prescribed way to call native functions from the CLR is through PInvoke, using the DllImport attribute, but this must be declared at compile time or, at the very least, generated on the fly using Reflection.Emit. This article will show an alternative way which requires the use of a little x86 assembler to meet our goal.

LoadLibrary

Windows provides two ways to load DLLs into the process of an executable. Either, the DLL can be specified in the imports table and the Windows Loader will map the DLL automatically or the LoadLibrary() Win32 API call can be used. These are called implicit linking and explicit linking respectively. Both these types can be seen in action using Dependency Walker available from http://www.dependencywalker.com/. The CLR, Visual BASIC 6 and the /delayload feature of MSVC6 all use explicit linking to call DLL functions.

We can quite happily call LoadLibrary() from C# to load a DLL into our address space. The problem comes when we try to call a function in the DLL. Win32 provides the GetProcAddress() function to return the memory address of a function exported from the given DLL and we can easily obtain this memory address, but we can do nothing with it. It is simply an integer. The CLR provides no way to jump to this location in memory, passing appropriate parameters too.

The CLR does allow us to do the reverse and pass a pointer to a managed function to a DLL using the delegate keyword, but there is no way to specify that a value returned from an unmanaged API call should be treated as a delegate. Perhaps we may see this in .Net version 2, but for now we need to find another way to call the function.

Going low-level

One solution would be to write a small C++ DLL which merely forwards the call on. In other words, the C++ DLL is acting as a proxy for our intended function. The downside is that a new C++ DLL would have to be created every time a different DLL function needs to be called. The proxy function needs the exact number of parameters that the real function takes. Every C# programmer needs to know C++ to be able to do this.

A much better solution is to write a small, reusable DLL in x86 assembly language which can forward function calls to any location. This is trivial to write if we know a bit about how Win32 DLLs are called. All DLLs are called using the stdcall calling convention. This means that parameters are pushed onto the stack beginning at the right-most parameter. Thus, the first in the parameter list will be at the top of the stack. The return address is then placed on the stack and control is transferred to the callee. It is the callee's responsibility to pop all the parameters off the stack and not fiddle with more registers than absolutely necessary.

Consider the following function declaration:

[DllImport("Invoke", CharSet=CharSet.Unicode)]
public extern static int InvokeFunc(int funcptr, int hwnd, 
                                    string message, string title, int flags);
It is implemented in a DLL called Invoke.dll and has the export name InvokeFunc. It also takes five parameters, of which the last four are the exact parameters taken by the MessageBox() function. The first parameter is an address of a function. We will leave the implementation of InvokeFunc for now and look at code which can call this.
int hmod=LoadLibrary("User32");
int funcaddr=GetProcAddress(hmod, "MessageBoxW");
int result=InvokeFunc(funcaddr, 0, "Hello World", 
                      ".Net dynamic export invocation", 1 /*MB_OKCANCEL*/);
Console.WriteLine("Result of invocation is " + result);

FreeLibrary(hmod);
This code loads the DLL into our process space, finds the address of a function we wish to call, then uses our special InvokeFunc() function to call a function through a function pointer.

Screenshot of Dependency Walker watching this taking place

In the screenshot above, notice how GetProcAddress() is being used to find the address of GetProcAddress()! This is because PInvoke uses GetProcAddress to find the address of any function specified by the DllImport attribute.

InvokeFunc Implementation

As we discussed earlier, the stdcall calling conventions places parameters onto the stack in reverse order. Thus, our function pointer will be at the top of the stack because it is first in the parameter list. If we can take this parameter off the stack, then jump to that location in memory, it would be the equivalent of calling that function without the intermediate proxy function.

The following fragment of x86 assembler achieves this

pop ecx		; save return address
pop edx		; Get function pointer
push ecx	; Restore return address
jmp edx		; Transfer control to the function pointer
Because we've used a jmp instruction rather than a call instruction, control will be transferred directly from the called function back to the CLR, passing any return value directly back.

Conclusion

Everything needed to compile and run this code is included with Visual Studio .Net. The x86 DLL built can be reused for calling any function pointer, not just a function with a specific signature and is only 2,560 bytes.

It turns out that if you are not running .Net on Windows XP, there is a DLL with an equivalent proxy function to the one we built. That DLL is msjava.dll, which of course is missing from Windows XP due to the Microsoft-Sun agreement on Java technology. msjava.dll provides an export with the name call() which duplicates this functionality.

License

This article, along with any associated source code and files, is licensed under The BSD License

About the Author

Richard Birkby
Web Developer
United Kingdom United Kingdom
Member
Richard Birkby is a software engineer from London, UK, specializing in .Net. Richard has coded for many different sized companies from small venture-capital funded start-ups, to multi-national corporations (ie Microsoft). When he's not programming, he enjoys driving his sports car or eating curry (although never at the same time!).
 
Richard helps run CurryPages.com and has several other covert ventures in development. Stay tuned!

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board.
Search this forum  
    Spacing  Noise  Layout  Per page   
QuestionLoading unmanaged DLL from memorymemberFlyersWeb5 Nov '12 - 10:19 
Hi,
 
Very interesting article and comment. I'm currently working on a similar issue but I want to load and execute a DLL from memory.
 
I intended to do so like that :
 
public unsafe void LaunchWindowedProgramInMemory(Stream s)
{
	BinaryReader br = new BinaryReader(s);
	br.BaseStream.Position = 0;
 
	byte[] bin = br.ReadBytes((int)s.Length);
	try
	{
		fixed (byte* p = bin)
		{
			IntPtr ptr = (IntPtr)p;
 
			IntPtr pAddressOfFunctionToCall = NativeMethods.GetProcAddress(ptr, "MultiplyByTen");
			if (pAddressOfFunctionToCall == IntPtr.Zero) return;
 
			MultiplyByTen multiplyByTen = (MultiplyByTen)Marshal.GetDelegateForFunctionPointer(																						                                       
                              pAddressOfFunctionToCall,																					
                              typeof(MultiplyByTen)
                        );
			int theResult = multiplyByTen(10);
			Console.WriteLine(theResult);
		}
 
	}
	catch (Exception e)
	{
		Console.Write(e.ToString());
	}
}
 
This is for personal experiments and for studies so my DLL is very simple, I've taken the same as in preceding comment :
 
extern "C" __declspec(dllexport) int MultiplyByTen(int numberToMultiply);
 
int MultiplyByTen(int numberToMultiply)
{
        int returnValue = numberToMultiply * 10;
        return returnValue;
}
 
The problem is that when I call GetProcAddress I always got a 0x00 address return. If someone has an idea of why I got this... Thanks Smile | :)
SuggestionDynamically calling an unmanaged dll from .NET (C#)memberDamavand2 Mar '12 - 4:08 
Dynamically calling an unmanaged dll from .NET (C#) by JonathanSwift
 
This sample is in response to a question left on my previous post, namely how to call an unmanaged dll from managed code when the dll in question isn't known until runtime (for instance, the path is stored in the registry, or an xml file, etc etc).
 
Apologies if this sample seems a little hurried, but I have another presentation to write and so time is short!
 
So let's begin.
 
To start and to refresh our memories, let's create a very basic C++ dll that does very little..... your code should resemble the following (check out my previous post for more info on this):
 
Header file
extern "C" __declspec(dllexport) int MultiplyByTen(int numberToMultiply);
 
Source code file
#include "DynamicDLLToCall.h"

int MultiplyByTen(int numberToMultiply)
{
        int returnValue = numberToMultiply * 10;
        return returnValue;
} 
As you can probably infer from the function name, an int is passed into this function and it will return the number passed in multiplied by ten. Told you it would be simple.
 
Now comes the more interesting part, actually calling this dll dynamically from your C# source code. There are two Win32 functions that are going to help us do this:
 
1) LoadLibrary - returns a handle to the dll in question
2) GetProcAddress - obtain the address of an exported function within the previously loaded dll
 
The rest is rather simple. We use LoadLibrary and GetProcAddress to get the address of the function within the dll we want to call, and then we use the GetDelegateForFunctionPointer static method within the Marshal class to assign this address to a C# delegate that we define. Take a look at the following C# code:
 
static class NativeMethods
{
        [DllImport("kernel32.dll")]
        public static extern IntPtr LoadLibrary(string dllToLoad);
 
        [DllImport("kernel32.dll")]
        public static extern IntPtr GetProcAddress(IntPtr hModule, string procedureName);
 

        [DllImport("kernel32.dll")]
        public static extern bool FreeLibrary(IntPtr hModule);
}
 
class Program
{
        [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
        private delegate int MultiplyByTen(int numberToMultiply);
 
        static void Main(string[] args)
        {
                IntPtr pDll = NativeMethods.LoadLibrary(@"PathToYourDll.DLL");
                //oh dear, error handling here
                //if (pDll == IntPtr.Zero)

                IntPtr pAddressOfFunctionToCall = NativeMethods.GetProcAddress(pDll, "MultiplyByTen");
                //oh dear, error handling here
                //if(pAddressOfFunctionToCall == IntPtr.Zero)

                MultiplyByTen multiplyByTen = (MultiplyByTen)Marshal.GetDelegateForFunctionPointer(
                                                                                        pAddressOfFunctionToCall,
                                                                                        typeof(MultiplyByTen));
 
                int theResult = multiplyByTen(10);
 
                bool result = NativeMethods.FreeLibrary(pDll);
                //remaining code here

                Console.WriteLine(theResult);
        }
} 
 
The only item worthy of note is the UnmanagedFunctionPointer attribute, which was introduced to version 2.0 of the .NET framework, check out the docs online for more information.
 
Hope this helps.
GeneralRe: Dynamically calling an unmanaged dll from .NET (C#)memberRichard Birkby2 Mar '12 - 6:09 
My CodeProject article was written in 2001. This was before .Net 2 and the rather useful GetDelegateForFunctionPoint method was introduced. Had that method been around 11 years ago, it's very unlikely I'd have written this article.
QuestionI had to change the makefile a bit to path to Csc.exememberdcarl66117 Aug '11 - 6:19 
c:\WINDOWS\Microsoft.NET\Framework\v3.5\Csc.exe $**
GeneralLoading User dllsmemberDebojyoti Majumder14 Jan '11 - 1:46 
I have some dll's which are created from Visual C++.
I want to them load from C# application.
 
I have tried by giving the full path name to the Dllimport but I didn't worked.
I have put them in C:\Windows\System32 then they worked.
 
However, I guess this is how things should not be working.
What should I do??
QuestionCreate invoke.dll on 64-bit machinesmemberAlexander Pikus3 Oct '10 - 3:58 
How can I create invoke.dll on 64-bit machines, since NMAKE is supported only on 32-bit machines?
 
Thanks a lot
GeneralDon't do this any morememberMoxxis7 Jun '10 - 8:42 
Back in wacky 2001, this was all cool and macho. Now we have
 
System::Runtime::InteropServices::Marshal::GetDelegateForFunctionPointer
 
which is there for just this purpose. It will take an intenger (actually, IntPtr) and convert it to a delegate you can call from C#. "No assembly required. (TM)"
Questionwithout asm?memberUnruled Boy18 Dec '09 - 1:59 
is there a way out without using asm, just pass: dll file, function name, argument list, and it goes?
 
and, your asm way is not really dynamic, it only works for the MessageBox api, not all dlls.
 
Regards,
unruledboy_at_gmail_dot_com
http://www.xnlab.com

GeneralEasy way (.Net Marshaling)memberJonyRocketCZ25 Nov '09 - 3:42 
This c# call function from dll. You only need to know types op parameters and type od return value.
I have 2 strings and result is also string.
 


 
using System.Runtime.InteropServices;
 
...
 
[DllImport("kernel32")]
private extern static int LoadLibrary(string lpLibFileName);
[DllImport("kernel32")]
private extern static bool FreeLibrary(int hLibModule);
[DllImport("kernel32", CharSet = CharSet.Ansi)]
private extern static int GetProcAddress(int hModule, string lpProcName);
private delegate String myMethodDelegate( string func_dataarg, string func_cfgarg);
private string SharpDllcall(string dll_name, string func_name, string func_dataarg, string func_cfgarg)
{
if (dll_name == null) return "ERROR - null dll_name";
if (dll_name == "") return "ERROR - empty dll_name";
if (func_name == null) return "ERROR - null func_name";
if (func_name == "") return "ERROR - empty func_name";
 
int dllhnd = 0;
int funchnd = 0;
int stateSucess = 0;
try
{
dllhnd = LoadLibrary(dll_name);
if (dllhnd == 0) throw new Exception();
stateSucess = 1;
funchnd = GetProcAddress(dllhnd, func_name);
if (funchnd == 0) throw new Exception();
stateSucess = 2;
myMethodDelegate myDelegate;
myDelegate = (myMethodDelegate)Marshal.GetDelegateForFunctionPointer
((IntPtr)funchnd, typeof(myMethodDelegate));
stateSucess = 3;
return myDelegate(func_dataarg, func_cfgarg);
}
catch
{
switch (stateSucess)
{
case 0: return "ERROR - error loading library";
case 1: return "ERROR - error calling function";
case 2: return "ERROR - error creating sharp delegate";
default: return "ERROR - error inside function";
}
}
finally
{
if (dllhnd != 0) FreeLibrary(dllhnd);
}
}

GeneralRe: Easy way (.Net Marshaling)memberRichard Birkby25 Nov '09 - 3:49 
Thanks for this.
 
See also the following comment: Late binding on native DLLs with C#[^]
GeneralRe: Easy way (.Net Marshaling)memberUnruled Boy18 Dec '09 - 1:58 
if you know the arguments and define the delegate, why bother late binding? why not just dllimport?
 
Regards,
unruledboy_at_gmail_dot_com
http://www.xnlab.com

Questioncall fun when not add referencesmemberhuuchau8419 Mar '09 - 19:07 
I have a lybrary:
namespace LBR
{
public class class1
{
public string getstr(string _str)
{
return _str + "test ok";
}
}
}
Buil:--> "LBR.DLL"
Creat a new project
not add reference file LBR.DLL to Bin, I copy LBR.DLL to "C:\\LBR.DLL". can i call fun getstr() in class "class1"???? Confused | :confused:
thanks!!!!!!
AnswerExcellent articlememberdefconhaya7 Mar '09 - 4:03 
Very useful stuff.
In order to make Invoke.dll you'll need MASM32 from here http://www.masm32.com/masmdl.htm[^] and run those commands:
d:\masm32\bin\ml.exe /c /coff /Cp /Fl /Sc /Sg Invoke.asm
d:\masm32\bin\link.exe -DLL -entry:DllMain /machine:i386 /subsystem:windows /out:Invoke.dll /export:InvokeFunc Invoke.obj

GeneralDynamicly load a DLL functionsmemberMember 453941111 Feb '09 - 6:41 
hello,
I'm searching for a way to call a function that i load dynamicly.
In my DLL are the functions CreateForms();ShowForms();CloseForms();
It's should be like I load ones my dll and afther that I call functies from that
DLL from a button. But how can you to that??
QuestionLINK: error LNK2001: unresolved external symbol _DLLMainmembernate alwine12 Nov '08 - 11:33 
Hi I am trying to build your project but am having issues linking Invoke.obj. When I try to execute
 
D:\Documents and Settings\208047355.GESMAM\My Documents\codeproject\loadlibrary\
article_src>link /DLL /entry:DLLMain /machine:i386 /subsystem:windows /out:Invok
e.dll /export:InvokeFunc Invoke.obj
 

it is returning the following error:
 
Microsoft (R) Incremental Linker Version 7.10.6030
Copyright (C) Microsoft Corporation. All rights reserved.
 
Creating library Invoke.lib and object Invoke.exp
Invoke.dll : warning LNK4086: entrypoint '_DLLMain' is not __stdcall with 12 byt
es of arguments; image may not run
LINK : error LNK2001: unresolved external symbol _DLLMain
Invoke.dll : fatal error LNK1120: 1 unresolved externals
 

Any idea how I fix this?
 
Thanks
Nate
QuestionDLLImportmembergclopes18 Sep '08 - 7:24 
I have a DLL in C++ and I want to use a function but in an application in C#.
 
The header of the function in C++ is:
 
__declspec(dllexport) short DLGet(LPSTR VarName, LPVOID Destination, LPSTR Format)
 
The second parameter is returned from the function.
 
What I want to know is How to pass those parameters to that function in my C# application?
 
I would be very appreciated if someone could help.
 
Thank you
 
GCLopes
QuestionHow to compile code written in assembler language?memberMember 6628769 Jul '08 - 22:19 
How to compile code written in assembler language?
GeneralIs it possible to elevate this process for Vistamemberyincekara11 Jun '08 - 6:12 
I am invoking a function from a 3'rd party dll. It works fine by using this method you 've mentioned in your article on XP. Also on Vista if UAC is disabled it works fine too. But if UAC is turned on method cannot work and returns an error code. How can we give appropriate rights do that InvokeFunc which is dynamically loaded into memory?
GeneralCompile time linking of dllmemberharsh290414 Apr '08 - 22:31 
Can I make an executable with a particular dll including in it?
I mean linking a dll at compile time only. So that I can run that exe from anywhere without having dll anywhere.
GeneralRe: Compile time linking of dllmemberMike_Silver_A2 Oct '08 - 0:53 
You can try to unpack a dll in memory, process relocations and so on. Also I find the following solution: boxedapp, it allows to load a dll from memory as it's really exists. seems what's you need.
 
hope this helps.
 
best, Mike
QuestionWhere i can find "Invoke.dll"?membertropot28 Jun '07 - 22:20 
Hi,
See the subject.
Best regards, Eugen.
AnswerRe: Where i can find "Invoke.dll"?memberRichard Birkby28 Jun '07 - 22:37 
The makefile gives the game away...
 

Invoke.obj: Invoke.asm
ml $(MLFLAGS) $**
Invoke.dll: Invoke.obj
link $** -DLL -entry:DllMain /machine:i386 /subsystem:windows /out:Invoke.dll /export:InvokeFunc

GeneralRe: Where i can find "Invoke.dll"?membertropot29 Jun '07 - 0:52 
Laugh | :laugh:
thanks,... silly me
GeneralRe: Where i can find "Invoke.dll"?memberdark_hunter6 Aug '07 - 13:09 
hola, no se mucho de esto asi que si me pudiera explicar un poco mas como obtener la dll o como hago funcionar este ejemplo te lo agradeceria mucho..
 
Gracias
 
salu2
 
x

GeneralRe: Where i can find "Invoke.dll"?memberkandy_soliton22 Aug '07 - 18:44 
HI Richard,
 
I don't understand the way the invoke.dll is created.
Can anyone explain the way it can be done?
 
Regards
kandy.
GeneralRe: Where i can find "Invoke.dll"?memberMike_Silver_A2 Oct '08 - 0:53 
it seems it's created using an asm compiler...
GeneralRe: Where i can find "Invoke.dll"?membergiger12 Apr '10 - 11:35 
in windows start visual studio command prompt. Go to the extracted folder
and just type 'nmake'.
GeneralRe: Where i can find "Invoke.dll"?memberLastMandg419 Jan '11 - 0:58 
Thanks!
GeneralReturning ValuesmemberDiogo Alves25 Jun '07 - 6:37 
Hi,
 
This seems to be the solution to my problem!
I have a dll that was wrote in C++ and I need to call that dll and get the return values
 
Is it possible to get the return values?
How?
 
Maybe your code is already doing this but I didn't understood your code very well so I would like this explanation if you don't mind.
 
Kind Regards
 
P.S.: If this works you've done a great job... Very nice indeed Big Grin | :-D
Generalinvoking dll in c#.net dynamicallymemberpksave9 May '07 - 23:32 
I want to add DLL dynamically.and want to invoke the method of DLL.I got the information that one Loadlibrary() funcion is there in c#.net.I tried that but it is not working.
 
my requirement to add add dll in form code diring form load event.
please tell me the code.
and also specify that on which object I should call that Loadlibrary().and code to access the funcions.
plz reply me.its argent..
 
Prachi
GeneralRe: invoking dll in c#.net dynamicallymemberSDX200025 May '07 - 2:34 
Please take a look at GetDelegateForFunctionPointer in the System.Runtime.InteropServices namespace (.Net 2.0)
 

 
SDX2000

GeneralRe: invoking dll in c#.net dynamicallymemberMember 473280619 Mar '08 - 2:18 
use DLLImport
maruti
GeneralIs it possiblememberjust2click21 Aug '06 - 3:35 
Hi,
 
Is it possible to use DllImport without setting the extern to be static?
Can I use an unmanged code DLL as a non-static object?
 
Thanks in advance,
 
Val
QuestionCan I use .Net Dll in Borland C++memberjags_vc5 Aug '05 - 1:29 
Sir,
Can you please give information related to use of .Net dll in VC++ or Borland C++.
Because I have a .Dll which is developed in .Net Frame work
And I want to use it in Borland C++ .
So I request to give information reklated to How camn i use it.Is it requred any dependancy or not ?
 
Thank You.
 
Jagdish
GeneralThere is a Way inside of C# (Well Sorta)memberScott Carr15 Apr '05 - 5:24 
You can execute procedures inside of DLL's using the CallWindowProc function.
 
[DllImport("user32", EntryPoint="CallWindowProc")]
public static extern int CallWindowProcA(int lpPrevWndFunc, int hwnd, int MSG, int wParam, int lParam);
 
Call it with the following, passing in the address of the function you got with GetProcAddress.
 
CallWindowProcA(funcaddr, 0, 0, 0, 0);
 
All from within the C# environment.
 
Scott Carr
OpenOffice.org
Documentation Maintainer
http://documentation.openoffice.org
GeneralRe: There is a Way inside of C# (Well Sorta)memberScott Carr15 Apr '05 - 5:28 
using System;
using System.Runtime.InteropServices;
 
namespace DCC.Install
{
///
/// Summary description for ExecuteDLLFunction.
///

public class ExecuteDLLFunction
{
[DllImport("kernel32")]
public extern static int LoadLibrary(string lpLibFileName);
[DllImport("kernel32")]
public extern static bool FreeLibrary(int hLibModule);
[DllImport("kernel32", CharSet=CharSet.Ansi)]
public extern static int GetProcAddress(int hModule, string lpProcName);
 
[DllImport("user32", EntryPoint="CallWindowProc")]
public static extern int CallWindowProcA(int lpPrevWndFunc, int hwnd, int MSG, int wParam, int lParam);
 
private string _dllfile;
private int _dll;
 
public string dllfile
{
get { return _dllfile; }
set { _dllfile = value; }
}
 
public ExecuteDLLFunction(string DLLFile)
{
_dllfile = DLLFile;
_dll = LoadLibrary(_dllfile);
}
 
~ExecuteDLLFunction()
{
FreeLibrary(_dll);
}
 
public int Execute(string strFunc)
{
int funcaddr;

if (_dll != 0)
{
 
funcaddr = GetProcAddress(_dll, strFunc);
 
if (funcaddr != 0)
{
return CallWindowProcA(funcaddr, 0, 0, 0, 0);
}
else
{
return -2;
}
}
else
{
return -1;
}
}
}
}


GeneralRe: There is a Way inside of C# (Well Sorta)memberTommy Svensson16 May '05 - 23:34 
Hi,
 
Great comment and great code! I have some follow-upers that I need some tech savvy people like you to straighten out for me:
 
Please, if possible, respond quickly as there is a short deadline in my project related to the issues below!
 
Q1: I have a C++ unmanaged API (binaries only: .libs and .dlls) and I wish to program against it using C# .NET. The API is huge with thousands of functions and classes. Honestly now, is there no way I can, at design time, simply call a function as described in the API's documentation?
 
Sure, if I do
 
DllImport("HugeAPI.dll")
public static extern void Test(int x);
 
all is fine because the return type and the parameter doesn't cause any problems. But the API uses user defined types that I don't have access to, which makes it hard to know what to do in this case:
 
DllImport("HugeAPI.dll")
public static extern SpecialAPIType Test(int x, AnotherSpecialAPIType type);
 
Q2: The above only applies to functions/methods in the API, but what about classes and arbitrary types?
 
For instance, if I want to derive a C# class from a particular C++ API class, what do I do?
 
Q3: Is there no hope? And no, I can't convert the API using Managed Extensions for C++ and no, I can't wrap the API in a COM server accessing it through COM Interop and no, I won't ever rewrite the entire API in .NET, it will simply take a few years.
 
Sincerely,
 
/Tommy
GeneralRe: There is a Way inside of C# (Well Sorta)memberScott Carr17 May '05 - 3:58 
Glad you enjoyed it. I was having a problem instantiating the DllRegisterServer for registering a dll.
 
I found the following on using Unmanaged Classes in C#:
 
http://www.codeguru.com/Cpp/Cpp/cpp_managed/interop/article.php/c6867/
 
Not sure if it'll help. I havn't had to write against Unmanaged C++ myself.
 
Scott Carr
OpenOffice.org
Documentation Maintainer
http://documentation.openoffice.org
GeneralRe: There is a Way inside of C# (Well Sorta)membernyf1220@126.com15 Nov '06 - 19:15 
good work
 
good work
GeneralRe: There is a Way inside of C# (Well Sorta)memberUnruled Boy5 May '09 - 3:44 
how to pass parameters?
 
Regards,
unruledboy_at_gmail_dot_com
http://www.xnlab.com

Generalneed the makefile as post build eventmemberdaniele_massaro7 Mar '05 - 6:31 
Hi,
 
executing the provided makefile only works within the command promt of the Visual Studio .NET 2003, which has the appropriate environment.
 
Is there a possibility using the makefile from the 'normal' command prompt?
 
I set the environment for using MS Visual C++ tools via vcvars32.bat, but it seemed that it isn't enough. If i execute the makefile with
 
nmake /all
 
i got the following message:
 
'ml' is not recognized as an internal or external command, operable program or batch file.
NMAKE : fatal error U1077: 'ml' : return code '0x1'
Stop.
 
Any ideas?
Kind regards, daniele.
Questiongetting an object pointer? activating it?memberlooknir23 Jan '05 - 6:36 
Hi
 
i want to get back from my DLL function1 a pointer to an object.
then - i want to activate a method of that object.
can i do it with C# in this way?
 
in C++ i had a struct of two virtual functions.
my first func - function1, gave me the pointer to the object from type myStruct. then i activatd the functions inside of it.
 

QuestionHave you seen this article on MSDN?memberTboner24 Nov '04 - 11:17 
Hi,
 
I am new to Win32 and I found a possible solution. I am wondering if it is valid though since I might not completely understand the problem.
 
Anyway, Navigate to the Url below and scroll down to the very bottom heading "Loading from Different Locations" (then read the 2 paragraphs)
 
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dncscol/html/csharp09192002.asp[^]
 
Basically it says you can call LoadLibrary to define the path of your .dll.
 
ie.
int hmod=LoadLibrary("C:\\PwApi.dll");
 
then in your dllImport where .net sees [DllImport("PwApi.dll")] it will refer to the .dll that was called by LoadLibrary.
 
It solves the dynamic path issue I think.
 
Here is some example code: (the .dll is 3rd party so you can't really test it but you can read the code to get an idea what I am trying to say.)
 
=================
 
using System;
using System.Text;
using System.Runtime.InteropServices;
 
namespace XXX.XXXXXX.XXXXX
{
///
/// This parser class is a wrapper for the 3rd Party
/// vendor balh blah blah's library....
///

public class Parser
{
[DllImport("PwApi.dll")]
public static extern int PwInitParsers(string dictionaryPath);
 
#region Address Functions
 
[DllImport("PwApi.dll")]
public static extern int PwParseAddr(string sourceAddress);
 
[DllImport("PwApi.dll")]
public static extern int PwFraction(byte[] target);
[DllImport("PwApi.dll")]
public static extern int PwHouseNumber(byte[] target);
[DllImport("PwApi.dll")]
public static extern int PwHousePrefix(byte[] target);
[DllImport("PwApi.dll")]
public static extern int PwHouseSuffix(byte[] target);
[DllImport("PwApi.dll")]
public static extern int PwPostDir(byte[] target);
[DllImport("PwApi.dll")]
public static extern int PwBox(byte[] target);
[DllImport("PwApi.dll")]
public static extern int PwPreDir(byte[] target);
[DllImport("PwApi.dll")]
public static extern int PwRoute(byte[] target);
[DllImport("PwApi.dll")]
public static extern int PwStreetName(byte[] target);
[DllImport("PwApi.dll")]
public static extern int PwStreetSuffix(byte[] target);
[DllImport("PwApi.dll")]
public static extern int PwUnitValue(byte[] target);
[DllImport("PwApi.dll")]
public static extern int PwUnitDesignator(byte[] target);
 
#endregion
 
[DllImport("kernel32")]
public extern static int LoadLibrary(string lpLibFileName);
[DllImport("kernel32")]
public extern static bool FreeLibrary(int hLibModule);
[DllImport("kernel32", CharSet=CharSet.Ansi)]
 
public Parser()
{
}
 
public Address ParseAddress(string addressToParse)
{
int returnCode;
int hmod;
try
{
hmod=LoadLibrary("C:\\PwApi.dll");
 
string dictionaryPath = @"C:\Default_100.dct"; // AppDomain.CurrentDomain.BaseDirectory + "Default_100.dct";
returnCode = PwInitParsers(dictionaryPath);
if(returnCode != 0)
{
string msg = String.Format("An error occurred loading the dictionary for PwApi.dll. Please ensure the dictionary path is correct: -->{0}<-- Error Code: -->{1}<--",dictionaryPath, returnCode);
throw new Exception(msg);
}
}
catch(Exception ex)
{
throw new Exception("There has been an error Initializing the PwApi.dll. Description:" + ex.Message);
}
 

Address address = new Address();
byte[] target;

 
if(PwParseAddr(addressToParse)==0) //If not successful leave everything blank.
{
target = new byte[250];
returnCode = PwFraction(target);
address.Fraction = ASCIIEncoding.ASCII.GetString(target,0,returnCode);

target = new byte[250];
returnCode = PwHouseNumber(target);
address.HouseNumber = ASCIIEncoding.ASCII.GetString(target,0,returnCode);
 
target = new byte[250];
returnCode = PwHousePrefix(target);
address.HousePrefix = ASCIIEncoding.ASCII.GetString(target,0,returnCode);
 
target = new byte[250];
returnCode = PwHouseSuffix(target);
address.HouseSuffix = ASCIIEncoding.ASCII.GetString(target,0,returnCode);
 
target = new byte[250];
returnCode = PwPostDir(target);
address.PostDirection = ASCIIEncoding.ASCII.GetString(target,0,returnCode);
 
target = new byte[250];
returnCode = PwBox(target);
address.PostOfficeBox = ASCIIEncoding.ASCII.GetString(target,0,returnCode);
 
target = new byte[250];
returnCode = PwPreDir(target);
address.PreDirection = ASCIIEncoding.ASCII.GetString(target,0,returnCode);
 
target = new byte[250];
returnCode = PwRoute(target);
address.Route = ASCIIEncoding.ASCII.GetString(target,0,returnCode);
 
target = new byte[250];
returnCode = PwStreetName(target);
address.StreetName = ASCIIEncoding.ASCII.GetString(target,0,returnCode);
 
target = new byte[250];
returnCode = PwStreetSuffix(target);
address.StreetSuffix = ASCIIEncoding.ASCII.GetString(target,0,returnCode);
 
target = new byte[250];
returnCode = PwUnitValue(target);
address.Unit = ASCIIEncoding.ASCII.GetString(target,0,returnCode);
 
target = new byte[250];
returnCode = PwUnitDesignator(target);
address.UnitDesignator = ASCIIEncoding.ASCII.GetString(target,0,returnCode);
}
 
FreeLibrary(hmod);
 
return address;
}
}
}
 
Trevor
AnswerRe: Have you seen this article on MSDN?memberTboner25 Nov '04 - 4:06 
Hold on sec. When the "location" of the .dll is dynamic but you know the name of the .dll you can use this function. (my above post doesn't work if the name of the .dll is unknown.)
 
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dllproc/base/setdlldirectory.asp[^]
GeneralUsing Invoke.dll in WebServicesmembersedel22 Nov '04 - 4:00 
Hello
 
I use the invoke dll in windows applications and it works fine.
I used the same .Net Wrapper (VB), in a .Net WebService and I have a probleme because my wrapper doesn't find the dll I load dynamicaly. (LoadLibrary return 0)
 
I know that Asp.Net make a copy of binary folder in cache.
 
How can I resolve this probleme
 
Thanks in advance
Sébastien
GeneralRe: Using Invoke.dll in WebServicesmemberjoylite12 May '06 - 22:29 
if u use the absolut DLL path.
such as : c:\\xxpath\\xx.dll
it should be work.
 

 
joylite

Generalint func(char* names[])memberkobybr23 Aug '04 - 10:23 
Hi
 
I have " int func(char* names[]) " function.
I need to call thus C++ dll function and get an array of names.
How I need to write my c# func?
 
Thanks
koby

GeneralCreating a Win32 Window in C#sussAnonymous5 Jul '04 - 7:32 
Here is the progress so far, but I am not able to successfully get a valid file handle to the window and show it. It does not crash however. This will aid to your progress as well.
 
namespace MyApp
{
struct WNDCLASSEX
{
public uint cbSize;
public uint style;
public long lpfnWndProc;
public int cbClsExtra;
public int cbWndExtra;
public long hInstance;
public long hIcon;
public long hCursor;
public long hbrBackground;
public string lpszMenuName;
public string lpszClassName;
public long hIconSm;
}
 
class Class1
{
public const string KERNEL32_DLL = "kernel32.dll";
 
[DllImport(KERNEL32_DLL, EntryPoint="GetModuleHandle")]
static extern int GetModuleHandleA(string lpModuleName);
 
public const string USER32_DLL = "user32";
public const uint CS_VREDRAW = 0x0001;
public const uint CS_HREDRAW = 0x0002;
public const long WS_OVERLAPPED = 0x00000000L;
public const long WS_EX_APPWINDOW = 0x00040000L;
public const long WS_SYSMENU = 0x00080000L;
public const int SW_SHOWNORMAL = 1;

[DllImport(USER32_DLL, EntryPoint="MessageBox")]
public static extern int MessageBox(int hWnd, String strMessage, String strCaption, uint uiType);
 
[DllImport(USER32_DLL, EntryPoint="GetForegroundWindow")]
public static extern int GetForegroundWindow();

[DllImport(USER32_DLL, EntryPoint="RegisterClassEx")]
public static extern short RegisterClassExA(ref WNDCLASSEX pcWndClassEx);
 
[DllImport(USER32_DLL, EntryPoint="CreateWindowEx")]
public static extern long CreateWindowExA(long dwExStyle, string lpClassName, string lpWindowName, long dwStyle, long x, long y, long nWidth, long nHeight, long hwndParent, long hMenu, long hInstance, object lpParam);
 
[DllImport(USER32_DLL, EntryPoint="ShowWindow")]
public static extern int ShowWindow(long hwnd, int nCmdShow);
 
[DllImport(USER32_DLL, EntryPoint="UpdateWindow")]
public static extern int UpdateWindow(long hwnd);
 
[DllImport(USER32_DLL, EntryPoint="SetFocus")]
public static extern int SetFocus(long hwnd);
 
[DllImport(USER32_DLL, EntryPoint="ShowCursor")]
public static extern int ShowCursor(bool bShow);
 
[DllImport(USER32_DLL, EntryPoint="UnregisterClass")]
public static extern int UnregisterClassA(string lpClassName, long hInstance);
 
///
/// The main entry point for the application.
///

[STAThread]
static void Main(string[] args)
{
WNDCLASSEX wndclassex = new WNDCLASSEX();
wndclassex.cbSize = 48;
wndclassex.style = CS_HREDRAW | CS_VREDRAW;
wndclassex.lpfnWndProc = 0;
wndclassex.cbClsExtra = 0;
wndclassex.cbWndExtra = 0;
wndclassex.hIcon = 0;
wndclassex.hCursor = 0;
wndclassex.hbrBackground = 0;
wndclassex.lpszMenuName = "";
wndclassex.lpszClassName = "myclassname";
wndclassex.hIconSm = 0;
wndclassex.hInstance = 0;
RegisterClassExA(ref wndclassex);
long hWnd = CreateWindowExA(
WS_EX_APPWINDOW,
wndclassex.lpszClassName,
"TAGML",
WS_OVERLAPPED | WS_SYSMENU, // Window won't be resizable
0,
0,
300,
300,
0,
0,
wndclassex.hInstance,
0);
 
if(hWnd == 0)
{
MessageBox(0, "Unable to create window", ".NET", 0);
UnregisterClassA(wndclassex.lpszClassName, wndclassex.hInstance);
return;
}
 
ShowWindow(hWnd, SW_SHOWNORMAL);
UpdateWindow(hWnd);
SetFocus(hWnd);
ShowCursor(true);
//UnregisterClassA(wndclassex.lpszClassName, wndclassex.hInstance);

GeneralRe: Creating a Win32 Window in C#sussAnonymous5 Jul '04 - 9:20 
Ok at this point I have the callback coming back from the window into C#, but I can't get a valid handle. It keeps coming up as zero. Any idea why the HWND is always zero????
 

using System;
using System.Runtime.InteropServices;
 
namespace MyApp
{
public delegate UIntPtr FPtr(IntPtr hWnd, uint uMsg, UIntPtr wParam, UIntPtr lParam);
 
struct WNDCLASSEX
{
public UInt32 cbSize;
public UInt32 style;
public FPtr lpfnWndProc;
public Int32 cbClsExtra;
public Int32 cbWndExtra;
public IntPtr hInstance;
public IntPtr hIcon;
public IntPtr hCursor;
public IntPtr hbrBackground;
public string lpszMenuName;
public string lpszClassName;
public IntPtr hIconSm;
}
 
///
/// Summary description for Class1.
///

class Class1
{
public const string KERNEL32_DLL = "kernel32.dll";
 
[DllImport(KERNEL32_DLL, EntryPoint="GetModuleHandle")]
static extern int GetModuleHandleA(string lpModuleName);

public const string USER32_DLL = "user32";
public const UInt32 CS_VREDRAW = 0x0001;
public const UInt32 CS_HREDRAW = 0x0002;
public const UInt32 WS_EX_APPWINDOW = 0x00040000;
public const UInt32 WS_OVERLAPPED = 0x00000000;
public const UInt32 WS_SYSMENU = 0x00080000;
public const Int32 SW_SHOWNORMAL = 1;
 
public const int WM_QUIT = 0x0012;

[DllImport(USER32_DLL, EntryPoint="MessageBox")]
public static extern int MessageBox(int hWnd, String strMessage, String strCaption, uint uiType);
 
[DllImport(USER32_DLL, EntryPoint="GetForegroundWindow")]
public static extern int GetForegroundWindow();

[DllImport(USER32_DLL, EntryPoint="RegisterClassEx")]
public static extern short RegisterClassExA(ref WNDCLASSEX pcWndClassEx);
 
[DllImport(USER32_DLL, EntryPoint="CreateWindowEx")]
public static extern IntPtr CreateWindowExA(UInt32 dwExStyle, string lpClassName, string lpWindowName, UInt32 dwStyle, Int32 x, Int32 y, Int32 nWidth, Int32 nHeight, IntPtr hwndParent, IntPtr hMenu, IntPtr hInstance, IntPtr lpParam);
 
[DllImport(USER32_DLL, EntryPoint="FindWindow")]
public static extern IntPtr FindWindowA(string lpClassName, string lpWindowName);
 
[DllImport(USER32_DLL, EntryPoint="FindWindowEx")]
public static extern IntPtr FindWindowExA(IntPtr hwndParent, IntPtr hwndChildAfter, string lpClassName, string lpWindowName);
 
[DllImport(USER32_DLL, EntryPoint="ShowWindow")]
public static extern int ShowWindow(long hwnd, Int32 nCmdShow);
 
[DllImport(USER32_DLL, EntryPoint="UpdateWindow")]
public static extern int UpdateWindow(long hwnd);
 
[DllImport(USER32_DLL, EntryPoint="SetFocus")]
public static extern int SetFocus(long hwnd);
 
[DllImport(USER32_DLL, EntryPoint="ShowCursor")]
public static extern int ShowCursor(bool bShow);
 
[DllImport(USER32_DLL, EntryPoint="UnregisterClass")]
public static extern int UnregisterClassA(string lpClassName, IntPtr hInstance);
 
public static UIntPtr WinProc(IntPtr hWnd, uint uMsg, UIntPtr wParam, UIntPtr lParam)
{
Console.WriteLine("WinProc Callback called!!!!!!!");
return UIntPtr.Zero;
}
 
///
/// The main entry point for the application.
///

[STAThread]
static void Main(string[] args)
{
string ClassName = "MyClassName";
string WindowName = "TagML";
 
WNDCLASSEX wndclassex = new WNDCLASSEX();
wndclassex.cbSize = 48;
wndclassex.style = CS_HREDRAW | CS_VREDRAW;
wndclassex.lpfnWndProc = new FPtr(WinProc);
wndclassex.cbClsExtra = 0;
wndclassex.cbWndExtra = 0;
wndclassex.hInstance = IntPtr.Zero;
wndclassex.hIcon = IntPtr.Zero;
wndclassex.hCursor = IntPtr.Zero;
wndclassex.hbrBackground = IntPtr.Zero;
wndclassex.lpszMenuName = "";
wndclassex.lpszClassName = ClassName;
wndclassex.hIconSm = IntPtr.Zero;
 
RegisterClassExA(ref wndclassex);
IntPtr hWnd = CreateWindowExA(
WS_EX_APPWINDOW,
wndclassex.lpszClassName,
WindowName,
WS_OVERLAPPED | WS_SYSMENU, // Window won't be resizable
0,
0,
300,
300,
IntPtr.Zero,
IntPtr.Zero,
wndclassex.hInstance,
IntPtr.Zero);
 
hWnd = FindWindowA(wndclassex.lpszClassName, WindowName);
 
hWnd = FindWindowExA(IntPtr.Zero, IntPtr.Zero, wndclassex.lpszClassName, WindowName);

if(hWnd == IntPtr.Zero)
{
MessageBox(0, "Unable to create window", ".NET", 0);
UnregisterClassA(wndclassex.lpszClassName, wndclassex.hInstance);
return;
}
 

GeneralRe: Creating a Win32 Window in C#sussAnonymous5 Jul '04 - 10:02 
Why isn't CreateWindowEx returning valid window handle?
 
Easy to check Source Files:
http://www.tagenigma.com/qa/CSharp.Win32.zip
 
Do I need to setup a hook or something?
http://msdn.microsoft.com/msdnmag/issues/02/10/CuttingEdge/

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Permalink | Advertise | Privacy | Mobile
Web04 | 2.6.130516.1 | Last Updated 13 Nov 2001
Article Copyright 2001 by Richard Birkby
Everything else Copyright © CodeProject, 1999-2013
Terms of Use
Layout: fixed | fluid