Shedding Light on windows Programming Home Training Resources Registration About the Paul Yao Company
The Paul Yao Company

The P/Invoke Wizard
Last updated: May 15, 2004
By: Paul Yao
The Paul Yao Company

click to download

click to order

What is the P/Invoke Wizard?

I wrote the P/Invoke Wizard to save time for both myself and my co-author, David Durant, while we were writing our .NET Compact Framework books. I wrote this tool because I found that P/Invoke declarations were both tedious and error prone when done by hand. Now with a few clicks of my mouse, I get complete and correct declarations in a fraction of the time it previously took. My company started selling the P/Invoke Wizard in 2002. Since finishing my books, I have been able to make some time to update the tool - and now version 1.3 is available.

The P/Invoke Wizard is a tool that automates the process of writing declarations in managed code for calling into unmanaged DLLs. With just a few mouse clicks, the P/Invoke Wizard can opens a C or C++ include file and create thousands of .NET-compatible P/Invoke declarations in a choice of C# or Visual Basic .NET. The wizard can be set for compatibility with either the .NET Compact Framework or the .NET Framework.

When we started selling the P/Invoke Wizard, we did not have a demo version; but a lot of people were asking for what features are supported. We now offer a demo version that you can download to see how well it works. There are two versions you can download: one with the Microsoft MSI installer runtime (over 3MB), and one without (under 100K). The demo version provides the full conversion for the registered, working version. The demo version does not provide clipboard or file-save operations for converted declarations.


Background: What is P/Invoke?

P/Invoke - also known as "Platform Invoke" - lets managed code call into unmanaged DLL functions. P/Invoke is supported in both the .NET Framework and the .NET Compact Framework. There are differences between how P/Invoke works in the two frameworks, and the P/Invoke Wizard lets you set an option for the framework that you are targeting.

Sometimes it makes sense to port legacy native code to managed code. But often, it makes sense to use existing native code DLLs that have already been written, debugged, and deployed. P/Invoke helps bridge the gap between managed code and native code, and the P/Invoke Wizard simplifies the task of creating managed code declarations to access your native-code DLLs.


Can I avoid P/Invoke?

Can you avoid P/Invoke? For stand-alone, new code - perhaps. But if your software relies on a native DLL for which you do not have the source code (perhaps provided by a third-party). In that case, you have to use P/Invoke (or remove a feature from the managed code version of your software -- something that users might not like).

Another situation when you need to use P/Invoke is when you want to access an operating system feature not supported by the framework. On the desktop .NET Framework, you are going to need to call P/Invoke for the following:

  • ActiveX Controls
  • Custom, Third-Party DLLs
  • DirectX
  • Drawing with 3D Graphics
  • COM components
  • Mail API (MAPI)
  • Serial communications
  • Structured Storage
  • Telephony API (TAPI)
  • Windows Hooks

While P/Invoke is helpful on the desktop, it is essential when building Windows Mobile or Windows CE applications written for the .NET Compact Framework. The Compact Framework brings to mobile and embedded devices some of the features of the desktop .NET Framework. But many features from the desktop framework were left out to adapt to the memory constraints of mobile and embedded devices. You get an idea about the differences between the two frameworks when you consider that the .NET Compact Framework is about 2 MB, a significant scaling back from the 25+ MB of the desktop .NET Framework. Some of the areas where P/Invoke is critical for Compact Framework programming includes the following:

  • ActiveSync
  • ActiveX Controls
  • Carets
  • CE Property databases
  • Clipboard
  • COM Components
  • Common Dialog Boxes
  • Cryptography API
  • Custom controls
  • Custom, Third-Party DLLs
  • DirectX
  • Fonts - enumerating available fonts; creating rotated fonts; using ClearType fonts
  • File System enumeration - flash cards, directories, etc.
  • Mail API (MAPI)
  • Memory allocation of unmanaged memory
  • Microsoft Message Queue (MSMQ)
  • Pocket Outlook Object Model (POOM)
  • Point-to-Point Message Queues
  • Printing
  • Real Time Threads
  • Registry
  • Running programs
  • Serial Communications
  • Shell functions
  • Structured Storage
  • Sounds
  • Telephony API (TAPI)
  • Stream interface drivers
  • Windows Hooks

How Does The P/Invoke Wizard Work?

P/Invoke works by reading C/C++ include (.H) files. The P/Invoke processing engine takes the various declarations and produces a compatible .NET version in your choice of C# or Visual Basic .NET.

P/Invoke understands the following kinds of C/C++ declarations:

  • #define statements for integer and string constants
  • enum statements that define enumerated constant values
  • typedef struct declarations that define the layout of structures
  • typedef declarations for custom data types
  • union statements
  • function prototypes

