
C# ПІДРУЧНИКИ / c# / MS Press - Msdn Training Programming Net Framework With C#
.pdf

Module 15 (Optional): Interoperating Between Managed and Unmanaged Code |
17 |
|
|
|
|
Exercise 1
Calling a Win32 API from Managed Code
In this exercise, you will call Win32 APIs from managed code. This includes adding DllImport attributes to methods in your class, and then invoking those methods. The first unmanaged function you call retrieves the user name, and the second unmanaged function you call displays the user name in a message box.
!Open the Visual Studio .NET project for this exercise and examine the application UI
1.In Microsoft Windows® Explorer, move to <install folder>\Labs\ Lab15\Lab15.1\Starter.
2.Double-click CallingUnmanagedCode.csproj to open the project for this exercise in Visual Studio .NET.
3.In the Solution Explorer pane, double-click ManagedCode.cs. The UI design for the Windows Forms application appears. Examine the UI for a moment to become familiar with it.
4.Press F7 to edit the code that implements the Windows Form application.
!Add the DllImport attribute for the method used to retrieve the user name
•GetUserNameEx is the Win32 API to be called. The signature for this function is as follows:
BOOLEAN GetUserNameEx( |
|
|
EXTENDED_NAME_FORMAT NameFormat, |
// name format |
|
LPTSTR lpNameBuffer, |
// name |
buffer |
PULONG nSize |
// size |
of name buffer |
); |
|
|
In the ManagedCode.cs file, notice the ‘TODO’ comment near the beginning, instructing you to add the declaration for a method that is used to call GetUserNameEx. Add the declaration for the method, including the DllImport attribute. Your method should also be named GetUserNameEx. Some key information you need in order to add the declaration is listed in the following table.
Information |
Value |
DLL containing the GetUserNameEx function |
secur32.dll |
Character set to use |
CharSet.Auto |
For information about the managed data types to use in your method declaration, see Marshaling earlier in this module. Notice that you can use the task list tab in the lower-left hand pane to find the ‘TODO’ comments. Click View, click Show Tasks, and then click All if the ‘TODO’ comments do not appear in the task list.

18Module 15 (Optional): Interoperating Between Managed and Unmanaged Code
!Add the DllImport attribute for the method used to display the user name
•MessageBox is the Win32 API to be called. The signature for this function is as follows:
int MessageBox( |
|
|
|
HWND |
hWnd, |
// handle to owner |
window |
LPCTSTR lpText, |
// text in message |
box |
|
LPCTSTR lpCaption, |
// message box title |
||
UINT |
uType |
// message box style); |
In the ManagedCode.cs file, notice the next ‘TODO’ comment near the beginning, instructing you to add the declaration for a method that is used to call MessageBox. Add the declaration for the method, including the DllImport attribute. Your method should also be named MessageBox. Some key information you need in order to add the declaration is listed in the following table.
Information |
Value |
|
|
DLL containing the MessageBox function |
user32.dll |
Character set to use |
CharSet.Auto |
For information about the managed data types to use in your method declaration, see Marshaling earlier in this module. Notice that the strings passed to MessageBox are input-only parameters.
!Implement the methods that call unmanaged code
1.Scroll down in the ManagedCode.cs file to find the next ‘TODO’ comment near the end of the file in the buttonRetrieveUserName_Click method. The comment instructs you to add the code to retrieve the user name and display it in a message box. Replace the comment with a call to
GetUserNameEx followed by a call to MessageBox.
The SamCompatibleNameFormat constant represents the format of the username that will be returned from GetUserNameEx. Note that GetUserNameEx returns a non-zero value if it succeeds. Otherwise it returns a value of zero.
For the uType parameter to MessageBox, you should pass in
(uint)MessageBoxIcon.Information if GetUserNameEx succeeds, or (uint)MessageBoxIcon.Error if GetUserNameEx fails. MessageBox returns a value for the button clicked on the message box, but this should not affect the application.
2.Scroll down to the catch block to find the next ‘TODO’ comment instructing you to add a MessageBox call to report the exception as an error. Replace the comment with a call to MessageBox after the exception message is created. Pass in (uint)MessageBoxIcon.Error for the uType parameter.
Module 15 (Optional): Interoperating Between Managed and Unmanaged Code |
19 |
|
|
|
|
! Build and test your application
1.On the File menu, click Save All.
2.On the Build menu, click Build Solution. Your application should build successfully. The following statement should appear as the last line of the output window:
Build: 1 succeeded, 0 failed, 0 skipped.
3.On the Debug menu, click Start, and then click Retrieve User Name. The user name should be displayed in a message box. Click OK to dismiss the message box.
4.To close the application, click Exit.


Module 15 (Optional): Interoperating Between Managed and Unmanaged Code |
21 |
|
|
|
|
Runtime Callable Wrappers
Topic Objective
To describe the purpose of runtime callable wrappers.
Lead-in
The primary goal of runtime callable wrappers is to hide the differences between the managed and unmanaged programming models.
*****************************ILLEGAL FOR NON-TRAINER USE******************************
In order to call a COM object, the runtime uses a runtime callable wrapper. Runtime callable wrappers contain all of the information needed to call the COM object. The runtime callable wrapper maintains a cache of interface pointers on the COM object it wraps and releases its reference on the COM object when the wrapper is no longer needed. The runtime performs garbage collection on the runtime callable wrapper after the COM object has been released.
One of the primary functions of the runtime callable wrapper is to marshal data between managed and unmanaged code. The runtime callable wrapper provides marshaling for method arguments and method return values whenever the client and server have different representations of the data passed between them. For example, when a .NET Framework client passes a String type as part of an argument to a managed object, the wrapper converts the String type to a BSTR type. Should the COM object return a BSTR type to its managed caller, the caller receives a String type. Both the client and the server send and receive data types that are familiar to each of them. Some other types require no conversion. For instance, a standard wrapper will always pass a 4-byte integer between managed and unmanaged code without converting the type.
The runtime callable wrapper implements the interfaces that the COM object implements and exposes the methods, properties, and events from the object’s interfaces. In the illustration, the wrapper exposes the INew interface and all its methods and properties to the client, but consumes the IUnknown and IDispatch interfaces. The IUnknown interface is used by the runtime to identify the COM object, provide type coercion, and control lifetime management. The runtime distinguishes between COM objects by comparing the value of the IUnknown interface for each object. The wrapper uses the QueryInterface method to get and hold a reference to an unmanaged object. The reference is retained until the runtime performs garbage collection on the wrapper. The wrapper releases the unmanaged object during garbage collection.
