Click to Rate and Give Feedback
Related Articles
Here the author introduces SQL Server Data Services, which exposes its functionality over standard Web service interfaces.

By David Robinson (July 2008)
Here the author answers questions regarding the Entity Framework and provides an understanding of how and why it was developed.

By Elisa Flasko (July 2008)
Here we present techniques for programmatic and declarative data binding and display with Windows Presentation Foundation.

By Josh Smith (July 2008)
Systems that handle failure without losing data are elusive. Learn how to achieve systems that are both scalable and robust.

By Udi Dahan (July 2008)
More ...
Articles by this Author
What's the deal with const functions, and lots more on the reasoning behind the design of the C++/CLI.

By Paul DiLascia (February 2007)
This month DLL problems, context menus, MFC strings to managed C++, and more.

By Paul DiLascia (October 2006)
This month Paul DiLascia teaches readers the right way to create dynamic dialogs, explains satellite DLLs and discusses language resource DLLs.

By Paul DiLascia (September 2006)
This month Paul DiLascia codes some Microsoft Office-style dialog box features.

By Paul DiLascia (August 2006)


By Paul DiLascia (July 2006)
Many of you are no doubt in the process of upgrading to Visual Studio® 2005, so I thought now would be a good time to relate some of my own experiences with the new compiler. What took me so long? Hey, I'm a retro kind of guy! Better late than never!.

By Paul DiLascia (June 2006)
This month: CWebVersion revisited using HTTP instead of FTP, and adding sounds to an MFC-based app.

By Paul DiLascia (May 2006)


By Paul DiLascia (April 2006)
More ...
Popular Articles
Here we introduce you to some of the concepts behind the new F# language, which combines elements of functional and object-oriented .NET languages. We then help you get started writing some simple programs.

By Ted Neward (Launch 2008)
Learn how to create a workflow that uses InfoPath forms and other office documents for passing data to targeted activities and for use in Office documents.

By Rick Spiewak (June 2008)
Speech Server 2007 lets you create sophisticated voice-response applications with Microsoft .NET Framework and Visual Studio tool integration. Here’s how.

By Michael Dunn (April 2008)
Learn how you can peer-enable business applications by allowing them to share state in a serverless peer network.

By Kevin Hoffman (July 2008)
More ...
Read the Blog
SQL Server Data Services (SSDS) is a robust, scale-free data service that internally uses proven SQL Server technology and exposes its functionality over industry standard Web service interfaces. In the July 2008 issue of MSDN Magazine, David Robinson introduces ...
Read more!
Windows Presentation Foundation (WPF) offers excellent support for managing the display and editing of complex data. In the December 2007 edition of MSDN Magazine, John Papa did a great job of explaining essential WPF data binding concepts. ...
Read more!
The most fundamental form of Web testing is HTTP request/response testing. This involves programmatically sending an HTTP request to the Web application, fetching the HTTP response, and examining the response for an expected value. In the May 2008 issue of MSDN Magazine, Read more!
In the November issue of MSDN Magazine, Jeffrey Richter demonstrates some recent additions to the C# programming language that make working with the APM significantly easier. In the June ...
Read more!
The July 2008 issue of MSDN Magazine is now available online. Here's what's in the issue: Data Services: Develop ...
Read more!
The June 2008 issue features the first installment of a new MSDN Magazine column on software design fundamentals. We’ll discuss design patterns and principles in a manner that isn't bound to a specific tool or lifecycle methodology. In this issue, Jeremy Miller starts the Patterns in Practice column ...
Read more!
More ...
From the August 2002 issue of MSDN Magazine
MSDN Magazine
Call Unmanaged DLLs from C#, Killing Processes Cleanly
Paul DiLascia C++ Q&A Archive
Download the code for this article: CQA0208.exe (47 KB)
Q How do I call a DLL or Win32® API function from my C# code if the function has a string (char*) output parameter? I can pass a string for an input parameter, but how do I get the returned string? Also, how do I call functions that require a struct or a callback, like GetWindowsRect and EnumWindows? I'm trying to convert from C++ and MFC, and I can't cope!
E. Nguyen

