[Windows rookie] C # to call the Windows API Technical Key Points

In the .Net Framework SDK documentation, an indication of the Windows API calls relatively fragmented, and which is slightly more comprehensively for Visual Basic .net is about. This article will point the C # API calls in the following collection, I want to give unused API in C # friends a little help. Also, if the installation of Visual Studio .net, then in C: \ Program Files \ Microsoft Visual Studio .NET \ FrameworkSDK \ Samples \ Technologies \ Interop \ PlatformInvoke \ WinAPIs \ There are plenty of examples of API calls at CS directory.

First, call format

Copy the code code is as follows:

 using System.Runtime.InteropServices; // this namespace references, simplified code behind
...
// DllImportAttribute used to introduce api function characteristic, note method declaration is empty, i.e. the method body is empty.
[DllImport ( "user32.dll")]
public static extern ReturnType FunctionName (arg1 of the type, of the type arg2, ...);
// When calling the call is no different to other methods 


Field may be used to further illustrate features, separated by commas, such as:

Copy the code code is as follows:

[ DllImport( "kernel32", EntryPoint="GetVersionEx" )]  


Public field DllImportAttribute characteristics are as follows:
. 1, CallingConvention value indicating achieve CallingConvention delivery method parameters used to unmanaged. 
CallingConvention.Cdecl: caller clean up the stack. It enables you to call a function with varargs.
CallingConvention.StdCall: callee clean up the stack. It is the default agreed to call an unmanaged function from managed code.

 

2, CharSet call control function indicating the name and version of how to marshal String parameter to the method.

This field is set to one CharSet value. If the field is set to CharSet Unicode, all the parameters passed to the string into Unicode characters are converted before unmanaged implementation. This also results in an additional letter "W" in the name of the DLL EntryPoint. If this field is set to Ansi, the string is converted to an ANSI string, while the additional letter "A" in the name of the DLL EntryPoint.

Most Win32 API to use this additional "W" or "A" of the agreement. If the CharSet is set to Auto, then this conversion is platform-dependent (on Windows NT is Unicode, on Windows 98 as Ansi). The default CharSet value Ansi. CharSet field is also used to determine which version of the function specified DLL import from.

CharSet.Ansi and CharSet.Unicode name matching rules very different. For Ansi, if the EntryPoint is set to "MyMethod" and it exists, "MyMethod" is returned. If the DLL is not "MyMethod", but there are "MyMethodA", then "MyMethodA" return.

It is just the opposite for Unicode. If EntryPoint is set to "MyMethod" and it exists, "MyMethodW" is returned. If there is no "MyMethodW" DLL in, but there are "MyMethod", then "MyMethod" return. If you are using Auto, the matching rule is platform-dependent (on Windows NT is Unicode, on Windows 98 as Ansi). If ExactSpelling set to true, then return only when "MyMethod" presence "MyMethod" DLL in.

3, EntryPoint indicating DLL entry point name or number to be called. 
If you do not want the same name as the method name and api function, it must be specified, for example:

 

Copy the code code is as follows:

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


4, ExactSpelling indicating whether to change the name of the unmanaged DLL entry points to specify the CharSet CharSet value corresponding field. If true, the field is set to Ansi when DllImportAttribute.CharSet CharSet value, the letter A is added to the name of the method, when the field is set to DllImportAttribute.CharSet CharSet Unicode value, an additional letter to the name of the method of W. The default value of this field is false.

 

5, PreserveSig indicating hosting method signature should not be converted into a return HRESULT, and there may be additional return values ​​[out, retval] unmanaged signature corresponds to a parameter.

6, SetLastError indicating the caller attributes before returning from the method call Win32 API SetLastError. true indicate that the caller will call SetLastError, the default is false. Marshaler runtime calls GetLastError and cache the return value, which is invoked to prevent overwriting other API. The user can retrieve the error code by calling GetLastWin32Error.

Second, the parameter type:

1, with the corresponding value of the direct type can. (DWORD -> int, WORD -> Int16)
2, the API pointer type string -> .net in String
. 3, the API in the handle (dWord) -> .net in IntPtr
. 4, the structure of the API -> .net structural or class. Note that this case, the statement defines a first characteristic or a class structure with StructLayout

Data field using common language runtime class or StructLayoutAttribute control physical layout structure in managed memory, i.e., structure type, or arranged in some way required. If you type is passed to unmanaged code to specify the layout, layout category Explicit control is important. With its constructor initializes a new instance of the value LayoutKind StructLayoutAttribute class. LayoutKind.Sequential used to force the members of the order in the order they appear in the layout.

LayoutKind.Explicit for controlling the precise location of each data member. Using Explicit, each member must FieldOffsetAttribute indication position this field types. Such as:

Copy the code code is as follows:

 [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(10)]public ushort wMinute; 
[FieldOffset(12)]public ushort wSecond; 
[FieldOffset(14)]public ushort wMilliseconds; 


OSVERSIONINFO structure described below for the API, an example of the class definition to the structure or in .net:

Copy the code code is as follows:

  /**********************************************
* API中定义原结构声明
* OSVERSIONINFOA STRUCT
*  dwOSVersionInfoSize   DWORD      ?
*  dwMajorVersion        DWORD      ?
*  dwMinorVersion        DWORD      ?
*  dwBuildNumber         DWORD      ?
*  dwPlatformId          DWORD      ?
*  szCSDVersion          BYTE 128 dup (?)
* OSVERSIONINFOA ENDS
*
* OSVERSIONINFO  equ  <OSVERSIONINFOA>
*********************************************/ 

 

Copy the code code is as follows:

 //.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;
}
//或者
//.net中声明为结构
[ StructLayout( LayoutKind.Sequential )]  
public struct OSVersionInfo2 
{
public int OSVersionInfoSize;
public int majorVersion; 
public int minorVersion;
public int buildNumber;
public int platformId;

 

Copy the code code is as follows:

[ MarshalAs( UnmanagedType.ByValTStr, SizeConst=128 )]    
public String versionString;


MashalAs characteristics used in this example, it is used to describe the field, method or parameter marshaling format. Prefix and use it as a parameter to specify the type of data desired target. For example, the following two parameters as the code length pointer data type sealing string to the Windows (LPStr) API functions: 

Copy the code code is as follows:

 [MarshalAs(UnmanagedType.LPStr)]
String existingfile;
[MarshalAs(UnmanagedType.LPStr)]
String newfile; 


Note that structure as an argument, the general in front of ref modifier to add, or an error: Object reference not specified instance of the object.

Copy the code code is as follows:

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


Third, how to ensure the use of the managed object platform invoke success?
If the managed object is not referred to in any position after calling platform invoke, the garbage collector may be completed by the managed object. This will free up resources and handle is invalid, resulting in a platform invoke call failed. HandleRef package with a handle ensures platform invoke before the call is completed, the managed object is not garbage collected.

 

Such as the following:

Copy the code code is as follows:

 FileStream fs = new FileStream( "a.txt", FileMode.Open );
StringBuilder buffer = new StringBuilder( 5 );
int read = 0;
ReadFile(fs.Handle, buffer, 5, out read, 0 ); //调用Win API中的ReadFile函数 


Since fs is a managed object, so there may be garbage in the trash has not been completed when the platform invoke. The stream file handle HandleRef After packaging, garbage can avoid station:

Copy the code code is as follows:

 [ 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 will hold reference to HandleRef until call ends
ReadFile( hr, buffer, 5, out read, 0 ); 

Guess you like

Origin www.cnblogs.com/code1992/p/11687151.html