Introduction
This article demonstrates interoperability between .NET managed code and old unmanaged code. It uses the P/Invoke mechanism to call unmanaged DLL entry points.
To demonstrate this technique let's create a managed C++ console program that will
run an application specified as a parameter of its command line.
We use the ShellExecute
function exported by the unmanaged DLL shell32.dll
First we create a new C++ project based on the managed C++ Console Application.
The application wizard creates a class that has one static method main()
that is an entry point to our application.
To access the .NET classes for P/Invoke support add the following line to your code:
using namespace System::Runtime::InteropServices;
In order to call a DLL export, we need to declare the method with the attached
a DllImport
attribute.
[DllImport("shell32.dll")]
extern "C" int _cdecl ShellExecute(int hwnd,
String *strVerb,
String *strFileName,
String *strParameters,
String *strDirectory,
int nShowCmd);
The marshaling service will marshal the managed types to the unmanaged types according
its built-in rules. During the P/Invoke call the marshaler will automatically copy the
managed integer type into an unmanaged integer type, it will convert (copy) the Unicode
character buffer of the String objects to the ANSI character buffer.
Other data types have other marshalling characteristics. You can override the default
behavior by specifying custom marshalling. Refer to the Data Marshaling Specification
section of the .NET Beta Specification in MSDN.
Now you can call your declared method. The following code illustrates this.
#using <mscorlib.dll>
using namespace System;
using namespace System::Runtime::InteropServices;
[DllImport("shell32.dll")]
extern "C" int _cdecl ShellExecute(int hwnd,
String *strVerb,
String *strFileName,
String *strParameters,
String *strDirectory,
int nShowCmd);
__gc class Launcher
{
public:
static int StartProgram(String *strFileName)
{
return ShellExecute(0,
S"Open",
strFileName,
String::Empty,
String::Empty,
1 );
}
};
int main( int argc, char *argv[ ])
{
if(argc < 2)
{
Console::Write(S"Not enough parameters.");
return 0;
}
if(Launcher::StartProgram(new String(argv[1])) < 33)
Console::Write(S"Couldn't launch the program!");
return 0;
}
History
16 Oct 2001 - updated source for VS .NET beta 2