Essentials for calling Windows APIs in C #

Source: Internet
Author: User
Tags bool error code functions readfile win32 visual studio
window in the. Net Framework SDK documentation, the instructions for invoking the Windows API are fragmented, and a little more comprehensive is described in visual Basic. Net. This article brings together the main points of calling APIs in C # to help friends who have not used APIs in C #. In addition, if you have Visual Studio. NET installed, C:\Program Files\Microsoft Visual Studio. Net\frameworksdk\samples\technologies\interop There are a number of examples of calling APIs under the \platforminvoke\winapis\cs directory.

One, calling format

Using System.Runtime.InteropServices; Reference this namespace to simplify the following code
...
Using the DllImportAttribute attribute to introduce API functions, notice that the null method is declared, that is, the method body is empty.
[DllImport ("user32.dll")]
public static extern returntype functionname (type arg1,type arg2,...);
Call is no different from calling other methods

You can use fields to further describe attributes, separated by commas, such as:

[DllImport ("kernel32", entrypoint= "GetVersionEx")]
The public fields for the DllImportAttribute attribute are as follows:

1, callingconvention indicates the CallingConvention value to use when passing method parameters to an unmanaged implementation.

CALLINGCONVENTION.CDECL: The caller cleans up the stack. It enables you to invoke functions that have varargs.
Callingconvention.stdcall: The caller cleans up the stack. It is the default convention for calling unmanaged functions from managed code.

2, CharSet controls the name version of the calling function and indicates how to marshal the String parameter to the method.

This field is set to one of the CharSet values. If the CharSet field is set to Unicode, all string parameters are converted to Unicode characters before being passed to the unmanaged implementation. This also causes the letter "W" to be appended to the name of the DLL entrypoint. If this field is set to ANSI, the string is converted to an ANSI string, and the letter "A" is appended to the name of the DLL entrypoint. Most Win32 APIs Use this convention that appends "W" or "a". If CharSet is set to Auto, this conversion is platform-related (Unicode on Windows NT, Ansi on Windows 98). The default value for CharSet is Ansi. The CharSet field is also used to determine which version of the function will be imported from the specified DLL. The name matching rules for CharSet.Ansi and CharSet.Unicode are very different.

For Ansi, returns "MyMethod" if EntryPoint is set to "MyMethod" and it exists. Returns "Mymethoda" if there is no "MyMethod" in the DLL, but there is a "Mymethoda". The opposite is true for Unicode. Returns "Mymethodw" if EntryPoint is set to "MyMethod" and it exists. Returns "MyMethod" if "Mymethodw" is not present in the DLL, but "MyMethod" exists. If you are using Auto, the matching rules are platform-related (Unicode on Windows NT, Ansi on Windows 98). If ExactSpelling is set to True, "MyMethod" is returned only if "MyMethod" exists in the DLL.

3, EntryPoint indicates the name or ordinal of the DLL entry point to invoke.

If your method name does not want to have the same name as the API function, be sure to specify this parameter, for example:


[DllImport ("user32.dll", charset= "CharSet.Auto", entrypoint= "MessageBox")]
public static extern int MsgBox (IntPtr hwnd,string txt,string caption, int type);

4. ExactSpelling indicates whether the name of the entry point in the unmanaged DLL should be modified to correspond to the CharSet value specified in the CharSet field. If true, appends the letter A to the method name when the DllImportAttribute.CharSet field is set to the Ansi value of CharSet, when the DllImportAttribute.CharSet field is set to CharSet U Nicode value, append the letter W to the name of the method. The default value for this field is false.

5. PreserveSig indicates that the managed method signature should not be converted to a return HRESULT and may have an unmanaged signature that corresponds to an additional [out, retval] parameter corresponding to the return value.

6. SetLastError instructs the callee to invoke Win32 API SetLastError before returning from the attributed method. True indicates that the caller will invoke SetLastError, which defaults to false. The runtime marshaler invokes GetLastError and caches the returned value in case it is overridden by other API calls. The user can retrieve the error code by calling GetLastWin32Error.



Second, the parameter type:

1, numerical type directly with the corresponding can be. (DWORD-> int, WORD-> Int16)

2, the API string pointer type-> string in. Net

3, the API in the handle (DWord)->. NET IntPtr

4, in the API structure->. NET structure or class. Note that in this case, you first qualify the declaration structure or class with the StructLayout attribute

