The main points of Calling windows api in c # Are in the. Net Framework SDK documentation. The instructions on calling Windows API are scattered, and some of them are described in Visual Basic. net. In this article, the main points of calling APIs in C # are summarized as follows, hoping to help those who have not used APIs in C. In addition, if Visual Studio is installed. in C: \ Program Files \ Microsoft Visual Studio. NET \ FrameworkSDK \ Samples \ Technologies \ Interop \ PlatformInvoke \ WinAPIs \ CS directory contains a large number of examples of calling APIs. 1. The call format is using System. runtime. interopServices; // reference this namespace to simplify the subsequent code... // use the DllImportAttribute feature to introduce api functions. Note that empty methods are declared, that is, the method body is empty. [DllImport ("user32.dll")] public static extern ReturnType FunctionName (type arg1, type arg2 ,...); // There is no difference between calling and calling other methods. You can use fields to further describe features and separate them with commas, for example, [DllImport ("kernel32", EntryPoint = "GetVersionEx")] the common fields of the DllImportAttribute feature are as follows: 1. CallingConvention indicates the CallingConvention value used to pass method parameters to an unmanaged implementation. CallingConvention. Cdecl: The caller clears the stack. It enables you to call functions with varargs. CallingConvention. StdCall: the called party clears the stack. It is the default convention for calling unmanaged functions from managed code. 2. CharSet controls the name version of the called function and indicates how to mail 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 an unmanaged implementation. This also causes the name of the DLL EntryPoint to be appended with the letter "W ". If this field is set to Ansi, the string is converted to an ANSI string and the name of the DLL EntryPoint is appended with the letter "". Most Win32 APIs use this APPEND "W" or "A" convention. If CharSet is set to Auto, the conversion is platform-related (Unicode on Windows NT and Ansi on Windows 98 ). The default value of CharSet is Ansi. The CharSet field is also used to determine which function version will be imported from the specified DLL. The name matching rules for CharSet. Ansi and CharSet. Unicode are very different. For Ansi, if EntryPoint is set to "MyMethod" and it exists, "MyMethod" is returned ". If the DLL does not contain "MyMethod", but "MyMethodA" exists, "MyMethodA" is returned ". The opposite is true for Unicode. If you set EntryPoint to "MyMethod" and it exists, "MyMethodW" is returned ". If "MyMethodW" does not exist in the DLL but "MyMethod" exists, "MyMethod" is returned ". If Auto is used, the matching rule is related to the platform (Unicode on Windows NT and Ansi on Windows 98 ). If ExactSpelling is set to true, "MyMethod" is returned only when "MyMethod" exists in the DLL ". 3. entrypoint indicates the name or serial number of the dll entry point to be called. If your method name does not want to have the same name as the api function, you must 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 to modify the name of the entry point in the unmanaged dll to correspond to the charset value specified in the charset field. If this parameter is set to true, the parameter is set to dllimportattribute. when the charset field is set to the ansi value of charset, append the letter a to the method name, when dllimportattribute. when the charset field is set to the unicode value of charset, w is appended to the method name. The default value of this field is false. 5. PreserveSig indicates that the signature of the managed method should not be converted to an unmanaged signature that returns HRESULT and may have an additional [out, retval] parameter corresponding to the returned value. 6. SetLastError indicates that the called party will call the Win32 API SetLastError before returning the property method. True indicates that the caller calls SetLastError. The default value is false. GetLastError will be called by the mail collector during runtime and the returned value will be cached to prevent it from being overwritten by other API calls. You can call GetLastWin32Error to retrieve the error code. Ii. Parameter type: 1. You can directly use the corresponding numeric type. (DWORD-> int, WORD-> Int16) 2. String pointer type in API->. net string 3, API handle (dWord)->. net IntPtr 4, the structure in the API->. net Structure or class. Note that in this case, you must first use the StructLayout feature to limit the physical layout of the declared structure or class public language runtime using StructLayoutAttribute to control the data fields of the class or structure in the managed memory, classes or structures need to be arranged in some way. If you want to pass the class to the unmanaged code that requires the specified layout, it is important to explicitly control the class layout. Its constructor uses the LayoutKind value to initialize a new instance of the StructLayoutAttribute class. LayoutKind. Sequential is used to force members to be laid out in the order 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. For example, [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 wM Illiseconds;} below is the OSVERSIONINFO structure for the API, in. net: /*************************************** * osversioninfoa struct * dwOSVersionInfoSize DWORD? * DwMajorVersion DWORD? * DwMinorVersion DWORD? * DwBuildNumber DWORD? * DwPlatformId DWORD? * SzCSDVersion BYTE 128 dup (?) * Osversioninfoa ends ** OSVERSIONINFO equ **************************************** *****///. Net is declared as a class [StructLayout (LayoutKind. sequential)] public class OSVersionInfo {public int OSVersionInfoSize; public int majorVersion; public int minorVersion; public int buildNumber; public int platformId; [financialas (unmanagedtype. byvaltstr, sizeconst = 128)] public String versionString;} // or //. net is declared as the structure [StructLayout (LayoutKind. sequential)] Public struct OSVersionInfo2 {public int OSVersionInfoSize; public int majorVersion; public int minorVersion; public int buildNumber; public int platformId; [financialas (unmanagedtype. byvaltstr, sizeconst = 128)] public String versionString;} in this example, the mashalas feature is used to describe the sending format of fields, methods, or parameters. Use it as the parameter prefix and specify the data type required by the target. For example, the following code uses two parameters as the data type long pointer to seal the string (lpstr) to windows api functions: [exploralas (UnmanagedType. LPStr)] String existingfile; [financialas (UnmanagedType. LPStr)] String newfile; note that when the structure is used as a parameter, a ref modifier must be added before it. Otherwise, an error occurs: the object reference does not include an instance of the specified object. [DllImport ("kernel32", EntryPoint = "GetVersionEx")] public static extern bool GetVersionEx2 (ref OSVersionInfo2 osvi); 3. How to ensure successful calls using a platform hosting objects? If the hosted object is not referenced anywhere after the platform invoke is called, The Garbage Collector may complete the hosted object. This will release the resource and make the handle invalid, resulting in platform invoke call failure. Using HandleRef to wrap the handle ensures that the hosted object is not garbage collected before the platform's invoke call is complete. For example: 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 hosted object, it may be reclaimed by the recycle bin before the platform call is complete. After the file stream handle is packaged with HandleRef, it can be recycled by the garbage station: [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); author -- Author: Bestone -- Release Date: 15:45:59 -- the api function is the cornerstone of building a windws application. For every windows application development tool, the underlying functions provided by api call windows api functions indirectly or directly, at the same time, in order to achieve function expansion, interfaces for calling windowsapi functions are generally provided, that is, they can call dynamic connection libraries. Visual c # can call the api functions of the dynamic link library like other development tools .. Net Framework itself provides such a service that allows governed code to call non-governed functions implemented in the dynamic link library, including windows api functions provided by the operating system. It can locate and call the output function, and organize its parameters (integer, string type, array, and structure) to span the interoperability boundary as needed. The following uses c # as an example to briefly introduce the basic process of calling an api: the Declaration of the function of the dynamic link library must be declared before the function is used. Compared with VB, the C # function declaration is even more complex, the former can be used directly after being pasted using the Api Viewer, while the latter requires additional parameter changes. The function declaration part of the dynamic link library is generally composed of the following two parts: one is the function name or index number, and the other is the file name of the dynamic link library. For example, if you want to call the MessageBox function in User32.DLL, you must specify the function name MessageBoxA or MessageBoxW, and the library name User32.dll, we know that Win32 API generally has two versions for each function involving strings and characters, the ANSI version of single-byte characters and the UNICODE version of double-byte characters. The following is an example of calling an API function: [DllImport ("KERNEL32.DLL", EntryPoint = "MoveFileW", SetLastError = true, CharSet = CharSet. unicode, ExactSpelling = true, CallingConvention = CallingConvention. stdCall)] public static extern bool MoveFile (String src, String dst); The entry point EntryPoint identifies the function at the entry point of the Dynamic Link Library, in a project under the jurisdiction, the original name and number entry point of the target function not only identify a function that spans the boundaries of interoperability. You can also map the entry point to a different name, that is, rename the function. Renaming can bring various conveniences to function calling. by renaming, on the one hand, we don't have to worry about the case sensitivity of the function, and it can also ensure that it is consistent with the existing naming rules, allows functions with different parameter types to coexist. More importantly, it simplifies calls to ANSI and Unicode versions. CharSet is used to identify the Unicode or ANSI version used for function calls. ExactSpelling = false tells the compiler to decide whether to use Unicode or Ansi. For other parameters, see the MSDN online help. in C #, you can declare a Dynamic Linked Library Function in the EntryPoint field by name and serial number. If the function name used in the method definition is the same as the DLL entry point, you do not need to display the declaration function in the EntryPoint field. Otherwise, you must use the following attribute format to indicate a name and serial number. [Dllimport ("dllname", entrypoint = "functionname")] [DllImport ("dllname", EntryPoint = "#123")] It is worth noting that, you must add "#" before the number. The following is an example of replacing the MessageBox name with MsgBox: [C #] using System. runtime. interopServices; public class win32 {[DllImport ("user32.dll", EntryPoint = "MessageBox")] public static extern int MsgBox (int hWnd, String text, String caption, uint type );} many governed Dynamic Linked Library functions expect you to pass a complex parameter type to the function, such as a user-defined structure type member or subject code You must provide additional information to format this type to maintain the original layout and alignment of the parameter. C # provides a structlayoutattribute class through which you can define your own formatting type. In the governed code, the formatting type is a structure or class member described by structlayoutattribute, it ensures the expected layout information of its internal members. There are three layout options: LayoutKind. Automatic: LayoutKind. To improve efficiency, allow the running state to reorder type members. Note: never use this option to call uncontrolled Dynamic Linked Library functions. LayoutKind. Explicit sorts the type members of each domain by FieldOffset attribute. LayoutKind. Sequential sorts the type members in the memory that are not under the jurisdiction of the type definition. The following example shows how to define a vertex and rectangle type in the governed code and pass it as a parameter to the PtInRect function in the User32.dll library. The ungoverned prototype Declaration of the function is as follows: BOOL PtInRect (const RECT * lprc, POINT pt); note that you must pass Rect Structure Parameters by referencing, because the function requires a Rect structure pointer. [C #] using System. runtime. interopServices; [structlayout (layoutkind. sequential)] public struct Point {public int x; public int y;} [structlayout (layoutkind. explicit] public struct Rect {[FieldOffset (0)] public int left; [FieldOffset (4)] public int top; [FieldOffset (8)] public int right; [FieldOffset (12)] public int bottom;} class win32api {[DllImport ("User32.dll")] public static extern Bool P TInRect (ref Rect r, Point p);} Similarly, you can call the GetSystemInfo function to obtain the system information :? Using System. runtime. interopServices; [StructLayout (LayoutKind. sequential)] public struct SYSTEM_INFO {public uint dwOemId; public uint dwPageSize; public uint lpMinimumApplicationAddress; public uint role; public uint dwProcessorType; public uint role; public uint dwProcessorLevel; publ Ic uint dwProcessorRevision;} [DllImport ("kernel32")] static extern void GetSystemInfo (ref SYSTEM_INFO pSI); system_info psi = new system_info (); GetSystemInfo (ref pSI ); transfer of Class Members as long as the class has a fixed class member layout, you can also pass a class member to an uncontrolled Dynamic Linked Library function, the following example describes how to pass a sequential sequence-defined MySystemTime class to the GetSystemTime function of User32.dll. The function uses the C/C ++ call specification as follows: void getsystemtime (systemtime * systemtime ); unlike the value type, the class always transmits parameters through reference. [C #] [StructLayout (Layout Kind. sequential)] public class MySystemTime {public ushort wYear; public ushort wMonth; public ushort hour; public ushort wDay; public ushort wHour; public ushort wMinute; public ushort wSecond; public ushort hour ;} class Win32API {[DllImport ("User32.dll")] public static extern void GetSystemTime (MySystemTime st);} callback function transfer: calls most dynamic link library functions from the governed code, you only need to create a function definition under your jurisdiction and call it. This process is very straightforward. If a Dynamic Linked Library function requires a function pointer as a parameter, you need to take the following steps: first, you must refer to the documentation on this function to determine whether a callback is required for this function; second, you must create a callback function in the governed code. Finally, you can pass the pointer to this function as a parameter to the DLL function ,. callback functions and their implementation: callback functions are often used when tasks need to be executed repeatedly, such as enumeration functions, such as EnumFontFamilies (font enumeration) and EnumPrinters (printer) in Win32 APIs ), enumWindows (window enumeration) function. the following uses window enumeration as an example to describe how to call the EnumWindow function to traverse all windows in the system. The steps are as follows: 1. before calling the function, see the function declaration BOOL EnumWindows (WNDENUMPROC lpEnumFunc, LPARMAM IParam). Obviously, this function requires a callback function address as a parameter. 2. create a managed Callback function. The example declaration is a representative type (delegate), that is, the callback we call. It has two parameters: hwnd and lparam. The first parameter is a window handle, the second parameter is defined by the application. Both parameters are integer. When this callback function returns a non-zero value, it indicates that the execution is successful, and zero indicates that the operation fails. In this example, the value True is always returned for continuous enumeration. 3. Create an object (delegate) and pass it as a parameter to the EnumWindows function. The platform automatically converts the representation to a callback format that can be recognized by the function. [C #] using System; using System. runtime. interopServices; public delegate bool callback (int hwnd, int lparam); public class enumreportapp {[dllimport ("user32")] public static extern int EnumWindows (CallBack x, int y ); public static void main () {CallBack myCallBack = new CallBack (EnumReportApp. report); EnumWindows (myCallBack, 0);} public static bool report (int hwnd, int lparam) {Console. write ("Window The port handle is "); Console. writeLine (hwnd); return true ;}} pointer type parameter transfer: in Windows API function calls, most functions use pointer to pass parameters, for a structure variable pointer, in addition to passing parameters using the above class and structure methods, we can also use arrays to pass parameters. The following function obtains the username BOOL GetUserName (LPTSTR lpBuffer, // username Buffer LPDWORD nSize // address pointer for storing the buffer size) by calling GetUserName; [DllImport ("Advapi32.dll ", entryPoint = "GetComputerName", ExactSpelling = false, SetLastError = true)] static extern bool GetComputerName ([delealas (UnmanagedType. LPArray)] byte [] lpBuffer, [financialas (UnmanagedType. LPArray) Int32 [] nSize); this function accepts two parameters: char * and int *. Because you must allocate a string buffer to accept string pointers, you can use St The ring class replaces this parameter type. Of course, you can declare a byte array to pass the ANSI string. You can also declare a long integer array with only one element, use the array name as the second parameter. The preceding function can be called as follows: byte [] str = new byte [20]; Int32 [] len = new Int32 [1]; len [0] = 20; GetComputerName (str, len); MessageBox. show (System. text. encoding. ASCII. getString (str); the last note is that before using each method, you must add using System in the file header. runtime. interopServices; Recommended NET learning blog |
ASP. NET Technology Application blog
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