Managed code (VB.net and C#) are great for a lot of things, but unfortunately, even as of VS2008, it’s still missing at least one. Standard DLL exports.
You see, way back in the olden days, virtually every DLL in Windows was written in C or assembler and exported functions via the standard DLL export table.
Then came COM and now .NET, providing much easier, object oriented export capabilities. Old style EXPORTS have been falling by the wayside ever since.
Unfortunately, if you program for Windows, eventually you’ll find yourself needing to either consume or provide exports. There’s just no way around it.
For consuming (ie simply “calling”) exported functions in a DLL, .net makes that almost trivially easy. All of the Windows API can be called in this way, simply by including the proper attributes (for VB) for the function declaration in your application. Here’s an example for the SENDMESSAGE Windows API function.
<DllImport("user32.dll", SetLastError:=True, CharSet:=CharSet.Auto)> _ Private Shared Function SendMessage(ByVal hWnd As IntPtr, ByVal Msg As UInteger, ByVal wParam As IntPtr, ByVal lParam As IntPtr) As IntPtr End Function
The Hard Part
However, exporting functions from a .NET DLL in the standard Windows API style is not near as easy.
Why would you need to do this? The main reason is to provide hooks that other applications can call. There are many, many applications out there that require addins or plugins to export standard DLL entry points. Being unable to do this in .net means either having to write a shell in C/C++ around those entry points (doable but cumbersome), or simply not providing that functionality.
The good news is that the .NET compiler designers didn’t completely forget about such down-to-the-metal tidbits as this. The bad news is that they didn’t provide any syntactic sugar to make it straightforward either.
Emilio Reale posted an excellent article on CodeProject that discusses the dirty IL (Intermediate Language in .net speak) mechanics of how to:
- compile your .net DLL
- disassembly it with ILDASM to IL source code.
- find the necessary bits in the disassembled output and what to change them to
- reassembly the IL source using ILASM into a DLL with the proper functions exported.
All fine and dandy till you look at what’s required. Needless to say, it’s an amazingly involved process to perform manually.
Fortunately, another CodeProject contributor tackled this problem and posted this article. In it, he presents a small utility and attribute definition dll that allows you to export a function (almost ANY function) from a .NET DLL simply by applying an attribute to it, like so:
<ExportDllAttribute.ExportDll("MyFunction", _ System.Runtime.InteropServices.CallingConvention.Cdecl)> _ Public Shared Sub EntryPoint_MyFunction() ...my code goes here.... End Sub
and then running the utility on the compiled DLL, which automates the above tasks.
It takes a little work to get things set up, but in the end, it worked flawlessly for me. Within just a few hours, I’d put together the shell of a plugin for an application that I’d had reservations about writing plugins for, simply because it looked like I’d have to do so in C++.
Now, the whole plugin is done, it’s all in VB.net (my language of preference currently), it’s a single DLL with no dependencies (other than the .net runtime <g>), and it can be deployed by simply copying it into a folder.
Can’t get better than that!