A One of the major benefits of Microsoft® .NET is that it provides a language-independent development system. You can write classes in Visual Basic®, C++, C#—whatever—and use them in other languages; you can even derive from classes in a different language. But what happens when you want to call some old-school unmanaged DLL? You have to somehow translate .NET objects into the structs, char*'s, and function pointers C expects. In techno lingo, your parameters must be marshaled. Marshaling is a big topic, but luckily you don't have to know much to get the job done.
      To call a DLL function from C#, first you must provide a declaration, something programmers using Visual Basic have been doing for years. In C#, it's DllImport:
using System.Runtime.InteropServices; // DllImport
public class Win32 {
  [DllImport("User32.Dll")]
  public static extern void SetWindowText(int h, String s);
}
      In C#, you use DllImport to tell the compiler where the entry point lives and bundle your wrapper functions inside a class. You can give this class any name you like; I chose Win32. You can even put the class inside a namespace, like I did in Figure 1. To compile Win32API.cs, type:
csc /t:library /out:Win32API.dll Win32API.cs
Now you have a Win32API.dll you can use in any C# project.
using Win32API;
int hwnd = // get it...
String s = "I'm so cute."
Win32.SetWindowText(hwnd, s);
The compiler knows to find SetWindowText in user32.dll and automatically converts your string to LPTSTR (TCHAR*) before calling. Amazing! How does .NET perform this magic? Every C# type has a default marshaling type. For strings, it's LPTSTR. But what happens if you try this for GetWindowText, where the string is an out parameter, not an in parameter? It doesn't work because strings are immutable. Really. You may not have noticed, but whenever you do something to a string, a new string is created. To modify the one and only actual string, you have to use StringBuilder:
using System.Text; // for StringBuilder
public class Win32 {
  [DllImport("user32.dll")]
  public static extern int GetWindowText(int hwnd,
    StringBuilder buf, int nMaxCount);
}
The default marshaling type for StringBuilder is also LPTSTR, but now GetWindowText can modify your actual string.
int hwnd = // get it...
StringBuilder cb = new StringBuilder(256);
Win32.GetWindowText(hwnd, sb, sb.Capacity);
      So the short answer to your first question is, use StringBuilder.
      All that seems super, but what happens if the default marshaling type isn't what you want? For example, suppose you want to call GetClassName? Windows® gurus know that unlike most API functions, GetClassName takes LPSTR (char*), even in Unicode builds. If you pass a string, the common language runtime (CLR) will convert it to TCHARs—oops! Never fear, you can use MarshalAs to override the default:
[DllImport("user32.dll")]
public static extern int GetClassName(int hwnd,
  [MarshalAs(UnmanagedType.LPStr)] StringBuilder buf,
  int nMaxCount);
Now when you call GetClassName, .NET passes your string as an ANSI char, not a wide one. Whew!
      So much for strings. What about structs and callbacks? As you might guess, .NET has a way to handle them, too. Take a simple sample, GetWindowRect. This function stuffs a RECT with a window's screen coordinates:
// in C/C++
RECT rc;
HWND hwnd = FindWindow("foo",NULL);
::GetWindowRect(hwnd, &rc);
      How do you call GetWindowRect from C#? How do you pass the RECT? You do it as a C# struct, using another attribute, StructLayout.
[StructLayout(LayoutKind.Sequential)]
public struct RECT {
  public int left;
  public int top;
  public int right;
  public int bottom;
}
Once you have your struct defined, you can implement the wrapper like so:
[DllImport("user32.dll")]
public static extern int 
  GetWindowRect(int hwnd, ref RECT rc);
It's important to use ref so the CLR will pass your RECT as a reference so the function can modify your object, not a nameless stack copy. With GetWindowRect defined, you can call it like so:
RECT rc = new RECT();
int hwnd = // get it ...
Win32.GetWindowRect(hwnd, ref rc);
Note that you must use the ref in the call as well as the declaration—picky! The default marshaling type for C# structs is—what else?—LPStruct, so there's no need for MarshalAs. But if you made RECT a class instead of a struct, you'd have to implement the wrapper like this:
// if RECT is a class, not struct
[DllImport("user32.dll")]
public static extern int 
  GetWindowRect(int hwnd, 
    [MarshalAs(UnmanagedType.LPStruct)] RECT rc);
      In C#, just like C++, there are lots of ways to do things. But System.Drawing already has a Rectangle struct for handling rectangles, so why reinvent the wheel?