The common language runtime takes advantage of the physical layout of the data fields of the StructLayoutAttribute control class or structure in managed memory, that is, classes or structs need to be arranged in some way. It is important to explicitly control the class layout if you want to pass the class to unmanaged code that needs to specify the layout. Initializes a new instance of the StructLayoutAttribute class with the LayoutKind value in its constructor. LayoutKind.Sequential is used to force members to lay out sequentially in the order in which they appear.

Layoutkind.explicit is used to control the exact location of each data member. With Explicit, each member must use FieldOffsetAttribute to indicate the position of this field in the type. Such as:


[StructLayout (Layoutkind.explicit, size=16, Charset=charset.ansi)]
public class MySystemTime
{
[FieldOffset (0)]public ushort wyear;
[FieldOffset (2)]public ushort Wmonth;
[FieldOffset (4)]public ushort Wdayofweek;
[FieldOffset (6)]public ushort Wday;
[FieldOffset (8)]public ushort Whour;
[FieldOffset (a)]public ushort Wminute;
[FieldOffset ()]public ushort Wsecond;
[FieldOffset ()]public ushort Wmilliseconds;
}

Here is an example of a corresponding class or structure defined in. NET for the OSVERSIONINFO structure in the API:


/**********************************************
* The original structure declaration is defined in the API
* Osversioninfoa STRUCT
* dwOSVersionInfoSize DWORD?
* dwMajorVersion DWORD?
* dwMinorVersion DWORD?
* dwBuildNumber DWORD?
* dwPlatformId DWORD?
* szCSDVersion BYTE 128 dup (?)
* Osversioninfoa ENDS
*
* osVersionInfo equ <OSVERSIONINFOA>
*********************************************/

Declared as classes in. Net
[StructLayout (LayoutKind.Sequential)]
public class osVersionInfo
{
public int osversioninfosize;
public int majorversion;
public int minorversion;
public int BuildNumber;
public int platformid;

[MarshalAs (UnmanagedType.ByValTStr, sizeconst=128)]
Public String versionstring;
}
Or
Declared as structure in. Net
[StructLayout (LayoutKind.Sequential)]
public struct OSVERSIONINFO2
{
public int osversioninfosize;
public int majorversion;
public int minorversion;
public int BuildNumber;
public int platformid;

[MarshalAs (UnmanagedType.ByValTStr, sizeconst=128)]
Public String versionstring;
}


In this example, the Mashalas attribute is used to describe the marshaling format for a field, method, or parameter. Use it as the parameter prefix and specify the data type that the target needs. For example, the following code sends two parameters to the Windows API function string (LPSTR) as a long pointer to the data type:


[MarshalAs (UNMANAGEDTYPE.LPSTR)]
String Existingfile;
[MarshalAs (UNMANAGEDTYPE.LPSTR)]
String NewFile;

Note structure as a parameter, generally preceded by the ref modifier, otherwise there will be an error: The object's reference does not specify an instance of the object.


[DllImport ("kernel32", entrypoint= "GetVersionEx")]
public static extern bool GetVersionEx2 (ref OSVersionInfo2 OSVI);

Third, how to ensure that the use of Managed objects platform invoke success?

If the managed object is not referenced anywhere after invoking platform invoke, the garbage collector may complete the managed object. This frees the resource and invalidates the handle, causing the platform invoke call to fail. The HandleRef wrapper handle guarantees that the managed object will not be garbage collected until the platform invoke call completes.

For example, the following:


FileStream fs = new FileStream ("A.txt", FileMode.Open);
StringBuilder buffer = new StringBuilder (5);
int read = 0;
ReadFile (fs. Handle, buffer, 5, out read, 0); Call the ReadFile function in the win API

Because FS is a managed object, it is possible to be reclaimed by the garbage collector when the platform call is not complete. After wrapping the handle of the file stream with HandleRef, you can avoid being reclaimed by the garbage collector:


[DllImport ("Kernel32.dll")]
public static extern bool ReadFile (
HandleRef Hndref,
StringBuilder Buffer,
int Numberofbytestoread,
out int Numberofbytesread,
Ref overlapped flag);
......
......
FileStream fs = new FileStream ("HandleRef.txt", FileMode.Open);
HandleRef hr = new HandleRef (FS, FS. Handle);
StringBuilder buffer = new StringBuilder (5);
int read = 0;
Platform invoke'll hold reference to HandleRef until call ends
ReadFile (HR, buffer, 5, out read, 0);




Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.