The P/Invoke Wizard converts #define constants into the equivalent C# or VB.NET declarations. It converts C/C++ data structure definitions and converts them into the equivalent .NET data structures. It also reads C/C++ function prototypes and generates the equivalent function.


Examples of P/Invoke Conversions

Here is an (admittedly) simple example of some C/C++ declarations that were converted by the P/Invoke Wizard. Starting with this declaration:

// C/C++ input
#define PS_SOLID 0
#define PS_DASH 1
#define PS_NULL 5

typedef struct tagRECT
{
LONG left;
LONG top;
LONG right;
LONG bottom;
} RECT;

WINBASEAPI
DWORD
WINAPI
GetTempPathW(
DWORD nBufferLength,
LPWSTR lpBuffer);

With a click of the mouse, the above input gets converted into either C# or Visual Basic.NET. The C# version to the above is shown here:

// [C#] output: managed code declarations
public const int PS_SOLID = 0;
public const int PS_DASH = 1;
public const int PS_NULL = 5;

[StructLayout(LayoutKind.Sequential,Pack=4)]
public struct RECT
{
public Int32 left;
public Int32 top;
public Int32 right;
public Int32 bottom;
};

[DllImport("kernel32.dll")]
public static extern Int32 GetTempPathW (UInt32 nBufferLength, String lpBuffer);

This code assumes that your C# code includes a reference to the System.Runtime.InteropServices namespace, with a statement like the following:

// [C#] required declaration
using System.Runtime.InteropServices;

For the above C/C++ declaration, the P/Invoke Wizard generates the VB.NET declarations shown below:

' [VB] output: managed code declarations
public const PS_SOLID As Integer = 0
public const PS_DASH As Integer = 1
public const PS_NULL As Integer = 5

Public Structure RECT
Public left As Int32
Public top As Int32
Public right As Int32
Public bottom As Int32
End Structure

<DllImport("kernel32.dll")> _
Public Shared Function GetTempPathW ( _
ByVal nBufferLength As UInt32 _
, ByVal lpBuffer As String _
) As Int32
End Function

The above code assumes that your Visual Basic.NET code includes a reference to the System.Runtime.InteropServices namespace, with a statement like the following:

' [VB] required declaration
Imports System.Runtime.InteropServices

Supported P/Invoke Features

The previous example does not do justice to the available features that the P/Invoke Wizard provides. We've used it extensively in writing production code for both mobile and desktop managed code development, and keep adding new features as we need them (and - increasingly - from our growing user base, as we hear about features that are needed).

  • Creates declarations in your choice of C# or Visual Basic .NET
  • Supports selection of a target framework: .NET Framework for the desktop, and .NET Compact Framework for Windows Mobile smart devices (and Windows CE)
  • Converts #define declarations to managed code constant declarations
  • Optionally places like-named groups of contiguous #define constants into enumerations (based on proximity and similarity between constant names)
  • Recognizes typedef declarations for application-specific data types
  • Converts structure definitions into managed code structure declarations
  • For arrays in structures, adds the MarshalAs attribute (desktop-only; not supported on mobile devices for CF 1.0)
  • Convert function declarations into managed code function declarations using the appropriate DllImport attribute.
  • For Visual Basic.NET, distinguishes between Sub (methods with no return value) and Function (methods with return values)
  • Plus much more...

P/Invoke Wizard Benefits

The P/Invoke Wizard saves programmers time and frustration. What is your time worth? If you have a large number of declarations to convert, this tool can eliminate hours of tedious coding with the click of a mouse. The time saved is better spent working on other, more interesting parts of your software projects.

What is it worth to you to eliminate some frustration from your work day - or from your life? Yes, it's true that P/Invoke is very interesting to learn, and every managed code programmer is going to want to create some declarations by hand. That helps you to really understand them. But when you have a large number of declarations to handle, doing them by hand does not make sense; it is tedious and error prone work.

The bottom line is that it makes more sense for software developers to spend time on the creative and interesting challenges that their jobs demand of them.


P/Invoke Wizard Limitations

Version 1.3 of the P/Invoke Wizard relies on information found in include (*.H) files. So if you do not have the include file, then P/Invoke cannot help you. It does not, for example, use the binary DLL file for input. Nor does the P/Invoke Wizard use a COM Type Library. In short, you need include (*.h) file declarations. Another limitation is that this tool does not accept executable C++ statements -- function calls, loops, etc.

What it *does* provide is a shortcut when you have a lot of native code declarations that you need to access from managed code. It saves your time. It saves your frustration. Download the demo version today, using the link (below). When you see much time you can save, register your copy using the other link (below).


click to download

click to order
CONTACT US LOGISTICS REQUEST MORE INFORMATION