[DllImport("user32.dll")]
public static extern int GetWindowRect(int hwnd, ref Rectangle rc);
The runtime already knows how to marshal a Rectangle as a Win32 RECT. Please note, however, that there's no need to call GetWindowRect (or Get/SetWindowText for that matter) in real code, since the Windows.Forms Control class has properties for this: Control.DisplayRectangle to get the window rectangle, and Control.Text to get or set the text.
Rectangle r = mywnd.DisplayRectangle;
mywnd.Text = "I'm so cute";
      You only need the API wrappers I've shown if for some reason you only have an HWND, not a Control-derived object.
      Strings, structs, Rectangles... what else? Oh yes, callbacks. How do you pass a callback from C# to unmanaged code? All you have to do is remember to say "delegate."
delegate bool EnumWindowsCB(int hwnd,     int lparam);
Once you've declared your delegate/callback type, the wrapper goes like this:
[DllImport("user32")]
public static extern int 
  EnumWindows(EnumWindowsCB cb, int lparam);
Since the delegate line merely declares a delegate type, you have to provide an actual delegate in your class
// in your class
public static bool MyEWP(int hwnd, int lparam) {
  // do something
  return true;
}
then pass it to the wrapper like so:
EnumWindowsCB cb = new EnumWindowsCB(MyEWP);
Win32.EnumWindows(cb, 0);
      Astute readers will notice I glossed over the problem of lparam. In C, if you give EnumWindows an LPARAM, Windows will notify your callback with it. Typically lparam is a pointer to some struct or class that contains context info that you need to do whatever it is you're doing. But remember, you can never say "pointer" in .NET! So what to do? In this case, you can declare your lparam as IntPtr and use a GCHandle to wrap it:
// lparam is IntPtr now
delegate bool EnumWindowsCB(int hwnd,     IntPtr lparam);

// wrap object in GCHandle
MyClass obj = new MyClass();
GCHandle gch = GCHandle.Alloc(obj);
EnumWindowsCB cb = new EnumWindowsCB(MyEWP);
   Win32.EnumWindows(cb, (IntPtr)gch);
   gch.Free();
      Don't forget to call Free when you're finished! Sometimes in C# you actually get to free your own memory, just like in the old days. To access the lparam "pointer" inside your enumerator, use GCHandle.Target.
public static bool MyEWP(int hwnd, IntPtr param) {
  GCHandle gch = (GCHandle)param;
  MyClass c = (MyClass)gch.Target;
  // ... use it
  return true;
}
      Figure 2 shows a class I wrote that encapsulates EnumWindows in an array. Instead of fussing with delegates and callbacks, you can write the following:
WindowArray wins = new WindowArray();
foreach (int hwnd in wins) {
 // do something
}
Pretty neat! Believe it or not, there's a method to all this madness. Everything makes sense once you get the hang of it. You can even use DllImport-style wrappers in managed C++. With .NET, you can move freely between managed and unmanaged worlds, as long as you do the proper translation. Most of the time you don't have to do anything; it just works. Occasionally, you need MarshalAs or a wrapper like GCHandle. For more on interop, read "Platform Invoke Tutorial" in the .NET documentation.
      Figure 3 shows a little program I wrote. ListWin lists the top-level windows with switches so you can display HWNDs, class names, titles, and/or window rectangles, using RECT or Rectangle. Figure 4 shows a sample run. I stripped some of the code to save space here; as always, you can grab the full source from the link at the top of this article.

Figure 4 ListWin Sample
Figure 4 ListWin Sample

Q I'm writing an app that backs up files to a network drive. My program works unless a user has Microsoft Outlook® open; then my program can't copy the mailbox file (mailbox.pst) because Outlook opens it with exclusive access. I want to be able to kill Outlook if it's running. How can I kill a process cleanly?
Jose Mercando

