Use Visual C # calls Windows API function Beijing Machinery Industry College Research 00 (100085) 林仓 01-9-14 10:34:59
The API function is the cornerstone of the WindWS application, each Windows application development tool, which provides the underlying function that is indirectly or directly calls the Windows API function, and in order to implement functional extensions, it is generally provided to call the WindowsAPI function. Interface, that is, the ability to call dynamic connection libraries. Visual C # and other development tools can also call the dynamic link library API function. The .NET framework itself provides such a service that allows the code-up code to call the Dynamic Link Library, which includes the Windows API function provided by the operating system. It is capable of positioning and calling the output function, organizes each parameter (integer, string type, array, and structure, etc.) as needed, across the interoperability boundary.
The following is a brief introduction to the basic process of calling the API as an example.
Dynamic link library function
Dynamic link library functions must be declared before use, relative to VB, C # function declaration is more commendable, after the former pastes through the API Viewer, can be used directly, and the latter needs to do additional changes in parameters.
Dynamic Link Library Function Declaration Sections are generally composed of two parts of the following, one is a function name or an index number, and the other is the file name of the dynamic link library.
For example, you want to call the Messagebox function in user32.dll, we must specify the name MessageBoxa or MessageBoxwwwa or MessageBoxwww, and library name user32.dll, we know that Win32 API has two versions of each of the functions involving strings and characters. The ANSI version of the single-byte character and the Unicode version of the double-byte character.
Below is an example of calling the API function:
[DLLIMPORT ("kernel32.dll", entrypoint = "movefilew", setLastError = true,
Charset = charset.unicode, exactspelling = true,
Callingconvention = calingconvention.stdcall)]
Public Static Extern Bool MoveFile (String SRC, String Dst);
Where the entry point EntryPoint identification function is in the entry location of the dynamic link library, in an jurisded engineering, the original name and serial number entry point of the target function not only identifies a function of the interoperability boundary. Moreover, you can also map this entry point into a different name, that is, rename the function. Rename can bring all kinds of convenience to the call function, by renaming, on the one hand, we don't have to write to the function of the function, and it can also ensure consistent with the existing naming rules, allowing a function with different parameter types. Coexistence, more importantly, it simplifies the call to ANSI and Unicode versions. Charset is used to identify function calls, which is Unicode or ANSI version. Exactspelling = false will tell the compiler to make the compiler decide to use Unicode or ANSI version. For other parameters, please refer to MSDN online help.
In C #, you can declare a dynamic link library function through the name and serial number in the EntryPoint field, if the function name used in the method definition is the same as the DLL entry point, you don't need to display the declaration function in the EntryPoint domain. 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 serial number.
Below is an example of replacing the MessageBox name with MSGBOX:
[C #]
Using system.Runtime.InteropServices;
PUBLIC CLASS WIN32 {
[DLLIMPORT ("User32.dll", entrypoint = "mess")]]
Public Static Extern Int Msgbox (int hwnd, string text, string caption, uint type);
}
Many jurisdictional link library functions expect you to deliver a complex parameter type to function, such as a user-defined structural type member or a class member defined by the jurisdiction, and you must provide additional information formatting this type. To maintain the original layout and alignment of the parameters.
C # provides a StructLayOutAttribute class, which you can define your own formatted type. In the jurisdiction code, the formatting type is a structure or class member with StructLayOutAttribute, which guarantees its internal member expected layout information. There are three options in the layout:
Layout option
description
Layoutkind.automatic
To improve efficiency allows the run state to reorder type members.
Note: Never use this option to call unlicensed dynamic link library functions.
Layoutkind.explicit
Sort by Fieldoffset property to each domain
Layoutkind.sequential
Sort by a type member that appears in the jurisdiction of the jurisdiction.
Transfer structure member
The following example shows how to define a point and rectangle type in the jurisdiction, and passed as a parameter to the PtinRect function in the user32.dll library,
The unlicensed prototypes of functions are as follows:
Bool PtinRect (Const Rect * LPRC, POINT PT);
Note You must pass the Rect structural parameters by reference, 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 in;
[FieldOffset (4)] public int top;
[FieldOffset (8)] public int right;
[FieldOffset (12)] public int ottom;
}
Class Win32API {
[DLLIMPORT ("User32.dll")]]]]]
Public Static Extern Bool PtinRect (Ref Rect R, POINT P);
}
Similar to you can call the getSystemInfo function to get system information:
Using system.Runtime.InteropServices;
[Structlayout (layoutkind.sequential)]
Public struct system_info {
Public uint dwoemid;
Public uint dwpagesize;
Public uint lpminimumApplicationAddress;
Public uint lpmaximuMapplicationAddress; public uint dwactiveprocessorMask
Public uint dwnumberofprocessors;
Public uint dwprocessortype;
Public uint dwallocationGranularity;
Public uint dwprocessorlevel;
Public uint dwprocessorrevision;
}
[DLLIMPORT ("kernel32")]]
Static Extern void getSystemInfo (Ref System_INFO PSI);
System_info psi = new system_info ();
GetSystemInfo (Ref psi);
Class member
Similarly, as long as the class has a fixed class member layout, you can also pass a class member to an unlicensed dynamic link library function. The following example mainly shows how to pass a Sequential order definition MYSystemTime class to the getSystemTime function of User32.dll The C / C call specification is as follows:
Void getSystemTime (SystemTime * SystemTime);
Unlike type values, classes are always transmitted by reference.
[C #]
[Structlayout (layoutkind.sequential)]
Public class mysystemtime {
Public ushort wyear;
Public ushort wmonth;
Public Ushort WDAYOFWEEK;
Public ushort wday;
Public ushort wheh;
Public ushort wminute;
Public Ushort WSecond;
Public ushort wmilliseconds;
}
Class Win32API {
[DLLIMPORT ("User32.dll")]]]]]
Public Static Extern void getSystemTime (MySystemTime ST);
}
Passing of the callback function:
Calling most dynamic link library functions from the jurisdiction, you only need to create a definition of the jurisdiction, then call it, this process is very straightforward.
If a dynamic link library function requires a function pointer as a parameter, you still need to do the following steps:
First, you must refer to the documentation about this function, determine if this function needs a callback; second, you must create a callback function in the jurisdiction; Finally, you can send a pointer to this function to create a parameter DLL function,.
Tune function and its implementation:
The callback function is often used in the task needs to be repeatedly executed, such as enumeration functions, such as EnumFontFamilies in the Win32 API, Enumprinters, EnumWindows, enumwindows (window enumeration) functions. Enumerate below Example, talk about how to traverse all windows existing in the system by calling the EnumWindow function
Divide a few steps below:
1. Statement of the first reference function before the call
Bool EnumWindows (WndenumProc LpenumFunc, LParmam iParam)
Obviously this function requires a callback function address as a parameter.
2. Create a callback function under the jurisdiction, this example is represented by delegate, which is what we call, it has two parameters hwnd and lparam, the first parameter is a window handle, the second The parameters are defined by the application, both of which are shaped.
When this callback function returns a non-zero value, the indication is successful, and the ridge is hints, this example always returns the TRUE value for continuous enumeration.
3. Finally, create a representative object, and passed it as a parameter to the EnumWindows function, and the platform automatically converts the transformation into a function that can identify the callback format that can be identified. [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 Handle");
Console.WriteLine (hwnd);
Return True;
}
}
Pointer type parameter passed:
When the Windows API function is called, most of the functions use pointer to pass parameters, for a structural variable pointer, in addition to using the above class and structural methods, we can sometimes use array to pass parameters.
Below this function gets username by calling getUsername
Bool getUsername
LPTSTR LPBUFFER, // Username Buffer
LPDWORD NSIZE / / Save the buffer size address pointer
);
[DLLIMPORT ("Advapi32.dll",
EntryPoint = "getcomputername",
EXACTSPELLING = FALSE,
SetLastError = true)]
Static Extern Bool getcomputername
[Marshalas (unmanagedtype.lparray)] Byte [] lpbuffer,
[MARSHALAS (UnmanagedType.lparray)] INT32 [] nsize;
This function accepts two parameters, char * and int *, because you must assign a string buffer to accept string pointers, you can use the String class instead of this parameter type, of course, you can also declare a byte array to pass ansi characters Strings, the same, you can also declare a long integer array with only one element, using an array name as the second parameter. The above functions 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));
Finally, it is necessary to remind that every method must be in the file head before use:
Using system.Runtime.InteropServices;