A A program called tskill.exe (see Figure 5) comes with newer versions of Windows and it does what you want.

Figure 5 tskill
Figure 5 tskill

For example
tskill outlook
kills the running instance of Outlook. But if you want to write the code yourself, the safest way to kill a process is to post a WM_CLOSE message to its main window:
HWND hwnd = // get main window
PostMessage(hwnd, WM_CLOSE, 0, 0);
Once the message is posted, you usually should wait for the process to actually terminate:
HANDLE hp = OpenProcess(SYNCHRONIZE|PROCESS_TERMINATE,FALSE,pid);
WaitForSingleObject(hp, 5000); // wait up to 5 seconds
When the process terminates, it flips to the signaled state and WaitForSingleObject returns WAIT_OBJECT_0. If it returns something else, the process is either hung or still doing something. In that case, the only way to kill the process is to pull out the big bazooka, TerminateProcess.
if (WaitForSingleObject(hp, 5000) != WAIT_OBJECT_0)
    TerminateProcess(hp,0); // Hasta la vista, baby!
      If you want to be really nice, you can send the main window a WM_QUERYENDSESSION before you close. Apps receive this message when the user is about to end the session (log out) or when someone calls ExitWindows. Apps are suppose to prepare for imminent death. Typically this means presenting a dialog that says something like, "Um, pardon me, but the system is about to implode and if you want to save the last ten hours of changes you've made, this would be a good time; would you like to save now? (Yes/No/Cancel)." WM_QUERYENDSESSION can even reject death (for example if the user chooses Cancel), in which case life goes on. In code, it looks like this:
DWORD bOKToKill = FALSE;
SendMessageTimeout(hwnd, WM_QUERYENDSESSION, 0, 0,
    SMTO_ABORTIFHUNG|SMTO_NOTIMEOUTIFNOTHUNG, 100, &bOKToKill);
if (bOKToKill) {
  // post WM_CLOSE and wait, etc.
}
      It's important to use SendMessageTimeout, not SendMessage, in case the process you're trying to close is hung. SMTO_NOTIMEOUTIFNOTHUNG is a flag that's only available in Windows 2000 and Windows XP that says, "don't timeout if the thread isn't hung." In other words, if the thread is processing normally then wait forever so the user can read the dialog and decide what to do. When the user makes his or her final decision, SendMessageTimeout will return with bOKToKill set appropriately. Naturally, all this assumes the other apps are well-behaved and process WM_QUERYENDSESSION as they're supposed to, which isn't always the case.
      I wrote a program, kp.exe (see Figure 6), to kill a process just like tskill. It uses a class CFindKillProcess (see Figure 7) to find and kill the process:
CFindKillProcess fkp;
DWORD pid = fkp.FindProcess("outlook.exe");
fkp.KillProcess(pid);
FindProcess uses CProcessIterator and CProcessModuleIterator from last month's column to iterate the processes, looking for one whose first module (the EXE that started the process) matches the one you want to find:
CProcessIterator itp;
for (DWORD pid=itp.First(); pid; pid=itp.Next()) {
  CProcessModuleIterator itm(pid);
  HMODULE hModule = itm.First(); // .EXE
  if (/* module name = what I'm looking for */) {
    return pid;
  }
}
      FindProcess looks for "foo" or "foo.exe." If it finds the process, it returns the process ID, which you can then pass to CFindKillProcess::KillProcess. KillProcess encapsulates the close window/terminate logic I just sketched. It uses CMainWindowIterator from last month's column to iterate the main windows of the process (there can be more than one), posts a WM_CLOSE to each, then waits for the process to die. It has a BOOLean parameter that says whether to use TerminateProcess if the app doesn't die willingly. For details, see Figure 7.

Send questions and comments for Paul to cppqa@microsoft.com.
Paul DiLascia is a freelance writer, consultant, and Web/UI designer-at-large. He is the author of Windows++: Writing Reusable Windows Code in C++(Addison-Wesley, 1992). Paul can be reached at askpd@pobox.com or http://www.dilascia.com.

Page view tracker