C:\ProgramFiles\MicrosoftVisual Studio .NET\ FrameworkSDK\Samples\ Technologies\ Interop\PlatformInvoke\ WinAPIs\CS ç®å½ä¸æ大éçè°ç¨ API çä¾åã ä¸ãè°ç¨æ ¼å¼ using System.Runtime.InteropServices; // å¼ç¨æ¤å称空é´ï¼ç®ååé¢ç代ç // ä½¿ç¨ DllImportAttribute ç¹æ§æ¥å¼å ¥ api å½æ°ï¼æ³¨æ声æçæ¯ç©ºæ¹æ³ï¼å³æ¹æ³ä½ä¸ºç©ºã [DllImport("user32.dll")] public static extern ReturnType FunctionName(type arg1,type arg2,...); // è°ç¨æ¶ä¸è°ç¨å ¶ä»æ¹æ³å¹¶æ åºå«  å¯ä»¥ä½¿ç¨å段è¿ä¸æ¥è¯´æç¹æ§ï¼ç¨éå·éå¼ï¼å¦ï¼ [ DllImport( "kernel32", EntryPoint="GetVersionEx" )] DllImportAttribute ç¹æ§çå ¬å ±å段å¦ä¸ï¼ 1ãCallingConventionæ示åéæ管å®ç°ä¼ éæ¹æ³åæ°æ¶æç¨ç CallingConventionå¼ã CallingConvention.Cdecl : è°ç¨æ¹æ¸ çå æ ãå®ä½¿æ¨è½å¤è°ç¨å ·æ varargs çå½æ°ã CallingConvention.StdCall : 被è°ç¨æ¹æ¸ çå æ ãå®æ¯ä»æ管代ç è°ç¨éæ管å½æ°çé»è®¤çº¦å®ã 2ãCharSetæ§å¶è°ç¨å½æ°çå称çæ¬åæ示å¦ä½åæ¹æ³å°é Stringåæ°ã æ¤å段被设置为 CharSet å¼ä¹ä¸ãå¦æ CharSet å段设置为 Unicode ï¼åææå符串åæ°å¨ä¼ éå°éæ管å®ç°ä¹åé½è½¬æ¢æ Unicode å符ãè¿è¿å¯¼è´å DLL EntryPoint çå称ä¸è¿½å åæ¯â W âãå¦ææ¤å段设置为 Ansi ï¼åå符串å°è½¬æ¢æ ANSI å符串ï¼åæ¶å DLL EntryPoint çå称ä¸è¿½å åæ¯â A âã大å¤æ° Win32 API 使ç¨è¿ç§è¿½å â W âæâ A âç约å®ãå¦æ CharSet 设置为 Auto ï¼åè¿ç§è½¬æ¢å°±æ¯ä¸å¹³å°æå ³çï¼å¨ Windows NT ä¸ä¸º Unicode ï¼å¨ Windows 98 ä¸ä¸º Ansi ï¼ã CharSet çé»è®¤å¼ä¸º Ansi ã CharSet å段ä¹ç¨äºç¡®å®å°ä»æå®ç DLL å¯¼å ¥åªä¸ªçæ¬çå½æ°ã CharSet.Ansi å CharSet.Unicode çå称å¹é è§å大ä¸ç¸åãå¯¹äº Ansi æ¥è¯´ï¼å¦æå° EntryPoint 设置为â MyMethod âä¸å®åå¨çè¯ï¼åè¿åâ MyMethod âãå¦æ DLL ä¸æ²¡æâ MyMethod âï¼ä½åå¨â MyMethodA âï¼åè¿åâ MyMethodA âã å¯¹äº Unicode æ¥è¯´åæ£å¥½ç¸åãå¦æå° EntryPoint 设置为â MyMethod âä¸å®åå¨çè¯ï¼åè¿åâ MyMethodW âãå¦æ DLL ä¸ä¸åå¨â MyMethodW âï¼ä½åå¨â MyMethod âï¼åè¿åâ MyMethod âãå¦æ使ç¨çæ¯ Auto ï¼åå¹é è§åä¸å¹³å°æå ³ï¼å¨ Windows NT ä¸ä¸º Unicode ï¼å¨ Windows 98 ä¸ä¸º Ansi ï¼ãå¦æ ExactSpelling 设置为 true ï¼ååªæå½ DLL ä¸åå¨â MyMethod âæ¶æè¿åâ MyMethod âã   3ãEntryPointæ示è¦è°ç¨ç DLL å ¥å£ç¹çå称æåºå·ã å¦æä½ çæ¹æ³åä¸æ³ä¸ api å½æ°ååçè¯ï¼ä¸å®è¦æå®æ¤åæ° , ä¾å¦ï¼ [DllImport("user32.dll",CharSet="CharSet.Auto",EntryPoint="MessageBox")] public static extern int MsgBox(IntPtr hWnd,string txt,string caption, int type);   4ãExactSpellingæ示æ¯å¦åºä¿®æ¹éæ管 DLLä¸çå ¥å£ç¹çå称ï¼ä»¥ä¸ CharSetå段ä¸æå®ç CharSetå¼ç¸å¯¹åºã å¦æ为 true ï¼åå½ DllImportAttribute.CharSet å段设置为 CharSet ç Ansi å¼æ¶ï¼åæ¹æ³å称ä¸è¿½å åæ¯ A ï¼å½ DllImportAttribute.CharSet å段设置为 CharSet ç Unicode å¼æ¶ï¼åæ¹æ³çå称ä¸è¿½å åæ¯ W ãæ¤å段çé»è®¤å¼æ¯ false ã 5 ã PreserveSig æ示æ管æ¹æ³ç¾åä¸åºè½¬æ¢æè¿å HRESULT ã并ä¸å¯è½æä¸ä¸ªå¯¹åºäºè¿åå¼çéå [out, retval] åæ°çéæ管ç¾åã 6 ã SetLastError æ示被è°ç¨æ¹å¨ä»å±æ§åæ¹æ³è¿åä¹åå°è°ç¨ Win32 API SetLastError ã true æ示è°ç¨æ¹å°è°ç¨ SetLastError ï¼é»è®¤ä¸º false ãè¿è¡æ¶å°éææ¶å¨å°è°ç¨ GetLastError 并ç¼åè¿åçå¼ï¼ä»¥é²å ¶è¢«å ¶ä» API è°ç¨éåãç¨æ·å¯éè¿è°ç¨ GetLastWin32Error æ¥æ£ç´¢é误代ç ã  äºãåæ°ç±»åï¼ 1 ãæ°å¼åç´æ¥ç¨å¯¹åºçå°±å¯ãï¼ DWORD -> int , WORD -> Int16 ï¼ 2 ã API ä¸å符串æéç±»å -> .net ä¸ string 3 ã API ä¸å¥æ (dWord) -> .net ä¸ IntPtr 4 ã API ä¸ç»æ -> .net ä¸ç»ææè ç±»ã注æè¿ç§æ åµä¸ï¼è¦å ç¨ StructLayout ç¹æ§éå®å£°æç»ææç±» å ¬å ±è¯è¨è¿è¡åºå©ç¨ StructLayoutAttribute æ§å¶ç±»æç»æçæ°æ®å段å¨æ管å åä¸çç©çå¸å± , å³ç±»æç»æéè¦ææç§æ¹å¼æåãå¦æè¦å°ç±»ä¼ éç»éè¦æå®å¸å±çéæ管代ç ï¼åæ¾å¼æ§å¶ç±»å¸å±æ¯éè¦çãå®çæé å½æ°ä¸ç¨ LayoutKind å¼åå§å StructLayoutAttribute ç±»çæ°å®ä¾ã LayoutKind.Sequential ç¨äºå¼ºå¶å°æåæå ¶åºç°ç顺åºè¿è¡é¡ºåºå¸å±ã LayoutKind.Explicit ç¨äºæ§å¶æ¯ä¸ªæ°æ®æåç精确ä½ç½®ãå©ç¨ Explicit ï¼ æ¯ä¸ªæåå¿ é¡»ä½¿ç¨ FieldOffsetAttribute æ示æ¤å段å¨ç±»åä¸çä½ç½®ãå¦ï¼ [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; } ä¸é¢æ¯é对 API ä¸ OSVERSIONINFO ç»æï¼å¨ .net ä¸å®ä¹å¯¹åºç±»æç»æçä¾åï¼ Â Â //.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;   [ MarshalAs( UnmanagedType.ByValTStr, SizeConst=128 )] public String versionString; }  æ¤ä¾ä¸ç¨å° MashalAs ç¹æ§ï¼å®ç¨äºæè¿°å段ãæ¹æ³æåæ°çå°éå¤çæ ¼å¼ãç¨å®ä½ä¸ºåæ°åç¼å¹¶æå®ç®æ éè¦çæ°æ®ç±»åãä¾å¦ï¼ä»¥ä¸ä»£ç å°ä¸¤ä¸ªåæ°ä½ä¸ºæ°æ®ç±»åé¿æéå°éç» Windows API å½æ°çå符串 (LPStr) ï¼ [MarshalAs(UnmanagedType.LPStr)] String existingfile; [MarshalAs(UnmanagedType.LPStr)] String newfile;  注æç»æä½ä¸ºåæ°æ¶åï¼ä¸è¬åé¢è¦å ä¸ref修饰符ï¼å¦åä¼åºç°éè¯¯ï¼ å¯¹è±¡çå¼ç¨æ²¡ææå®å¯¹è±¡çå®ä¾ã [ DllImport( "kernel32", EntryPoint="GetVersionEx" )] public static extern bool GetVersionEx2( ref OSVersionInfo2 osvi );  ä¸ãå¦ä½ä¿è¯ä½¿ç¨æ管对象çå¹³å°è°ç¨æåï¼ å¦æå¨è°ç¨å¹³å° invoke åçä»»ä½ä½ç½®é½æªå¼ç¨æ管对象ï¼ååå¾åæ¶å¨å¯è½å°å®æ该æ管对象ãè¿å°éæ¾èµæºå¹¶ä½¿å¥ææ æï¼ä»è导è´å¹³å° invoke è°ç¨å¤±è´¥ãç¨ HandleRef å è£ å¥æå¯ä¿è¯å¨å¹³å° invoke è°ç¨å®æåï¼ä¸å¯¹æ管对象è¿è¡åå¾åæ¶ã ä¾å¦ä¸é¢ï¼ 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 å½æ° ç±äº fs æ¯æ管对象ï¼æ以æå¯è½å¨å¹³å°è°ç¨è¿æªå®ææ¶å被åå¾åæ¶ç«åæ¶ãå°æ件æµçå¥æç¨ HandleRef å è£ åï¼å°±è½é¿å 被åå¾ç«åæ¶ : [ 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 );     æå¨èªå·±æè¿çç¼ç¨ä¸æ³¨æå°ä¸ä¸ªè¶å¿ï¼æ£æ¯è¿ä¸ªè¶å¿æå¼åºæ¬æçä¸æ 主é¢ãæè¿ï¼æå¨åºäº Microsoft? .NET Framework çåºç¨ç¨åºä¸å®æäºå¤§éç Win32? Interop ãæ并ä¸æ¯è¦è¯´æçåºç¨ç¨åºå 满äºèªå®ä¹ç interop 代ç ï¼ä½ææ¶æä¼å¨ .NET Framework ç±»åºä¸ç¢°å°ä¸äºæ¬¡è¦ä½åç¹çµ®ãä¸å åçå 容ï¼éè¿è°ç¨è¯¥ Windows? API ï¼å¯ä»¥å¿«éåå°è¿æ ·ç麻ç¦ã  å æ¤æè®¤ä¸ºï¼ .NET Framework 1.0 æ 1.1 çç±»åºä¸åå¨ä»»ä½ Windows æ没æçåè½éå¶é½ä¸è¶³ä¸ºæªãæ¯ç«ï¼ 32 ä½ç Windows ï¼ä¸ç®¡ä½ç§çæ¬ï¼æ¯ä¸ä¸ªæççæä½ç³»ç»ï¼ä¸ºå¹¿å¤§å®¢æ·æå¡äºåå¤å¹´ãç¸æ¯ä¹ä¸ï¼ .NET Framework å´æ¯ä¸ä¸ªæ°äºç©ã  éçè¶æ¥è¶å¤çå¼å人åå°ç产åºç¨ç¨åºè½¬å°æ管代ç ï¼å¼å人åæ´é¢ç¹å°ç 究åºå±æä½ç³»ç»ä»¥å¾æ¾åºä¸äºå ³é®åè½æ¾å¾å¾èªç¶ â è³å°ç®åæ¯å¦æ¤ã  å¼å¾åºå¹¸çæ¯ï¼å ¬å ±è¯è¨è¿è¡åº (CLR) ç interop åè½ï¼ç§°ä¸ºå¹³å°è°ç¨ (P/Invoke) ï¼é常å®åãå¨æ¬ä¸æ ä¸ï¼æå°éç¹ä»ç»å¦ä½å®é ä½¿ç¨ P/Invoke æ¥è°ç¨ Windows API å½æ°ãå½æ CLR ç COM Interop åè½æ¶ï¼ P/Invoke å½ä½åè¯ä½¿ç¨ï¼å½æ该åè½ç使ç¨æ¶ï¼åå°å ¶å½ä½å¨è¯ä½¿ç¨ãæ并ä¸æç®ç´æ¥ä»ç» COM Interop ï¼å 为å®æ¯ P/Invoke å ·ææ´å¥½çå¯è®¿é®æ§ï¼å´æ´å å¤æï¼è¿æç¹èªç¸çç¾ï¼è¿ä½¿å¾å° COM Interop ä½ä¸ºä¸æ 主é¢æ¥è®¨è®ºä¸å¤ªç®ææ¼è¦ã Â èµ°è¿ P/Invoke  é¦å ä»èå¯ä¸ä¸ªç®åç P/Invoke 示ä¾å¼å§ã让æ们çä¸çå¦ä½è°ç¨ Win32 MessageBeep å½æ°ï¼å®çéæ管声æå¦ä»¥ä¸ä»£ç æç¤ºï¼ Â BOOL MessageBeep(  UINT uType  // beep type );  为äºè°ç¨ MessageBeep ï¼æ¨éè¦å¨ C# ä¸å°ä»¥ä¸ä»£ç æ·»å å°ä¸ä¸ªç±»æç»æå®ä¹ä¸ï¼  [DllImport("User32.dll")] static extern Boolean MessageBeep(UInt32 beepType);  令人æ讶çæ¯ï¼åªéè¦è¿æ®µä»£ç å°±å¯ä»¥ä½¿æ管代ç è°ç¨éæ管ç MessageBeep API ãå®ä¸æ¯ä¸ä¸ªæ¹æ³è°ç¨ï¼èæ¯ä¸ä¸ªå¤é¨æ¹æ³å®ä¹ãï¼å¦å¤ï¼å®æ¥è¿äºä¸ä¸ªæ¥èª C è C# å 许çç´æ¥ç«¯å£ï¼å æ¤ä»¥å®ä¸ºèµ·ç¹æ¥ä»ç»ä¸äºæ¦å¿µæ¯æ帮å©çãï¼æ¥èªæ管代ç çå¯è½è°ç¨å¦ä¸æç¤ºï¼ Â MessageBeep(0);  请注æï¼ç°å¨ MessageBeep æ¹æ³è¢«å£°æ为 static ãè¿æ¯ P/Invoke æ¹æ³æè¦æ±çï¼å 为å¨è¯¥ Windows API ä¸æ²¡æä¸è´çå®ä¾æ¦å¿µãæ¥ä¸æ¥ï¼è¿è¦æ³¨æ该æ¹æ³è¢«æ 记为 extern ãè¿æ¯æ示ç¼è¯å¨è¯¥æ¹æ³æ¯éè¿ä¸ä¸ªä» DLL 导åºçå½æ°å®ç°çï¼å æ¤ä¸éè¦æä¾æ¹æ³ä½ã  说å°ç¼ºå°æ¹æ³ä½ï¼æ¨æ¯å¦æ³¨æå° MessageBeep 声æ并没æå å«ä¸ä¸ªæ¹æ³ä½ï¼ä¸å¤§å¤æ°ç®æ³ç±ä¸é´è¯è¨ (IL) æ令ç»æçæ管æ¹æ³ä¸åï¼ P/Invoke æ¹æ³åªæ¯å æ°æ®ï¼å®æ¶ (JIT) ç¼è¯å¨å¨è¿è¡æ¶éè¿å®å°æ管代ç ä¸éæ管ç DLL å½æ°è¿æ¥èµ·æ¥ãæ§è¡è¿ç§å°éæ管ä¸ççè¿æ¥æéçä¸ä¸ªéè¦ä¿¡æ¯å°±æ¯å¯¼åºéæ管æ¹æ³ç DLL çå称ãè¿ä¸ä¿¡æ¯æ¯ç± MessageBeep æ¹æ³å£°æä¹åç DllImport èªå®ä¹å±æ§æä¾çãå¨æ¬ä¾ä¸ï¼å¯ä»¥çå°ï¼ MessageBeep éæ管 API æ¯ç± Windows ä¸ç User32.dll 导åºçã  å°ç°å¨ä¸ºæ¢ï¼å ³äºè°ç¨ MessageBeep å°±å©ä¸¤ä¸ªè¯é¢æ²¡æä»ç»ï¼è¯·å顾ä¸ä¸ï¼è°ç¨ç代ç ä¸ä»¥ä¸æ示代ç ç段é常ç¸ä¼¼ï¼  [DllImport("User32.dll")] static extern Boolean MessageBeep(UInt32 beepType);  æåè¿ä¸¤ä¸ªè¯é¢æ¯ä¸æ°æ®å°éå¤ç (data marshaling) åä»æ管代ç å°éæ管å½æ°çå®é æ¹æ³è°ç¨æå ³çè¯é¢ãè°ç¨éæ管 MessageBeep å½æ°å¯ä»¥ç±æ¾å°ä½ç¨åå ç extern MessageBeep 声æçä»»ä½æ管代ç æ§è¡ã该è°ç¨ç±»ä¼¼äºä»»ä½å ¶ä»å¯¹éææ¹æ³çè°ç¨ãå®ä¸å ¶ä»ä»»ä½æ管æ¹æ³è°ç¨çå ±åä¹å¤å¨äºå¸¦æ¥äºæ°æ®å°éå¤ççéè¦ã  C# çè§åä¹ä¸æ¯å®çè°ç¨è¯æ³åªè½è®¿é® CLR æ°æ®ç±»åï¼ä¾å¦ System.UInt32 å System.Boolean ã C# æ¾ç¶ä¸è¯å« Windows API ä¸ä½¿ç¨çåºäº C çæ°æ®ç±»åï¼ä¾å¦ UINT å BOOL ï¼ï¼è¿äºç±»ååªæ¯ C è¯è¨ç±»åçç±»åå®ä¹èå·²ãæä»¥å½ Windows API å½æ° MessageBeep æ以ä¸æ¹å¼ç¼åæ¶ Â BOOL MessageBeep( UINT uType )  å¤é¨æ¹æ³å°±å¿ é¡»ä½¿ç¨ CLR ç±»åæ¥å®ä¹ï¼å¦æ¨å¨åé¢ç代ç ç段ä¸æçå°çãéè¦ä½¿ç¨ä¸åºç¡ API å½æ°ç±»åä¸åä½ä¸ä¹å ¼å®¹ç CLR ç±»åæ¯ P/Invoke è¾é¾ä½¿ç¨çä¸ä¸ªæ¹é¢ãå æ¤ï¼å¨æ¬ä¸æ çåé¢æå°ç¨å®æ´çç« èæ¥ä»ç»æ°æ®å°éå¤çã Â æ ·å¼ Â å¨ C# ä¸å¯¹ Windows API è¿è¡ P/Invoke è°ç¨æ¯å¾ç®åçãä½å¦æç±»åºæç»ä½¿æ¨çåºç¨ç¨åºååºå声ï¼åºè¯¥æ³æ¹è®¾æ³è°ç¨ Windows 使å®è¿è¡è¿é¡¹å·¥ä½ï¼æ¯åï¼ Â æ¯çãä½æ¯ä¸éæ©çæ¹æ³æå ³ï¼èä¸å ³ç³»ç大ï¼é常ï¼å¦æç±»åºæä¾æç§éå¾æ¥å®ç°æ¨çæå¾ï¼åæå¥½ä½¿ç¨ API èä¸è¦ç´æ¥è°ç¨éæ管代ç ï¼å 为 CLR ç±»åå Win32 ä¹é´å¨æ ·å¼ä¸æå¾å¤§çä¸åãæå¯ä»¥å°å ³äºè¿ä¸ªé®é¢ç建议å½ç»ä¸ºä¸å¥è¯ãå½æ¨è¿è¡ P/Invoke æ¶ï¼ä¸è¦ä½¿åºç¨ç¨åºé»è¾ç´æ¥å±äºä»»ä½å¤é¨æ¹æ³æå ¶ä¸çæ件ã å¦ææ¨éµå¾ªè¿ä¸ªå°è§åï¼ä»é¿è¿çç»å¸¸ä¼çå»è®¸å¤ç麻ç¦ã Â å¾ 1 ä¸ç代ç æ¾ç¤ºäºææ讨论ç MessageBeep å¤é¨æ¹æ³çæå°éå 代ç ãå¾ 1 ä¸å¹¶æ²¡æä»»ä½æ¾èçååï¼èåªæ¯å¯¹æ å è£ çå¤é¨æ¹æ³è¿è¡ä¸äºæ®éçæ¹è¿ï¼è¿å¯ä»¥ä½¿å·¥ä½æ´å è½»æ¾ä¸äºãä»é¡¶é¨å¼å§ï¼æ¨ä¼æ³¨æå°ä¸ä¸ªå为 Sound çå®æ´ç±»åï¼å®ä¸ç¨äº MessageBeep ãå¦ææéè¦ä½¿ç¨ Windows API å½æ° PlaySound æ¥æ·»å 对ææ¾æ³¢å½¢çæ¯æï¼åå¯ä»¥éç¨ Sound ç±»åãç¶èï¼æä¸ä¼å å ¬å¼åä¸ªå ¬å ±éææ¹æ³çç±»åèçæ°ãæ¯ç«è¿åªæ¯åºç¨ç¨åºä»£ç èå·²ãè¿åºè¯¥æ³¨æå°ï¼ Sound æ¯å¯å°çï¼å¹¶å®ä¹äºä¸ä¸ªç©ºçç§ææé å½æ°ãè¿äºåªæ¯ä¸äºç»èï¼ç®çæ¯ä½¿ç¨æ·ä¸ä¼é误å°ä» Sound æ´¾çç±»æè å建å®çå®ä¾ã Â å¾ 1 ä¸ç代ç çä¸ä¸ä¸ªç¹å¾æ¯ï¼ P/Invoke åºç°ä½ç½®çå®é å¤é¨æ¹æ³æ¯ Sound çç§ææ¹æ³ãè¿ä¸ªæ¹æ³åªæ¯ç±å ¬å ± MessageBeep æ¹æ³é´æ¥å ¬å¼ï¼åè æ¥å BeepTypes ç±»åçåæ°ãè¿ä¸ªé´æ¥çé¢å¤å±æ¯ä¸ä¸ªå¾å ³é®çç»èï¼å®æä¾äºä»¥ä¸å¥½å¤ãé¦å ï¼åºè¯¥å¨ç±»åºä¸å¼å ¥ä¸ä¸ªæªæ¥ç beep æ管æ¹æ³ï¼å¯ä»¥éå¤å°éè¿å ¬å ± MessageBeep æ¹æ³æ¥ä½¿ç¨æ管 API ï¼èä¸å¿ æ´æ¹åºç¨ç¨åºä¸çå ¶ä½ä»£ç ã  该å è£ æ¹æ³ç第äºä¸ªå¥½å¤æ¯ï¼å½æ¨è¿è¡ P/Invoke è°ç¨æ¶ï¼æ¨æ¾å¼äºå å访é®å²çªåå ¶ä»ä½çº§ç ´åçæå©ï¼è¿é常æ¯ç± CLR æä¾çãç¼å²æ¹æ³å¯ä»¥ä¿æ¤æ¨çåºç¨ç¨åºçå ¶ä½é¨åå å访é®å²çªå类似é®é¢çå½±åï¼å³ä½¿å®ä¸åä»»ä½äºèåªæ¯ä¼ éåæ°ï¼ã该ç¼å²æ¹æ³å°ç± P/Invoke è°ç¨å¼å ¥çä»»ä½æ½å¨çé误æ¬å°åã  å°ç§æå¤é¨æ¹æ³éèå¨å ¬å ±å è£ åé¢ç第ä¸åæ¶ä¹æ¯æåçä¸ä¸ªå¥½å¤æ¯ï¼æä¾äºå该æ¹æ³æ·»å ä¸äºæå°ç CLR æ ·å¼çæºä¼ãä¾å¦ï¼å¨å¾ 1 ä¸ï¼æå° Windows API å½æ°è¿åç Boolean 失败转æ¢ææ´å CLR çå¼å¸¸ãæè¿å®ä¹äºä¸ä¸ªå为 BeepTypes çæ举类åï¼å®çæå对åºäºå该 Windows API ä¸èµ·ä½¿ç¨çå®ä¹å¼ãç±äº C# ä¸æ¯æå®ä¹ï¼å æ¤å¯ä»¥ä½¿ç¨æ管æ举类åæ¥é¿å å¹»æ°åæ´ä¸ªåºç¨ç¨åºä»£ç æ©æ£ã  å è£ æ¹æ³çæåä¸ä¸ªå¥½å¤å¯¹äºç®åç Windows API å½æ°ï¼å¦ MessageBeep ï¼è¯ç¶æ¯å¾®ä¸è¶³éçãä½æ¯å½æ¨å¼å§è°ç¨æ´å¤æçéæ管å½æ°æ¶ï¼æ¨ä¼åç°ï¼æå¨å° Windows API æ ·å¼è½¬æ¢æ对 CLR æ´å å好çæ¹æ³æ带æ¥ç好å¤ä¼è¶æ¥è¶å¤ãè¶æ¯æç®å¨æ´ä¸ªåºç¨ç¨åºä¸éç¨ interop åè½ï¼è¶æ¯åºè¯¥è®¤çå°èèå è£ ç设计ãåæ¶æ认为ï¼å¨éé¢å对象çéæå è£ æ¹æ³ä¸ä½¿ç¨å¯¹ CLR å好çåæ°ä¹å¹¶éä¸å¯ä»¥ã  DLL Import å±æ§  ç°å¨æ¯æ´æ·±å ¥å°è¿è¡æ¢è®¨çæ¶åäºãå¨å¯¹æ管代ç è¿è¡ P/Invoke è°ç¨æ¶ï¼ DllImportAttribute ç±»åæ®æ¼çéè¦çè§è²ã DllImportAttribute ç主è¦ä½ç¨æ¯ç» CLR æ示åªä¸ª DLL 导åºæ¨æ³è¦è°ç¨çå½æ°ãç¸å ³ DLL çå称被ä½ä¸ºä¸ä¸ªæé å½æ°åæ°ä¼ éç» DllImportAttribute ã  å¦ææ¨æ æ³è¯å®åªä¸ª DLL å®ä¹äºæ¨è¦ä½¿ç¨ç Windows API å½æ°ï¼ Platform SDK ææ¡£å°ä¸ºæ¨æä¾æ好ç帮å©èµæºãå¨ Windows API å½æ°ä¸»é¢æå临è¿ç»å°¾çä½ç½®ï¼ SDK ææ¡£æå®äº C åºç¨ç¨åºè¦ä½¿ç¨è¯¥å½æ°å¿ é¡»é¾æ¥ç .lib æ件ãå¨å ä¹ææçæ åµä¸ï¼è¯¥ .lib æä»¶å ·æä¸å®ä¹è¯¥å½æ°çç³»ç» DLL æ件ç¸åçå称ãä¾å¦ï¼å¦æ该å½æ°éè¦ C åºç¨ç¨åºé¾æ¥å° Kernel32.lib ï¼å该å½æ°å°±å®ä¹å¨ Kernel32.dll ä¸ãæ¨å¯ä»¥å¨ MessageBeep ä¸æ¾å°æå ³ MessageBeep ç Platform SDK æ档主é¢ãå¨è¯¥ä¸»é¢ç»å°¾å¤ï¼æ¨ä¼æ³¨æå°å®æåºåºæä»¶æ¯ User32.lib ï¼è¿è¡¨æ MessageBeep æ¯ä» User32.dll ä¸å¯¼åºçã  å¯éç DllImportAttribute å±æ§  é¤äºæåºå®¿ä¸» DLL å¤ï¼ DllImportAttribute è¿å å«äºä¸äºå¯éå±æ§ï¼å ¶ä¸å个ç¹å«æè¶£ï¼ EntryPoint ã CharSet ã SetLastError å CallingConvention ã  EntryPoint å¨ä¸å¸æå¤é¨æ管æ¹æ³å ·æä¸ DLL 导åºç¸åçå称çæ åµä¸ï¼å¯ä»¥è®¾ç½®è¯¥å±æ§æ¥æ示导åºç DLL å½æ°çå ¥å£ç¹å称ãå½æ¨å®ä¹ä¸¤ä¸ªè°ç¨ç¸åéæ管å½æ°çå¤é¨æ¹æ³æ¶ï¼è¿ç¹å«æç¨ãå¦å¤ï¼å¨ Windows ä¸è¿å¯ä»¥éè¿å®ä»¬çåºå·å¼ç»å®å°å¯¼åºç DLL å½æ°ãå¦ææ¨éè¦è¿æ ·åï¼å诸å¦â #1âæâ#129âç EntryPoint å¼æ示 DLL ä¸éæ管å½æ°çåºå·å¼èä¸æ¯å½æ°åã  CharSet 对äºå符éï¼å¹¶éææçæ¬ç Windows é½æ¯åæ ·å建çã Windows 9x ç³»å产å缺å°éè¦ç Unicode æ¯æï¼è Windows NT å Windows CE ç³»ååä¸å¼å§å°±ä½¿ç¨ Unicode ãå¨è¿äºæä½ç³»ç»ä¸è¿è¡ç CLR å° Unicode ç¨äº String å Char æ°æ®çå é¨è¡¨ç¤ºãä½ä¹ä¸å¿ æ å¿ â å½è°ç¨ Windows 9x API å½æ°æ¶ï¼ CLR ä¼èªå¨è¿è¡å¿ è¦ç转æ¢ï¼å°å ¶ä» Unicode 转æ¢ä¸º ANSI ã  å¦æ DLL å½æ°ä¸ä»¥ä»»ä½æ¹å¼å¤çææ¬ï¼åå¯ä»¥å¿½ç¥ DllImportAttribute ç CharSet å±æ§ãç¶èï¼å½ Char æ String æ°æ®æ¯çå¼çä¸é¨åæ¶ï¼åºè¯¥å° CharSet å±æ§è®¾ç½®ä¸º CharSet.Auto ãè¿æ ·å¯ä»¥ä½¿ CLR æ ¹æ®å®¿ä¸» OS 使ç¨éå½çå符éãå¦æ没ææ¾å¼å°è®¾ç½® CharSet å±æ§ï¼åå ¶é»è®¤å¼ä¸º CharSet.Ansi ãè¿ä¸ªé»è®¤å¼æ¯æ缺ç¹çï¼å 为对äºå¨ Windows 2000 ã Windows XP å Windows NT? ä¸è¿è¡ç interop è°ç¨ï¼å®ä¼æ¶æå°å½±åææ¬åæ°å°éå¤ççæ§è½ã  åºè¯¥æ¾å¼å°éæ© CharSet.Ansi æ CharSet.Unicode ç CharSet å¼èä¸æ¯ä½¿ç¨ CharSet.Auto çå¯ä¸æ åµæ¯ï¼æ¨æ¾å¼å°æå®äºä¸ä¸ªå¯¼åºå½æ°ï¼è该å½æ°ç¹å®äºè¿ä¸¤ç§ Win32 OS ä¸çæä¸ç§ã ReadDirectoryChangesW API å½æ°å°±æ¯è¿æ ·çä¸ä¸ªä¾åï¼å®åªåå¨äºåºäº Windows NT çæä½ç³»ç»ä¸ï¼å¹¶ä¸åªæ¯æ Unicode ï¼å¨è¿ç§æ åµä¸ï¼æ¨åºè¯¥æ¾å¼å°ä½¿ç¨ CharSet.Unicode ã  ææ¶ï¼ Windows API æ¯å¦æå符éå ³ç³»å¹¶ä¸ææ¾ãä¸ç§å³ä¸ä¼æéç确认æ¹æ³æ¯å¨ Platform SDK ä¸æ£æ¥è¯¥å½æ°ç C è¯è¨å¤´æ件ãï¼å¦ææ¨æ æ³è¯å®è¦çåªä¸ªå¤´æ件ï¼åå¯ä»¥æ¥ç Platform SDK ææ¡£ä¸ååºçæ¯ä¸ª API å½æ°ç头æ件ãï¼å¦ææ¨åç°è¯¥ API å½æ°ç¡®å®å®ä¹ä¸ºä¸ä¸ªæ å°å°ä»¥ A æ W ç»å°¾çå½æ°åçå®ï¼åå符éä¸æ¨å°è¯è°ç¨çå½æ°æå ³ç³»ã Windows API å½æ°çä¸ä¸ªä¾åæ¯å¨ WinUser.h ä¸å£°æç GetMessage API ï¼æ¨ä¹è®¸ä¼æ讶å°åç°å®æ A å W 两ç§çæ¬ã  SetLastError é误å¤çé常éè¦ï¼ä½å¨ç¼ç¨æ¶ç»å¸¸è¢«éå¿ãå½æ¨è¿è¡ P/Invoke è°ç¨æ¶ï¼ä¹ä¼é¢ä¸´å ¶ä»çææ â å¤çæ管代ç ä¸ Windows API é误å¤çåå¼å¸¸ä¹é´çåºå«ãæå¯ä»¥ç»æ¨ä¸ç¹å»ºè®®ã  å¦ææ¨æ£å¨ä½¿ç¨ P/Invoke è°ç¨ Windows API å½æ°ï¼è对äºè¯¥å½æ°ï¼æ¨ä½¿ç¨ GetLastError æ¥æ¥æ¾æ©å±çé误信æ¯ï¼ååºè¯¥å¨å¤é¨æ¹æ³ç DllImportAttribute ä¸å° SetLastError å±æ§è®¾ç½®ä¸º true ãè¿éç¨äºå¤§å¤æ°å¤é¨æ¹æ³ã  è¿ä¼å¯¼è´ CLR å¨æ¯æ¬¡è°ç¨å¤é¨æ¹æ³ä¹åç¼åç± API å½æ°è®¾ç½®çé误ãç¶åï¼å¨å è£ æ¹æ³ä¸ï¼å¯ä»¥éè¿è°ç¨ç±»åºç System.Runtime.InteropServices.Marshal ç±»åä¸å®ä¹ç Marshal.GetLastWin32Error æ¹æ³æ¥è·åç¼åçé误å¼ãæç建议æ¯æ£æ¥è¿äºæææ¥èª API å½æ°çé误å¼ï¼å¹¶ä¸ºè¿äºå¼å¼åä¸ä¸ªå¯æç¥çå¼å¸¸ã对äºå ¶ä»ææ失败æ åµï¼å æ¬æ ¹æ¬å°±æ²¡ææå°ç失败æ åµï¼ï¼åå¼åå¨ System.ComponentModel å½å空é´ä¸å®ä¹ç Win32Exception ï¼å¹¶å° Marshal.GetLastWin32Error è¿åçå¼ä¼ éç»å®ãå¦ææ¨å头çä¸ä¸å¾ 1 ä¸ç代ç ï¼æ¨ä¼çå°æå¨ extern MessageBeep æ¹æ³çå ¬å ±å è£ ä¸å°±éç¨äºè¿ç§æ¹æ³ã  CallingConvention æå°å¨æ¤ä»ç»çæåä¹å¯è½æ¯æä¸éè¦çä¸ä¸ª DllImportAttribute å±æ§æ¯ CallingConvention ãéè¿æ¤å±æ§ï¼å¯ä»¥ç» CLR æ示åºè¯¥å°åªç§å½æ°è°ç¨çº¦å®ç¨äºå æ ä¸çåæ°ã CallingConvention.Winapi çé»è®¤å¼æ¯æ好çéæ©ï¼å®å¨å¤§å¤æ°æ åµä¸é½å¯è¡ãç¶èï¼å¦æ该è°ç¨ä¸èµ·ä½ç¨ï¼åå¯ä»¥æ£æ¥ Platform SDK ä¸ç声æ头æ件ï¼ççæ¨è°ç¨ç API å½æ°æ¯å¦æ¯ä¸ä¸ªä¸ç¬¦åè°ç¨çº¦å®æ åçå¼å¸¸ API ã  é常ï¼æ¬æºå½æ°ï¼ä¾å¦ Windows API å½æ°æ C- è¿è¡æ¶ DLL å½æ°ï¼çè°ç¨çº¦å®æè¿°äºå¦ä½å°åæ°æ¨å ¥çº¿ç¨å æ æä»çº¿ç¨å æ ä¸æ¸ é¤ã大å¤æ° Windows API å½æ°é½æ¯é¦å å°å½æ°çæåä¸ä¸ªåæ°æ¨å ¥å æ ï¼ç¶åç±è¢«è°ç¨çå½æ°è´è´£æ¸ ç该å æ ãç¸åï¼è®¸å¤ C- è¿è¡æ¶ DLL å½æ°é½è¢«å®ä¹ä¸ºæç §æ¹æ³åæ°å¨æ¹æ³ç¾åä¸åºç°ç顺åºå°å ¶æ¨å ¥å æ ï¼å°å æ æ¸ çå·¥ä½äº¤ç»è°ç¨è ã  幸è¿çæ¯ï¼è¦è®© P/Invoke è°ç¨å·¥ä½åªéè¦è®©å¤å´è®¾å¤ç解è°ç¨çº¦å®å³å¯ãé常ï¼ä»é»è®¤å¼ CallingConvention.Winapi å¼å§æ¯æ好çéæ©ãç¶åï¼å¨ C è¿è¡æ¶ DLL å½æ°åå°æ°å½æ°ä¸ï¼å¯è½éè¦å°çº¦å®æ´æ¹ä¸º CallingConvention.Cdecl ã  æ°æ®å°éå¤ç  æ°æ®å°éå¤çæ¯ P/Invoke å ·ææææ§çæ¹é¢ãå½å¨æ管åéæ管代ç ä¹é´ä¼ éæ°æ®æ¶ï¼ CLR éµå¾ªè®¸å¤è§åï¼å¾å°æå¼å人åä¼ç»å¸¸éå°å®ä»¬ç´è³å¯å°è¿äºè§åè®°ä½ãé¤éæ¨æ¯ä¸åç±»åºå¼å人åï¼å¦åå¨é常æ åµä¸æ²¡æå¿ è¦ææ¡å ¶ç»èã为äºæææå°å¨ CLR ä¸ä½¿ç¨ P/Invoke ï¼å³ä½¿åªå¶å°éè¦ interop çåºç¨ç¨åºå¼å人åä»ç¶åºè¯¥ç解æ°æ®å°éå¤ççä¸äºåºç¡ç¥è¯ã  å¨æ¬æä¸æ çå©ä½é¨åä¸ï¼æå°è®¨è®ºç®åæ°ååå符串æ°æ®çæ°æ®å°éå¤çãæå°ä»æåºæ¬çæ°åæ°æ®å°éå¤çå¼å§ï¼ç¶åä»ç»ç®åçæéå°éå¤çåå符串å°éå¤çã  å°éæ°ååé»è¾æ é  Windows OS 大é¨åæ¯ç¨ C ç¼åçãå æ¤ï¼ Windows API æç¨å°çæ°æ®ç±»åè¦ä¹æ¯ C ç±»åï¼è¦ä¹æ¯éè¿ç±»åå®ä¹æå®å®ä¹éæ°æ è®°ç C ç±»åã让æ们çç没ææéçæ°æ®å°éå¤çãç®åèµ·è§ï¼é¦å éç¹è®¨è®ºçæ¯æ°ååå¸å°å¼ã  å½éè¿å¼å Windows API å½æ°ä¼ éåæ°æ¶ï¼éè¦ç¥é以ä¸é®é¢ççæ¡ï¼  ? æ°æ®ä»æ ¹æ¬ä¸è®²æ¯æ´åçè¿æ¯æµ®ç¹åçï¼ Â ? å¦ææ°æ®æ¯æ´åçï¼åå®æ¯æ符å·çè¿æ¯æ 符å·çï¼ Â ? å¦ææ°æ®æ¯æ´åçï¼åå®çä½æ°æ¯å¤å°ï¼  ? å¦ææ°æ®æ¯æµ®ç¹åçï¼åå®æ¯å精度çè¿æ¯å精度çï¼ Â Â ææ¶çæ¡å¾ææ¾ï¼ä½ææ¶å´ä¸ææ¾ã Windows API 以åç§æ¹å¼éæ°å®ä¹äºåºæ¬ç C æ°æ®ç±»åãå¾ 2 ååºäº C å Win32 çä¸äºå ¬å ±æ°æ®ç±»ååå ¶è§èï¼ä»¥åä¸ä¸ªå ·æå¹é è§èçå ¬å ±è¯è¨è¿è¡åºç±»åã  é常ï¼åªè¦æ¨éæ©ä¸ä¸ªå ¶è§èä¸è¯¥åæ°ç Win32 ç±»åç¸å¹é ç CLR ç±»åï¼æ¨ç代ç å°±è½å¤æ£å¸¸å·¥ä½ãä¸è¿ä¹æä¸äºç¹ä¾ãä¾å¦ï¼å¨ Windows API ä¸å®ä¹ç BOOL ç±»åæ¯ä¸ä¸ªæ符å·ç 32 ä½æ´åãç¶èï¼ BOOL ç¨äºæ示 Boolean å¼ true æ false ãè½ç¶æ¨ä¸ç¨å° BOOL åæ°ä½ä¸º System.Int32 å¼å°éï¼ä½æ¯å¦æä½¿ç¨ System.Boolean ç±»åï¼å°±ä¼è·å¾æ´åéçæ å°ãå符类åçæ å°ç±»ä¼¼äº BOOL ï¼å 为æä¸ä¸ªç¹å®ç CLR ç±»å (System.Char) æåºå符çå«ä¹ã  å¨äºè§£è¿äºä¿¡æ¯ä¹åï¼éæ¥ä»ç»ç¤ºä¾å¯è½æ¯æ帮å©çãä¾ç¶éç¨ beep 主é¢ä½ä¸ºä¾åï¼è®©æ们æ¥è¯ä¸ä¸ Kernel32.dll ä½çº§ Beep ï¼å®ä¼éè¿è®¡ç®æºçæ¬å£°å¨åçå声ãè¿ä¸ªæ¹æ³ç Platform SDK ææ¡£å¯ä»¥å¨ Beep ä¸æ¾å°ãæ¬æº API æ以ä¸æ¹å¼è¿è¡è®°å½ï¼  BOOL Beep(  DWORD dwFreq,     // Frequency  DWORD dwDuration  // Duration in milliseconds );  å¨åæ°å°éå¤çæ¹é¢ï¼æ¨çå·¥ä½æ¯äºè§£ä»ä¹ CLR æ°æ®ç±»åä¸ Beep API å½æ°æ使ç¨ç DWORD å BOOL æ°æ®ç±»åç¸å ¼å®¹ãå顾ä¸ä¸å¾ 2 ä¸çå¾è¡¨ï¼æ¨å°çå° DWORD æ¯ä¸ä¸ª 32 ä½çæ 符å·æ´æ°å¼ï¼å¦å CLR ç±»å System.UInt32 ãè¿æå³çæ¨å¯ä»¥ä½¿ç¨ UInt32 å¼ä½ä¸ºéå¾ Beep ç两个åæ°ã BOOL è¿åå¼æ¯ä¸ä¸ªé常æ趣çæ åµï¼å 为该å¾è¡¨åè¯æ们ï¼å¨ Win32 ä¸ï¼ BOOL æ¯ä¸ä¸ª 32 ä½çæ符å·æ´æ°ãå æ¤ï¼æ¨å¯ä»¥ä½¿ç¨ System.Int32 å¼ä½ä¸ºæ¥èª Beep çè¿åå¼ãç¶èï¼ CLR ä¹å®ä¹äº System.Boolean ç±»åä½ä¸º Boolean å¼çè¯ä¹ï¼æ以åºè¯¥ä½¿ç¨å®æ¥æ¿ä»£ã CLR é»è®¤å° System.Boolean å¼å°é为 32 ä½çæ符å·æ´æ°ãæ¤å¤ææ¾ç¤ºçå¤é¨æ¹æ³å®ä¹æ¯ç¨äº Beep çç»æ P/Invoke æ¹æ³ï¼  [DllImport("Kernel32.dll", SetLastError=true)] static extern Boolean Beep(   UInt32 frequency, UInt32 duration);  æéåæ° Â è®¸å¤ Windows API å½æ°å°æéä½ä¸ºå®ä»¬çä¸ä¸ªæå¤ä¸ªåæ°ãæéå¢å äºå°éæ°æ®çå¤ææ§ï¼å 为å®ä»¬å¢å äºä¸ä¸ªé´æ¥å±ãå¦æ没ææéï¼æ¨å¯ä»¥éè¿å¼å¨çº¿ç¨å æ ä¸ä¼ éæ°æ®ãæäºæéï¼åå¯ä»¥éè¿å¼ç¨ä¼ éæ°æ®ï¼æ¹æ³æ¯å°è¯¥æ°æ®çå åå°åæ¨å ¥çº¿ç¨å æ ä¸ãç¶åï¼å½æ°éè¿å åå°åé´æ¥è®¿é®æ°æ®ã使ç¨æ管代ç 表示æ¤éå é´æ¥å±çæ¹å¼æå¤ç§ã Â å¨ C# ä¸ï¼å¦æå°æ¹æ³åæ°å®ä¹ä¸º ref æ out ï¼åæ°æ®éè¿å¼ç¨èä¸æ¯éè¿å¼ä¼ éãå³ä½¿æ¨æ²¡æä½¿ç¨ Interop ä¹æ¯è¿æ ·ï¼ä½åªæ¯ä»ä¸ä¸ªæ管æ¹æ³è°ç¨å°å¦ä¸ä¸ªæ管æ¹æ³ãä¾å¦ï¼å¦æéè¿ ref ä¼ é System.Int32 åæ°ï¼åå¨çº¿ç¨å æ ä¸ä¼ éçæ¯è¯¥æ°æ®çå°åï¼èä¸æ¯æ´æ°å¼æ¬èº«ãä¸é¢æ¯ä¸ä¸ªå®ä¹ä¸ºéè¿å¼ç¨æ¥æ¶æ´æ°å¼çæ¹æ³ç示ä¾ï¼  void FlipInt32(ref Int32 num){   num = -num; }  è¿éï¼ FlipInt32 æ¹æ³è·åä¸ä¸ª Int32 å¼çå°åã访é®æ°æ®ã对å®æ±åï¼ç¶åå°æ±åè¿çå¼èµç»åå§åéãå¨ä»¥ä¸ä»£ç ä¸ï¼ FlipInt32 æ¹æ³ä¼å°è°ç¨ç¨åºçåé x çå¼ä» 10 æ´æ¹ä¸º -10 ï¼ Â Int32 x = 10; FlipInt32(ref x);  å¨æ管代ç ä¸å¯ä»¥éç¨è¿ç§è½åï¼å°æéä¼ éç»éæ管代ç ãä¾å¦ï¼ FileEncryptionStatus API å½æ°ä»¥ 32 ä½æ 符å·ä½æ©ç çå½¢å¼è¿åæ件å å¯ç¶æã该 API æ以ä¸æ示æ¹å¼è¿è¡è®°å½ï¼  BOOL FileEncryptionStatus(  LPCTSTR lpFileName, // file name  LPDWORD lpStatus    // encryption status );  请注æï¼è¯¥å½æ°å¹¶ä¸ä½¿ç¨å®çè¿åå¼è¿åç¶æï¼èæ¯è¿åä¸ä¸ª Boolean å¼ï¼æ示è°ç¨æ¯å¦æåãå¨æåçæ åµä¸ï¼å®é çç¶æå¼æ¯éè¿ç¬¬äºä¸ªåæ°è¿åçãå®çå·¥ä½æ¹å¼æ¯è°ç¨ç¨åºå该å½æ°ä¼ éæåä¸ä¸ª DWORD åéçæéï¼è该 API å½æ°ç¨ç¶æå¼å¡«å æåçå åä½ç½®ã以ä¸ä»£ç ç段æ¾ç¤ºäºä¸ä¸ªè°ç¨éæ管 FileEncryptionStatus å½æ°çå¯è½å¤é¨æ¹æ³å®ä¹ï¼  [DllImport("Advapi32.dll", CharSet=CharSet.Auto)] static extern Boolean FileEncryptionStatus(String filename,   out UInt32 status);  该å®ä¹ä½¿ç¨ out å ³é®åæ¥ä¸º UInt32 ç¶æå¼æ示 by-ref åæ°ãè¿éæä¹å¯ä»¥éæ© ref å ³é®åï¼å®é ä¸å¨è¿è¡æ¶ä¼äº§çç¸åçæºå¨ç ã out å ³é®ååªæ¯ä¸ä¸ª by-ref åæ°çè§èï¼å®å C# ç¼è¯å¨æ示æä¼ éçæ°æ®åªå¨è¢«è°ç¨çå½æ°å¤é¨ä¼ éãç¸åï¼å¦æä½¿ç¨ ref å ³é®åï¼åç¼è¯å¨ä¼åå®æ°æ®å¯ä»¥å¨è¢«è°ç¨çå½æ°çå é¨åå¤é¨ä¼ éã  æ管代ç ä¸ out å ref åæ°çå¦ä¸ä¸ªå¾å¥½çæ¹é¢æ¯ï¼å°åä½ä¸º by-ref åæ°ä¼ éçåéå¯ä»¥æ¯çº¿ç¨å æ ä¸çä¸ä¸ªæ¬å°åéãä¸ä¸ªç±»æç»æçå ç´ ï¼ä¹å¯ä»¥æ¯å ·æåéæ°æ®ç±»åçæ°ç»ä¸çä¸ä¸ªå ç´ å¼ç¨ãè°ç¨ç¨åºçè¿ç§çµæ´»æ§ä½¿å¾ by-ref åæ°æ为å°éç¼å²åºæé以ååæ°å¼æéçä¸ä¸ªå¾å¥½çèµ·ç¹ãåªæå¨æåç° ref æ out åæ°ä¸ç¬¦åæçéè¦çæ åµä¸ï¼ææä¼èèå°æéå°é为æ´å¤æç CLR ç±»åï¼ä¾å¦ç±»ææ°ç»å¯¹è±¡ï¼ã  å¦ææ¨ä¸çæ C è¯æ³æè è°ç¨ Windows API å½æ°ï¼ææ¶å¾é¾ç¥éä¸ä¸ªæ¹æ³åæ°æ¯å¦éè¦æéãä¸ä¸ªå¸¸è§çæ示符æ¯çåæ°ç±»åæ¯å¦æ¯ä»¥åæ¯ P æ LP å¼å¤´çï¼ä¾å¦ LPDWORD æ PINT ãå¨è¿ä¸¤ä¸ªä¾åä¸ï¼ LP å P æ示åæ°æ¯ä¸ä¸ªæéï¼èå®ä»¬æåçæ°æ®ç±»ååå«ä¸º DWORD æ INT ãç¶èï¼å¨æäºæ åµä¸ï¼å¯ä»¥ç´æ¥ä½¿ç¨ C è¯è¨è¯æ³ä¸çæå· (*) å° API å½æ°å®ä¹ä¸ºæéã以ä¸ä»£ç ç段å±ç¤ºäºè¿æ¹é¢ç示ä¾ï¼  void TakesAPointer(DWORD* pNum);  å¯ä»¥çå°ï¼ä¸è¿°å½æ°çå¯ä¸ä¸ä¸ªåæ°æ¯æå DWORD åéçæéã  å½éè¿ P/Invoke å°éæéæ¶ï¼ ref å out åªç¨äºæ管代ç ä¸çå¼ç±»åãå½ä¸ä¸ªåæ°ç CLR ç±»åä½¿ç¨ struct å ³é®åå®ä¹æ¶ï¼å¯ä»¥è®¤ä¸ºè¯¥åæ°æ¯ä¸ä¸ªå¼ç±»åã Out å ref ç¨äºå°éæåè¿äºæ°æ®ç±»åçæéï¼å 为é常å¼ç±»ååéæ¯å¯¹è±¡ææ°æ®ï¼èå¨æ管代ç ä¸å¹¶æ²¡æ对å¼ç±»åçå¼ç¨ãç¸åï¼å½å°éå¼ç¨ç±»å对象æ¶ï¼å¹¶ä¸éè¦ ref å out å ³é®åï¼å 为åéå·²ç»æ¯å¯¹è±¡çå¼ç¨äºã  å¦ææ¨å¯¹å¼ç¨ç±»ååå¼ç±»åä¹é´çå·®å«ä¸æ¯å¾çæï¼è¯·æ¥é 2000 å¹´ 12 æ åè¡ç MSDN? Magazine ï¼å¨ .NET ä¸æ ç主é¢ä¸å¯ä»¥æ¾å°æ´å¤ä¿¡æ¯ã大å¤æ° CLR ç±»åé½æ¯å¼ç¨ç±»åï¼ç¶èï¼é¤äº System.String å System.Object ï¼ææçåºå ç±»åï¼ä¾å¦ System.Int32 å System.Boolean ï¼é½æ¯å¼ç±»åã  å°éä¸éæ (Opaque) æéï¼ä¸ç§ç¹æ®æ åµ Â ææ¶å¨ Windows API ä¸ï¼æ¹æ³ä¼ éæè¿åçæéæ¯ä¸éæçï¼è¿æå³ç该æéå¼ä»ææ¯è§åº¦è®²æ¯ä¸ä¸ªæéï¼ä½ä»£ç å´ä¸ç´æ¥ä½¿ç¨å®ãç¸åï¼ä»£ç å°è¯¥æéè¿åç» Windows 以便éåè¿è¡éç¨ã  ä¸ä¸ªé常常è§çä¾åå°±æ¯å¥æçæ¦å¿µãå¨ Windows ä¸ï¼å é¨æ°æ®ç»æï¼ä»æ件å°å±å¹ä¸çæé®ï¼å¨åºç¨ç¨åºä»£ç ä¸é½è¡¨ç¤ºä¸ºå¥æãå¥æå ¶å®å°±æ¯ä¸éæçæéææçæé宽度çæ°å¼ï¼åºç¨ç¨åºç¨å®æ¥è¡¨ç¤ºå é¨ç OS æé ã  å°æ°æ åµä¸ï¼ API å½æ°ä¹å°ä¸éææéå®ä¹ä¸º PVOID æ LPVOID ç±»åãå¨ Windows API çå®ä¹ä¸ï¼è¿äºç±»åææå°±æ¯è¯´è¯¥æé没æç±»åã  å½ä¸ä¸ªä¸éææéè¿åç»æ¨çåºç¨ç¨åºï¼æè æ¨çåºç¨ç¨åºææå¾å°ä¸ä¸ªä¸éææéï¼æ¶ï¼æ¨åºè¯¥å°åæ°æè¿åå¼å°é为 CLR ä¸çä¸ç§ç¹æ®ç±»å â System.IntPtr ãå½æ¨ä½¿ç¨ IntPtr ç±»åæ¶ï¼é常ä¸ä½¿ç¨ out æ ref åæ°ï¼å 为 IntPtr æ为ç´æ¥æææéãä¸è¿ï¼å¦ææ¨å°ä¸ä¸ªæéå°é为ä¸ä¸ªæéï¼å对 IntPtr ä½¿ç¨ by-ref åæ°æ¯åéçã Â å¨ CLR ç±»åç³»ç»ä¸ï¼ System.IntPtr ç±»åæä¸ä¸ªç¹æ®çå±æ§ãä¸åç³»ç»ä¸çå ¶ä»åºç±»åï¼ IntPtr 并没æåºå®ç大å°ãç¸åï¼å®å¨è¿è¡æ¶ç大å°æ¯ä¾åºå±æä½ç³»ç»çæ£å¸¸æé大å°èå®çãè¿æå³çå¨ 32 ä½ç Windows ä¸ï¼ IntPtr åéçå®½åº¦æ¯ 32 ä½çï¼èå¨ 64 ä½ç Windows ä¸ï¼å®æ¶ç¼è¯å¨ç¼è¯ç代ç ä¼å° IntPtr å¼çä½ 64 ä½çå¼ãå½å¨æ管代ç åéæ管代ç ä¹é´å°éä¸éææéæ¶ï¼è¿ç§èªå¨è°è大å°çç¹ç¹ååæç¨ã  请记ä½ï¼ä»»ä½è¿åææ¥åå¥æç API å½æ°å ¶å®æä½çå°±æ¯ä¸éææéãæ¨ç代ç åºè¯¥å° Windows ä¸çå¥æå°éæ System.IntPtr å¼ã  æ¨å¯ä»¥å¨æ管代ç ä¸å° IntPtr å¼å¼ºå¶è½¬æ¢ä¸º 32 ä½æ 64 ä½çæ´æ°å¼ï¼æå°åè 强å¶è½¬æ¢ä¸ºåè ãç¶èï¼å½ä½¿ç¨ Windows API å½æ°æ¶ï¼å 为æéåºæ¯ä¸éæçï¼æ以é¤äºåå¨åä¼ éç»å¤é¨æ¹æ³å¤ï¼ä¸è½å°å®ä»¬å¦åå®ç¨ãè¿ç§âåªéåå¨åä¼ éâè§åç两个ç¹ä¾æ¯å½æ¨éè¦åå¤é¨æ¹æ³ä¼ é null æéå¼åéè¦æ¯è¾ IntPtr å¼ä¸ null å¼çæ åµã为äºåå°è¿ä¸ç¹ï¼æ¨ä¸è½å°é¶å¼ºå¶è½¬æ¢ä¸º System.IntPtr ï¼èåºè¯¥å¨ IntPtr ç±»åä¸ä½¿ç¨ Int32.Zero éæå ¬å ±å段ï¼ä»¥ä¾¿è·å¾ç¨äºæ¯è¾æèµå¼ç null å¼ã  å°éææ¬ Â å¨ç¼ç¨æ¶ç»å¸¸è¦å¯¹ææ¬æ°æ®è¿è¡å¤çãææ¬ä¸º interop å¶é äºä¸äºéº»ç¦ï¼è¿æ两个åå ãé¦å ï¼åºå±æä½ç³»ç»å¯è½ä½¿ç¨ Unicode æ¥è¡¨ç¤ºå符串ï¼ä¹å¯è½ä½¿ç¨ ANSI ãå¨æå°æ°æ åµä¸ï¼ä¾å¦ MultiByteToWideChar API å½æ°ç两个åæ°å¨å符éä¸æ¯ä¸ä¸è´çã  第äºä¸ªåå æ¯ï¼å½éè¦è¿è¡ P/Invoke æ¶ï¼è¦å¤çææ¬è¿éè¦ç¹å«äºè§£å° C å CLR å¤çææ¬çæ¹å¼æ¯ä¸åçãå¨ C ä¸ï¼å符串å®é ä¸åªæ¯ä¸ä¸ªå符å¼æ°ç»ï¼é常以 null ä½ä¸ºç»æ符ã大å¤æ° Windows API å½æ°æ¯æç §ä»¥ä¸æ¡ä»¶å¤çå符串çï¼å¯¹äº ANSI ï¼å°å ¶ä½ä¸ºå符å¼æ°ç»ï¼å¯¹äº Unicode ï¼å°å ¶ä½ä¸ºå®½å符å¼æ°ç»ã  幸è¿çæ¯ï¼ CLR 被设计å¾ç¸å½çµæ´»ï¼å½å°éææ¬æ¶é®é¢å¾ä»¥è½»æ¾è§£å³ï¼èä¸ç¨å¨æ Windows API å½æ°ææä»æ¨çåºç¨ç¨åºå¾å°çæ¯ä»ä¹ãè¿éæ¯ä¸äºéè¦è®°ä½ç主è¦èèäºé¡¹ï¼  ? æ¯æ¨çåºç¨ç¨åºå API å½æ°ä¼ éææ¬æ°æ®ï¼è¿æ¯ API å½æ°åæ¨çåºç¨ç¨åºè¿åå符串æ°æ®ï¼æè äºè å ¼æï¼ Â ? æ¨çå¤é¨æ¹æ³åºè¯¥ä½¿ç¨ä»ä¹æ管类åï¼ Â ? API å½æ°ææå¾å°çæ¯ä»ä¹æ ¼å¼çéæ管åç¬¦ä¸²ï¼ Â Â æ们é¦å 解çæåä¸ä¸ªé®é¢ã大å¤æ° Windows API å½æ°é½å¸¦æ LPTSTR æ LPCTSTR å¼ãï¼ä»å½æ°è§åº¦çï¼å®ä»¬åå«æ¯å¯ä¿®æ¹åä¸å¯ä¿®æ¹çç¼å²åºï¼å å«ä»¥ null ç»æçå符æ°ç»ãâ C â代表常æ°ï¼æå³ç使ç¨è¯¥åæ°ä¿¡æ¯ä¸ä¼ä¼ éå°å½æ°å¤é¨ã LPTSTR ä¸çâ T â表æ该åæ°å¯ä»¥æ¯ Unicode æ ANSI ï¼åå³äºæ¨éæ©çå符éååºå±æä½ç³»ç»çå符éãå ä¸ºå¨ Windows API ä¸å¤§å¤æ°å符串åæ°é½æ¯è¿ä¸¤ç§ç±»åä¹ä¸ï¼æ以åªè¦å¨ DllImportAttribute ä¸éæ© CharSet.Auto ï¼ CLR å°±æé»è®¤çæ¹å¼å·¥ä½ã  ç¶èï¼æäº API å½æ°æèªå®ä¹ç DLL å½æ°éç¨ä¸åçæ¹å¼è¡¨ç¤ºå符串ãå¦ææ¨è¦ç¨å°ä¸ä¸ªè¿æ ·çå½æ°ï¼å°±å¯ä»¥éç¨ MarshalAsAttribute 修饰å¤é¨æ¹æ³çå符串åæ°ï¼å¹¶ææä¸ç§ä¸åäºé»è®¤ LPTSTR çåç¬¦ä¸²æ ¼å¼ãæå ³ MarshalAsAttribute çæ´å¤ä¿¡æ¯ï¼è¯·åé ä½äº MarshalAsAttribute Class ç Platform SDK æ档主é¢ã  ç°å¨è®©æ们çä¸ä¸å符串信æ¯å¨æ¨ç代ç åéæ管å½æ°ä¹é´ä¼ éçæ¹åãæ两ç§æ¹å¼å¯ä»¥ç¥éå¤çå符串æ¶ä¿¡æ¯çä¼ éæ¹åã第ä¸ä¸ªä¹æ¯æå¯é çä¸ä¸ªæ¹æ³å°±æ¯é¦å ç解åæ°çç¨éãä¾å¦ï¼æ¨æ£è°ç¨ä¸ä¸ªåæ°ï¼å®çå称类似 CreateMutex 并带æä¸ä¸ªå符串ï¼åå¯ä»¥æ³å该å符串信æ¯æ¯ä»åºç¨ç¨åºå API å½æ°ä¼ éçãåæ¶ï¼å¦ææ¨è°ç¨ GetUserName ï¼å该å½æ°çå称表æå符串信æ¯æ¯ä»è¯¥å½æ°åæ¨çåºç¨ç¨åºä¼ éçã  é¤äºè¿ç§æ¯è¾åççæ¹æ³å¤ï¼ç¬¬äºç§æ¥æ¾ä¿¡æ¯ä¼ éæ¹åçæ¹å¼å°±æ¯æ¥æ¾ API åæ°ç±»åä¸çåæ¯â C âãä¾å¦ï¼ GetUserName API å½æ°ç第ä¸ä¸ªåæ°è¢«å®ä¹ä¸º LPTSTR ç±»åï¼å®ä»£è¡¨ä¸ä¸ªæå Unicode æ ANSI å符串ç¼å²åºçé¿æéãä½æ¯ CreateMutex çå称åæ°è¢«ç±»åå为 LTCTSTR ã请注æï¼è¿éçç±»åå®ä¹æ¯ä¸æ ·çï¼ä½å¢å ä¸ä¸ªåæ¯â C âæ¥è¡¨æç¼å²åºä¸ºå¸¸æ°ï¼ API å½æ°ä¸è½åå ¥ã  ä¸æ¦æç¡®äºææ¬åæ°æ¯åªç¨ä½è¾å ¥è¿æ¯ç¨ä½è¾å ¥ / è¾åºï¼å°±å¯ä»¥ç¡®å®ä½¿ç¨åªç§ CLR ç±»åä½ä¸ºåæ°ç±»åãè¿éæä¸äºè§åãå¦æå符串åæ°åªç¨ä½è¾å ¥ï¼åä½¿ç¨ System.String ç±»åãå¨æ管代ç ä¸ï¼å符串æ¯ä¸åçï¼éåç¨äºä¸ä¼è¢«æ¬æº API å½æ°æ´æ¹çç¼å²åºã  å¦æå符串åæ°å¯ä»¥ç¨ä½è¾å ¥å / æè¾åºï¼åä½¿ç¨ System.StringBuilder ç±»åã StringBuilder ç±»åæ¯ä¸ä¸ªå¾æç¨çç±»åºç±»åï¼å®å¯ä»¥å¸®å©æ¨ææå°æ建å符串ï¼ä¹æ£å¥½å¯ä»¥å°ç¼å²åºä¼ éç»æ¬æºå½æ°ï¼ç±æ¬æºå½æ°ä¸ºæ¨å¡«å å符串æ°æ®ãä¸æ¦å½æ°è°ç¨è¿åï¼æ¨åªéè¦è°ç¨ StringBuilder 对象ç ToString å°±å¯ä»¥å¾å°ä¸ä¸ª String 对象ã  GetShortPathName API å½æ°è½å¾å¥½å°ç¨äºæ¾ç¤ºä»ä¹æ¶åä½¿ç¨ String ãä»ä¹æ¶åä½¿ç¨ StringBuilder ï¼å 为å®åªå¸¦æä¸ä¸ªåæ°ï¼ä¸ä¸ªè¾å ¥å符串ãä¸ä¸ªè¾åºå符串åä¸ä¸ªææè¾åºç¼å²åºçå符é¿åº¦çåæ°ã Â å¾ 3 æ示为å 注éçéæ管 GetShortPathName å½æ°ææ¡£ï¼å®åæ¶æåºäºè¾å ¥åè¾åºå符串åæ°ãå®å¼åºäºæ管çå¤é¨æ¹æ³å®ä¹ï¼ä¹å¦å¾ 3 æ示ã请注æ第ä¸ä¸ªåæ°è¢«å°é为 System.String ï¼å 为å®æ¯ä¸ä¸ªåªç¨ä½è¾å ¥çåæ°ã第äºä¸ªåæ°ä»£è¡¨ä¸ä¸ªè¾åºç¼å²åºï¼å®ä½¿ç¨äº System.StringBuilder ã  å°ç»  æ¬æä¸æ æä»ç»ç P/Invoke åè½è¶³å¤è°ç¨ Windows ä¸çè®¸å¤ API å½æ°ãç¶èï¼å¦ææ¨å¤§éç¨å° interop ï¼åä¼æç»åç°èªå·±å°éäºå¾å¤æçæ°æ®ç»æï¼çè³å¯è½éè¦å¨æ管代ç ä¸éè¿æéç´æ¥è®¿é®å åãå®é ä¸ï¼æ¬æºä»£ç ä¸ç interop å¯ä»¥æ¯ä¸ä¸ªå°ç»èåä½çº§æ¯ç¹èå¨éé¢ççæ£çæ½å¤æçåã CLR ã C# åæ管 C++ æä¾äºè®¸å¤æç¨çåè½ï¼ä¹è®¸ä»¥åæä¼å¨æ¬ä¸æ ä»ç»é«çº§ç P/Invoke è¯é¢ã  åæ¶ï¼åªè¦æ¨è§å¾ .NET Framework ç±»åºæ æ³ææ¾æ¨ç声é³æè 为æ¨æ§è¡å ¶ä»ä¸äºåè½ï¼æ¨å¯ä»¥ç¥éå¦ä½ååå§èä¼ç§ç Windows API 寻æ±ä¸äºå¸®å©ã  API( åºç¨ç¼ç¨æ¥å£ ) æ¯ç¨åºä¸å¤çå¨æ¥å£çå½ä»¤éãæ常ç¨çå°±æ¯å¨å¤é¨è°ç¨å¾®è½¯ WINDOWS å é¨çè¿ç¨ã WINDOWS API å æ¬æåçä½ å¯ä»¥ä½¿ç¨çå½æ°ãç»æã常éãè¿äºå½æ°æ¯ç¨ C è¯è¨åçï¼å¨ä½¿ç¨ä»ä»¬ä¹åï¼ä½ å¿ é¡»å£°æã å®ä¹ Dll çè¿ç¨å°ç¸å½çå¤æï¼çè³æ¯ VB è¿å¤æãä½ å¯ä»¥ä½¿ç¨ API Viewer å·¥å ·å¾å° API å½æ°ç声æï¼ä½æ¯å¿ 须注æçæ¯ï¼å®çåæ°ç±»åè· C# çä¸ä¸æ ·ã 大é¨åçé«çº§è¯è¨é½æ¯æ API ï¼å¾®è½¯å½æ°ç±»åº (MFC) å°è£ äºå¤§é¨åç Win32 API ã ODBC API 对æé«æ°æ®åºçæä½é度大æ好å¤ãä½¿ç¨ API ï¼å¯ä»¥è¯·æ±æ´åºå±çç³»ç»æå¡ã API ä»ç®åç对è¯æ¡å°å¤æçå å¯è¿ç®é½æä¾æ¯æãå¼åè åºè¯¥ç¥éå¦ä½å¨ä»ä»¬ç¨åºä¸ä½¿ç¨ API API æ许å¤ç±»åï¼ï¼é对ä¸åçæä½ç³»ç»ãå¤çå¨â¦â¦â¦â¦ï¼ OS specific API: æä½ç³»ç»ç¹æ API: æ¯ç§æä½ç³»ç»é½æä¸å¥å ¬ç¨ API åä¸æ API ãæ¯å¦ï¼ Windows NT æ¯æ MS-DOS, Win16, Win32, POSIX ( 便æºå¼æä½ç³»ç»æ¥å£ ) ï¼ OS/2 console API ï¼åæ¶ Windows 95 supports MS-DOS, Win16 å Win32 API ã Win16 å Win32 API: WIN16 æ¯åºäº 16 ä½çå¤çå¨ï¼å¹¶ä½¿ç¨ 16 ä½çå¼ï¼å®æ¯ä¸ä¸ªç¬ç«çå¹³å°ãæ¯å¦ï¼ä½ å¯ä»¥è¿è¡ TSR ç¨åºå¨ MS-DOS ç¯å¢ä¸ã WIN32 æ¯åºäº 32 ä½çå¤çå¨ï¼å¹¶ä½¿ç¨ 32 ä½çå¼ãä»å¯ç¨äºä»»ä½æä½ç³»ç»ï¼å®ç使ç¨èå´æ´å¹¿ã Win32 API has 32 prefix after the library name e.g. KERNEL32, USER32 etc? Win32 API ç DLL ä¸è¬é½å ·æ 32 çåç¼ï¼æ¯å¦ï¼ KERNEL32, USER32 çã ææç API é½å¨ä¸é¢ 3 个 DLL ä¸å®ç°çã Kernel User GDI 1. KERNEL å®çåºåæ¯ï¼ KERNEL32.DLL ï¼å®æ¯æä½ç³»ç»ç®¡çç API é Process loading. å è½½è¿ç¨ Context switching. File I/O. æ件æä½ Memory management. å å管ç æ¯å¦ï¼ GlobalMemoryStatus å½æ°è·å¾ç®åç³»ç»ç©çèæå åç使ç¨ä¿¡æ¯ã 2. USER å¨ WIN32 ä¸ï¼å®çåºåæ¯ USER32.DLL This allows managing the entire user interfaces such as å®ç®¡çå ¨é¨çç¨æ·çé¢ï¼æ¯å¦ï¼ Windows çªå£ Menus èå Dialog Boxes 对è¯æ¡ Icons etc., å¾æ ç æ¯å¦ï¼ DrawIcon ç»ä¸ä¸ªå¾æ å¨æå®ç设å¤ä¸ã 3. GDI (Graphical Device Interface) è¿ä¸ª DLL æ¯ GDI32.dll ï¼å®è´è´£å¾åçè¾åºï¼ä½¿ç¨ GDI ç»åºçªå£ï¼èåï¼å¯¹è¯æ¡ It can create Graphical Output. è¾åºå¾å æ¯å¦ï¼ CreateBitmap å½æ°å建ä¸ä¸ªæå®å®½åº¦ãé«åº¦åé¢è²æ ¼å¼çä½å¾ã C# ä¸ API çå·¥å ·å¯¹åå¦è æ¯ç¸å½ä¸éçãå¨ C# 使ç¨ä¸ä½¿ç¨ API ä¹åï¼ä½ åºè¯¥å ç¥é C# ä¸å¦ä½ä½¿ç¨ç»æãç±»å转æ¢ï¼å®å ¨ä¸ä¸å®å ¨ä»£ç çã 使ç¨å¤æç api ä¹åï¼æ们å ç¨ä¸ä¸ªç®åç MessageBox API ä½ä¸ºååãæå¼ä¸ä¸ª C# å·¥ç¨ï¼å¢å ä¸ä¸ªæé®ï¼å¨æé®çç¹å»äºä»¶ä¸ï¼æ们å°æ¾ç¤ºä¸ä¸ªä¿¡æ¯æ¡ã å¢å 使ç¨å¤é¨åºçå½å空é´ï¼ using System.Runtime.InteropServices; ä¸é¢å£°æ API [DllImport("User32.dll")] DllImport å±æ§ç¨æ¥æå®å å«å¤é¨æ¹æ³çå¨æè¿æ¥åºçä½ç½®ã "User32.dll" æåºäºåºåï¼ static ææå®ä¸å±äºç¹å®ç对象ã extern æææ¯ä¸ä¸ªå¤é¨çæ¹æ³ã带æ DllImport å±æ§çæ¹æ³å¿ 须带æ修饰符 extern ã MessageBox æ¯ä¸ä¸ªæ±æ°åï¼å¸¦å个åæ°è¿åä¸ä¸ª int åå¼ã è®¸å¤ API 使ç¨ç»ææ¥ä¼ éãè¿ååæ°ï¼è¿æ ·å¯ä»¥åå°å¤æ度ãå®ä¹å 许使ç¨è±¡ MessageBox å½æ°é£æ ·ï¼ä½¿ç¨åºå®çåæ°ã  å¨æé®çç¹å»äºä»¶ä¸å¢å ä¸é¢ä»£ç ï¼ protected void button1_Click (object sender, System.EventArgs e) { MessageBox (0,"API Message Box","API Demo",0); } ç¼è¯å¹¶è¿è¡ç¨åºï¼ç¹å»æé®ä»¥åï¼ä½ å°±å¯ä»¥çå°ä¸ä¸ªç± API è°ç¨çä¿¡æ¯æ¡ã Using structure 使ç¨ç»æ API ä¸ç»å¸¸ä½¿ç¨å¤æçç»æãä¸è¿ä¸æ¦ä½ æç½äºä»ä»¬ï¼å°æ¯å¾ç®åçã In next example we will use GetSystemInfo API which returns information about the current system. ä¸é¢çååï¼æä»¬ç¨ GetSystemInfo API å¾å°å½åç³»ç»çä¿¡æ¯ã 第ä¸æ¥ï¼å¢å ä¸ä¸ª C# çªå£ï¼å¹¶å¨ä¸é¢å¢å ä¸ä¸ªæé®ï¼å¨çªå£ä»£ç 页å¢å ä¸ä¸ªå½å空é´ï¼ using System.Runtime.InteropServices; 声æ GetSystemInfo çåæ°ç»æ : [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; } 声æ API å½æ°ï¼ [DllImport("kernel32")] static extern void GetSystemInfo(ref SYSTEM_INFO pSI); ref æ¯ä¸ä¸ªæ å¿åéä¼ éå½¢å¼çå ³é®åï¼å®ä½¿ä¼ å ¥ä¼ åºçåéæååä¸ä¸ªåéï¼ä¼ åä¼ éï¼ å¨æé®ç¹å»äºä»¶ä¸å¢å ä¸é¢ç代ç ï¼ protected void button1_Click (object sender, System.EventArgs e) { try { SYSTEM_INFO pSI = new SYSTEM_INFO(); GetSystemInfo(ref pSI); Once you retrieve the structure perform operations on required parameter æ¯å¦ï¼ listBox1.Items.Insert(0,pSI.dwActiveProcessorMask.ToString()); } catch(Exception er) { MessageBox.Show (er.Message); } } Â Â ç¨ Visual C# è°ç¨ Windows API å½æ°  å京æºæ¢°å·¥ä¸å¦é¢ç 00 çº§ï¼ 100085 ï¼åæä» Â Â Â Â Â Api å½æ°æ¯æç Windws åºç¨ç¨åºçåºç³ï¼æ¯ä¸ç§ Windows åºç¨ç¨åºå¼åå·¥å ·ï¼å®æä¾çåºå±å½æ°é½é´æ¥æç´æ¥å°è°ç¨äº Windows API å½æ°ï¼åæ¶ä¸ºäºå®ç°åè½æ©å±ï¼ä¸è¬ä¹é½æä¾äºè°ç¨ WindowsAPI å½æ°çæ¥å£ï¼ ä¹å°±æ¯è¯´å ·å¤è°ç¨å¨æè¿æ¥åºçè½åã Visual C# åå ¶å®å¼åå·¥å ·ä¸æ ·ä¹è½å¤è°ç¨å¨æé¾æ¥åºç API å½æ°ã .NET æ¡æ¶æ¬èº«æä¾äºè¿æ ·ä¸ç§æå¡ , å 许å管è¾ç代ç è°ç¨å¨æé¾æ¥åºä¸å®ç°çéå管è¾å½æ° , å æ¬æä½ç³»ç»æä¾ç Windows API å½æ°ãå®è½å¤å®ä½åè°ç¨è¾åºå½æ° , æ ¹æ®éè¦ï¼ç»ç»å ¶å个åæ° ( æ´åãå符串类åãæ°ç»ãåç»æçç ) è·¨è¶äºæä½è¾¹çã  ä¸é¢ä»¥ C# 为ä¾ç®åä»ç»è°ç¨ API çåºæ¬è¿ç¨ï¼  å¨æé¾æ¥åºå½æ°ç声æ  ãå¨æé¾æ¥åºå½æ°ä½¿ç¨åå¿ é¡»å£°æï¼ç¸å¯¹äº VB,C# å½æ°å£°ææ¾å¾æ´å ç½å¦ï¼åè éè¿ Api Viewer ç²è´´ä»¥åï¼å¯ä»¥ç´æ¥ä½¿ç¨ï¼èåè åéè¦å¯¹åæ°ä½äºé¢å¤çååå·¥ä½ã  ãå¨æé¾æ¥åºå½æ°å£°æé¨åä¸è¬ç±ä¸å两é¨åç»æï¼ä¸æ¯å½æ°åæç´¢å¼å·ï¼äºæ¯å¨æé¾æ¥åºçæ件åã  ã è¬å¦ï¼ä½ æ³è°ç¨ User32.DLL ä¸ç MessageBox å½æ°ï¼æä»¬å¿ é¡»ææå½æ°çåå MessageBoxA æ MessageBoxW ï¼ä»¥ååºåå User32.dll, æ们ç¥é Win32 API 对æ¯ä¸ä¸ªæ¶åå符串åå符çå½æ°ä¸è¬é½åå¨ä¸¤ä¸ªçæ¬ï¼ååèå符ç ANSI çæ¬åååèå符ç UNICODE çæ¬ã  ãä¸é¢æ¯ä¸ä¸ªè°ç¨ API å½æ°çä¾åï¼ Â [DllImport("KERNEL32.DLL", EntryPoint="MoveFileW", SetLastError=true, CharSet=CharSet.Unicode, ExactSpelling=true, CallingConvention=CallingConvention.StdCall)] public static extern bool MoveFile(String src, String dst);  ãå ¶ä¸å ¥å£ç¹ EntryPoint æ è¯å½æ°å¨å¨æé¾æ¥åºçå ¥å£ä½ç½®ï¼å¨ä¸ä¸ªå管è¾çå·¥ç¨ä¸ï¼ç®æ å½æ°çåå§ååååºå·å ¥å£ç¹ä¸ä» æ è¯ä¸ä¸ªè·¨è¶äºæä½çéçå½æ°ãèä¸ï¼ä½ è¿å¯ä»¥æè¿ä¸ªå ¥å£ç¹æ å°ä¸ºä¸ä¸ªä¸åçååï¼ä¹å°±æ¯å¯¹å½æ°è¿è¡éå½åãéå½åå¯ä»¥ç»è°ç¨å½æ°å¸¦æ¥ç§ç§ä¾¿å©ï¼éè¿éå½åï¼ä¸æ¹é¢æ们ä¸ç¨ä¸ºå½æ°ç大å°å伤éèçï¼åæ¶å®ä¹å¯ä»¥ä¿è¯ä¸å·²æçå½åè§åä¿æä¸è´ï¼å 许带æä¸ååæ°ç±»åçå½æ°å ±åï¼æ´éè¦çæ¯å®ç®åäºå¯¹ ANSI å Unicode çæ¬çè°ç¨ã CharSet ç¨äºæ è¯å½æ°è°ç¨æéç¨çæ¯ Unicode ææ¯ ANSI çæ¬ï¼ ExactSpelling ï¼ false å°åè¯ç¼è¯å¨ , 让ç¼è¯å¨å³å®ä½¿ç¨ Unicode æè æ¯ Ansi çæ¬ãå ¶å®çåæ°è¯·åè MSDN å¨çº¿å¸®å© .  ãå¨ C# ä¸ï¼ä½ å¯ä»¥å¨ EntryPoint åéè¿ååååºå·å£°æä¸ä¸ªå¨æé¾æ¥åºå½æ°ï¼å¦æå¨æ¹æ³å®ä¹ä¸ä½¿ç¨çå½æ°åä¸ DLL å ¥å£ç¹ç¸åï¼ä½ ä¸éè¦å¨ EntryPoint åæ¾ç¤ºå£°æå½æ°ãå¦åï¼ä½ å¿ é¡»ä½¿ç¨ä¸åå±æ§æ ¼å¼æ示ä¸ä¸ªååååºå·ã  [DllImport("dllname", EntryPoint="Functionname")] [DllImport("dllname", EntryPoint="#123")] å¼å¾æ³¨æçæ¯ï¼ä½ å¿ é¡»å¨æ°ååºå·åå âï¼â  ä¸é¢æ¯ä¸ä¸ªç¨ MsgBox æ¿æ¢ MessageBox ååçä¾åï¼ Â [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); } 许å¤å管è¾çå¨æé¾æ¥åºå½æ°ææä½ è½å¤ä¼ éä¸ä¸ªå¤æçåæ°ç±»åç»å½æ°ï¼è¬å¦ä¸ä¸ªç¨æ·å®ä¹çç»æç±»åæåæè å管è¾ä»£ç å®ä¹çä¸ä¸ªç±»æåï¼è¿æ¶ä½ å¿ é¡»æä¾é¢å¤çä¿¡æ¯æ ¼å¼åè¿ä¸ªç±»åï¼ä»¥ä¿æåæ°åæçå¸å±å对é½ã  C# æä¾äºä¸ä¸ª StructLayoutAttribute ç±»ï¼éè¿å®ä½ å¯ä»¥å®ä¹èªå·±çæ ¼å¼åç±»åï¼å¨å管è¾ä»£ç ä¸ï¼æ ¼å¼åç±»åæ¯ä¸ä¸ªç¨ StructLayoutAttribute 说æçç»ææç±»æåï¼éè¿å®è½å¤ä¿è¯å ¶å é¨æåé¢æçå¸å±ä¿¡æ¯ãå¸å±çéé¡¹å ±æä¸ç§ï¼  å¸å±é项  æè¿°  LayoutKind.Automatic 为äºæé«æçå 许è¿è¡æ对类åæåéæ°æåºã  注æï¼æ°¸è¿ä¸è¦ä½¿ç¨è¿ä¸ªé项æ¥è°ç¨ä¸å管è¾çå¨æé¾æ¥åºå½æ°ã  LayoutKind.Explicit 对æ¯ä¸ªåæç § FieldOffset å±æ§å¯¹ç±»åæåæåº Â LayoutKind.Sequential 对åºç°å¨å管è¾ç±»åå®ä¹å°æ¹çä¸å管è¾å åä¸çç±»åæåè¿è¡æåºã Â ä¼ éç»ææå  ä¸é¢çä¾å说æå¦ä½å¨å管è¾ä»£ç ä¸å®ä¹ä¸ä¸ªç¹åç©å½¢ç±»åï¼å¹¶ä½ä¸ºä¸ä¸ªåæ°ä¼ éç» User32.dll åºä¸ç PtInRect å½æ°ï¼  å½æ°çä¸å管è¾åå声æå¦ä¸ï¼  BOOL PtInRect(const RECT *lprc, POINT pt); 注æä½ å¿ é¡»éè¿å¼ç¨ä¼ é Rect ç»æåæ°ï¼å 为å½æ°éè¦ä¸ä¸ª Rect çç»ææéã  [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 PtInRect(ref Rect r, Point p); }Â ç±»ä¼¼ä½ å¯ä»¥è°ç¨ GetSystemInfo å½æ°è·å¾ç³»ç»ä¿¡æ¯ï¼  ? 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);  类æåçä¼ é  åæ ·åªè¦ç±»å ·æä¸ä¸ªåºå®çç±»æåå¸å±ï¼ä½ ä¹å¯ä»¥ä¼ éä¸ä¸ªç±»æåç»ä¸ä¸ªä¸å管è¾çå¨æé¾æ¥åºå½æ°ï¼ä¸é¢çä¾å主è¦è¯´æå¦ä½ä¼ éä¸ä¸ª sequential 顺åºå®ä¹ç MySystemTime ç±»ç» User32.dll ç GetSystemTime å½æ° , å½æ°ç¨ C/C++ è°ç¨è§èå¦ä¸ :  void GetSystemTime(SYSTEMTIME* SystemTime); ä¸åä¼ å¼ç±»å , ç±»æ»æ¯éè¿å¼ç¨ä¼ éåæ° . [C#] [StructLayout(LayoutKind.Sequential)] public class MySystemTime { public ushort wYear; public ushort wMonth; public ushort wDayOfWeek; public ushort wDay; public ushort wHour; public ushort wMinute; public ushort wSecond; public ushort wMilliseconds; } class Win32API { [DllImport("User32.dll")] public static extern void GetSystemTime(MySystemTime st); } åè°å½æ°çä¼ é : ä»å管è¾ç代ç ä¸è°ç¨å¤§å¤æ°å¨æé¾æ¥åºå½æ° , ä½ åªéå建ä¸ä¸ªå管è¾çå½æ°å®ä¹ï¼ç¶åè°ç¨å®å³å¯ , è¿ä¸ªè¿ç¨é常ç´æ¥ã  å¦æä¸ä¸ªå¨æé¾æ¥åºå½æ°éè¦ä¸ä¸ªå½æ°æéä½ä¸ºåæ°ï¼ä½ è¿éè¦å以ä¸å æ¥ï¼  é¦å ï¼ä½ å¿ é¡»åèæå ³è¿ä¸ªå½æ°çææ¡£ï¼ç¡®å®è¿ä¸ªå½æ°æ¯å¦éè¦ä¸ä¸ªåè°ï¼ç¬¬äºï¼ä½ å¿ é¡»å¨å管è¾ä»£ç ä¸å建ä¸ä¸ªåè°å½æ°ï¼æåï¼ä½ å¯ä»¥ææåè¿ä¸ªå½æ°çæéä½ä¸ºä¸ä¸ªåæ°åéç» DLL å½æ° ,.  åè°å½æ°åå ¶å®ç° : åè°å½æ°ç»å¸¸ç¨å¨ä»»å¡éè¦éå¤æ§è¡çåºå , è¬å¦ç¨äºæ举å½æ° , è¬å¦ Win32 API ä¸ç EnumFontFamilies( åä½æ举 ), EnumPrinters( æå°æº ), EnumWindows ( çªå£æ举 ) å½æ° . ä¸é¢ä»¥çªå£æä¸¾ä¸ºä¾ , è°è°å¦ä½éè¿è°ç¨ EnumWindow å½æ°éåç³»ç»ä¸åå¨çææçªå£  åä¸é¢å 个æ¥éª¤ : 1. å¨å®ç°è°ç¨åå åèå½æ°ç声æ  BOOL EnumWindows(WNDENUMPROC lpEnumFunc, LPARMAM IParam) æ¾ç¶è¿ä¸ªå½æ°éè¦ä¸ä¸ªåè°å½æ°å°åä½ä¸ºåæ° . 2. å建ä¸ä¸ªå管è¾çåè°å½æ° , è¿ä¸ªä¾å声æ为代表类å (delegate), ä¹å°±æ¯æ们æ说çåè° , å®å¸¦æ两个åæ° hwnd å lparam, 第ä¸ä¸ªåæ°æ¯ä¸ä¸ªçªå£å¥æï¼ç¬¬äºä¸ªåæ°ç±åºç¨ç¨åºå®ä¹ï¼ä¸¤ä¸ªåæ°å为æ´å½¢ã  ããå½è¿ä¸ªåè°å½æ°è¿åä¸ä¸ªéé¶å¼æ¶ï¼æ 示æ§è¡æåï¼é¶åæ示失败ï¼è¿ä¸ªä¾åæ»æ¯è¿å True å¼ï¼ä»¥ä¾¿æç»æ举ã  3. æåå建以代表对象 (delegate) ï¼å¹¶æå®ä½ä¸ºä¸ä¸ªåæ°ä¼ éç» EnumWindows å½æ°ï¼å¹³å°ä¼èªå¨å° æ代表转åæå½æ°è½å¤è¯å«çåè°æ ¼å¼ã  [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(" çªå£å¥æ为 "); Console.WriteLine(hwnd); return true; } }  æéç±»ååæ°ä¼ éï¼ Â ãå¨ Windows API å½æ°è°ç¨æ¶ï¼å¤§é¨åå½æ°éç¨æéä¼ éåæ°ï¼å¯¹ä¸ä¸ªç»æåéæéï¼æ们é¤äºä½¿ç¨ä¸é¢çç±»åç»ææ¹æ³ä¼ éåæ°ä¹å¤ï¼æ们ææ¶è¿å¯ä»¥éç¨æ°ç»ä¼ éåæ°ã  ãä¸é¢è¿ä¸ªå½æ°éè¿è°ç¨ GetUserName è·å¾ç¨æ·å  BOOL GetUserName( LPTSTR lpBuffer, // ç¨æ·åç¼å²åº  LPDWORD nSize // åæ¾ç¼å²åºå¤§å°çå°åæé  ); ã  [DllImport("Advapi32.dll", EntryPoint="GetComputerName", ExactSpelling=false, SetLastError=true)] static extern bool GetComputerName ( [MarshalAs(UnmanagedType.LPArray)] byte[] lpBuffer, ã [MarshalAs(UnmanagedType.LPArray)] Int32[] nSize ); ãè¿ä¸ªå½æ°æ¥å两个åæ°ï¼ char * å int *, å ä¸ºä½ å¿ é¡»åé ä¸ä¸ªå符串ç¼å²åºä»¥æ¥åå符串æéï¼ä½ å¯ä»¥ä½¿ç¨ String 类代æ¿è¿ä¸ªåæ°ç±»åï¼å½ç¶ä½ è¿å¯ä»¥å£°æä¸ä¸ªåèæ°ç»ä¼ é ANSI å符串ï¼åæ ·ä½ ä¹å¯ä»¥å£°æä¸ä¸ªåªæä¸ä¸ªå ç´ çé¿æ´åæ°ç»ï¼ä½¿ç¨æ°ç»åä½ä¸ºç¬¬äºä¸ªåæ°ãä¸é¢çå½æ°å¯ä»¥è°ç¨å¦ä¸ï¼  byte[] str=new byte[20]; Int32[] len=new Int32[1]; len[0]=20; GetComputerName (str,len); MessageBox.Show(System.Text.Encoding.ASCII.GetString(str)); ãæåéè¦æéçæ¯ï¼æ¯ä¸ç§æ¹æ³ä½¿ç¨åå¿ é¡»å¨æ件头å ä¸ï¼  ã using System.Runtime.InteropServices; C# API C:\ProgramFiles\MicrosoftVisual Studio .NET\ FrameworkSDK\Samples\ Technologies\ Interop\PlatformInvoke\ WinAPIs\CS ç®å½ä¸æ大éçè°ç¨ API çä¾åã ä¸ãè°ç¨æ ¼å¼ using System.Runtime.InteropServices; // å¼ç¨æ¤å称空é´ï¼ç®ååé¢ç代ç // ä½¿ç¨ DllImportAttribute ç¹æ§æ¥å¼å ¥ api å½æ°ï¼æ³¨æ声æçæ¯ç©ºæ¹æ³ï¼å³æ¹æ³ä½ä¸ºç©ºã [DllImport("user32.dll")] public static extern ReturnType FunctionName(type arg1,type arg2,...); // è°ç¨æ¶ä¸è°ç¨å ¶ä»æ¹æ³å¹¶æ åºå«  å¯ä»¥ä½¿ç¨å段è¿ä¸æ¥è¯´æç¹æ§ï¼ç¨éå·éå¼ï¼å¦ï¼ [ DllImport( "kernel32", EntryPoint="GetVersionEx" )] DllImportAttribute ç¹æ§çå ¬å ±å段å¦ä¸ï¼ 1ãCallingConventionæ示åéæ管å®ç°ä¼ éæ¹æ³åæ°æ¶æç¨ç CallingConventionå¼ã CallingConvention.Cdecl : è°ç¨æ¹æ¸ çå æ ãå®ä½¿æ¨è½å¤è°ç¨å ·æ varargs çå½æ°ã CallingConvention.StdCall : 被è°ç¨æ¹æ¸ çå æ ãå®æ¯ä»æ管代ç è°ç¨éæ管å½æ°çé»è®¤çº¦å®ã 2ãCharSetæ§å¶è°ç¨å½æ°çå称çæ¬åæ示å¦ä½åæ¹æ³å°é Stringåæ°ã æ¤å段被设置为 CharSet å¼ä¹ä¸ãå¦æ CharSet å段设置为 Unicode ï¼åææå符串åæ°å¨ä¼ éå°éæ管å®ç°ä¹åé½è½¬æ¢æ Unicode å符ãè¿è¿å¯¼è´å DLL EntryPoint çå称ä¸è¿½å åæ¯â W âãå¦ææ¤å段设置为 Ansi ï¼åå符串å°è½¬æ¢æ ANSI å符串ï¼åæ¶å DLL EntryPoint çå称ä¸è¿½å åæ¯â A âã大å¤æ° Win32 API 使ç¨è¿ç§è¿½å â W âæâ A âç约å®ãå¦æ CharSet 设置为 Auto ï¼åè¿ç§è½¬æ¢å°±æ¯ä¸å¹³å°æå ³çï¼å¨ Windows NT ä¸ä¸º Unicode ï¼å¨ Windows 98 ä¸ä¸º Ansi ï¼ã CharSet çé»è®¤å¼ä¸º Ansi ã CharSet å段ä¹ç¨äºç¡®å®å°ä»æå®ç DLL å¯¼å ¥åªä¸ªçæ¬çå½æ°ã CharSet.Ansi å CharSet.Unicode çå称å¹é è§å大ä¸ç¸åãå¯¹äº Ansi æ¥è¯´ï¼å¦æå° EntryPoint 设置为â MyMethod âä¸å®åå¨çè¯ï¼åè¿åâ MyMethod âãå¦æ DLL ä¸æ²¡æâ MyMethod âï¼ä½åå¨â MyMethodA âï¼åè¿åâ MyMethodA âã å¯¹äº Unicode æ¥è¯´åæ£å¥½ç¸åãå¦æå° EntryPoint 设置为â MyMethod âä¸å®åå¨çè¯ï¼åè¿åâ MyMethodW âãå¦æ DLL ä¸ä¸åå¨â MyMethodW âï¼ä½åå¨â MyMethod âï¼åè¿åâ MyMethod âãå¦æ使ç¨çæ¯ Auto ï¼åå¹é è§åä¸å¹³å°æå ³ï¼å¨ Windows NT ä¸ä¸º Unicode ï¼å¨ Windows 98 ä¸ä¸º Ansi ï¼ãå¦æ ExactSpelling 设置为 true ï¼ååªæå½ DLL ä¸åå¨â MyMethod âæ¶æè¿åâ MyMethod âã   3ãEntryPointæ示è¦è°ç¨ç DLL å ¥å£ç¹çå称æåºå·ã å¦æä½ çæ¹æ³åä¸æ³ä¸ api å½æ°ååçè¯ï¼ä¸å®è¦æå®æ¤åæ° , ä¾å¦ï¼ [DllImport("user32.dll",CharSet="CharSet.Auto",EntryPoint="MessageBox")] public static extern int MsgBox(IntPtr hWnd,string txt,string caption, int type);   4ãExactSpellingæ示æ¯å¦åºä¿®æ¹éæ管 DLLä¸çå ¥å£ç¹çå称ï¼ä»¥ä¸ CharSetå段ä¸æå®ç CharSetå¼ç¸å¯¹åºã å¦æ为 true ï¼åå½ DllImportAttribute.CharSet å段设置为 CharSet ç Ansi å¼æ¶ï¼åæ¹æ³å称ä¸è¿½å åæ¯ A ï¼å½ DllImportAttribute.CharSet å段设置为 CharSet ç Unicode å¼æ¶ï¼åæ¹æ³çå称ä¸è¿½å åæ¯ W ãæ¤å段çé»è®¤å¼æ¯ false ã 5 ã PreserveSig æ示æ管æ¹æ³ç¾åä¸åºè½¬æ¢æè¿å HRESULT ã并ä¸å¯è½æä¸ä¸ªå¯¹åºäºè¿åå¼çéå [out, retval] åæ°çéæ管ç¾åã 6 ã SetLastError æ示被è°ç¨æ¹å¨ä»å±æ§åæ¹æ³è¿åä¹åå°è°ç¨ Win32 API SetLastError ã true æ示è°ç¨æ¹å°è°ç¨ SetLastError ï¼é»è®¤ä¸º false ãè¿è¡æ¶å°éææ¶å¨å°è°ç¨ GetLastError 并ç¼åè¿åçå¼ï¼ä»¥é²å ¶è¢«å ¶ä» API è°ç¨éåãç¨æ·å¯éè¿è°ç¨ GetLastWin32Error æ¥æ£ç´¢é误代ç ã  äºãåæ°ç±»åï¼ 1 ãæ°å¼åç´æ¥ç¨å¯¹åºçå°±å¯ãï¼ DWORD -> int , WORD -> Int16 ï¼ 2 ã API ä¸å符串æéç±»å -> .net ä¸ string 3 ã API ä¸å¥æ (dWord) -> .net ä¸ IntPtr 4 ã API ä¸ç»æ -> .net ä¸ç»ææè ç±»ã注æè¿ç§æ åµä¸ï¼è¦å ç¨ StructLayout ç¹æ§éå®å£°æç»ææç±» å ¬å ±è¯è¨è¿è¡åºå©ç¨ StructLayoutAttribute æ§å¶ç±»æç»æçæ°æ®å段å¨æ管å åä¸çç©çå¸å± , å³ç±»æç»æéè¦ææç§æ¹å¼æåãå¦æè¦å°ç±»ä¼ éç»éè¦æå®å¸å±çéæ管代ç ï¼åæ¾å¼æ§å¶ç±»å¸å±æ¯éè¦çãå®çæé å½æ°ä¸ç¨ LayoutKind å¼åå§å StructLayoutAttribute ç±»çæ°å®ä¾ã LayoutKind.Sequential ç¨äºå¼ºå¶å°æåæå ¶åºç°ç顺åºè¿è¡é¡ºåºå¸å±ã LayoutKind.Explicit ç¨äºæ§å¶æ¯ä¸ªæ°æ®æåç精确ä½ç½®ãå©ç¨ Explicit ï¼ æ¯ä¸ªæåå¿ é¡»ä½¿ç¨ FieldOffsetAttribute æ示æ¤å段å¨ç±»åä¸çä½ç½®ãå¦ï¼ [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; } ä¸é¢æ¯é对 API ä¸ OSVERSIONINFO ç»æï¼å¨ .net ä¸å®ä¹å¯¹åºç±»æç»æçä¾åï¼ Â Â //.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;   [ MarshalAs( UnmanagedType.ByValTStr, SizeConst=128 )] public String versionString; }  æ¤ä¾ä¸ç¨å° MashalAs ç¹æ§ï¼å®ç¨äºæè¿°å段ãæ¹æ³æåæ°çå°éå¤çæ ¼å¼ãç¨å®ä½ä¸ºåæ°åç¼å¹¶æå®ç®æ éè¦çæ°æ®ç±»åãä¾å¦ï¼ä»¥ä¸ä»£ç å°ä¸¤ä¸ªåæ°ä½ä¸ºæ°æ®ç±»åé¿æéå°éç» Windows API å½æ°çå符串 (LPStr) ï¼ [MarshalAs(UnmanagedType.LPStr)] String existingfile; [MarshalAs(UnmanagedType.LPStr)] String newfile;  注æç»æä½ä¸ºåæ°æ¶åï¼ä¸è¬åé¢è¦å ä¸ref修饰符ï¼å¦åä¼åºç°éè¯¯ï¼ å¯¹è±¡çå¼ç¨æ²¡ææå®å¯¹è±¡çå®ä¾ã [ DllImport( "kernel32", EntryPoint="GetVersionEx" )] public static extern bool GetVersionEx2( ref OSVersionInfo2 osvi );  ä¸ãå¦ä½ä¿è¯ä½¿ç¨æ管对象çå¹³å°è°ç¨æåï¼ å¦æå¨è°ç¨å¹³å° invoke åçä»»ä½ä½ç½®é½æªå¼ç¨æ管对象ï¼ååå¾åæ¶å¨å¯è½å°å®æ该æ管对象ãè¿å°éæ¾èµæºå¹¶ä½¿å¥ææ æï¼ä»è导è´å¹³å° invoke è°ç¨å¤±è´¥ãç¨ HandleRef å è£ å¥æå¯ä¿è¯å¨å¹³å° invoke è°ç¨å®æåï¼ä¸å¯¹æ管对象è¿è¡åå¾åæ¶ã ä¾å¦ä¸é¢ï¼ 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 å½æ° ç±äº fs æ¯æ管对象ï¼æ以æå¯è½å¨å¹³å°è°ç¨è¿æªå®ææ¶å被åå¾åæ¶ç«åæ¶ãå°æ件æµçå¥æç¨ HandleRef å è£ åï¼å°±è½é¿å 被åå¾ç«åæ¶ : [ 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 );     æå¨èªå·±æè¿çç¼ç¨ä¸æ³¨æå°ä¸ä¸ªè¶å¿ï¼æ£æ¯è¿ä¸ªè¶å¿æå¼åºæ¬æçä¸æ 主é¢ãæè¿ï¼æå¨åºäº Microsoft? .NET Framework çåºç¨ç¨åºä¸å®æäºå¤§éç Win32? Interop ãæ并ä¸æ¯è¦è¯´æçåºç¨ç¨åºå 满äºèªå®ä¹ç interop 代ç ï¼ä½ææ¶æä¼å¨ .NET Framework ç±»åºä¸ç¢°å°ä¸äºæ¬¡è¦ä½åç¹çµ®ãä¸å åçå 容ï¼éè¿è°ç¨è¯¥ Windows? API ï¼å¯ä»¥å¿«éåå°è¿æ ·ç麻ç¦ã  å æ¤æè®¤ä¸ºï¼ .NET Framework 1.0 æ 1.1 çç±»åºä¸åå¨ä»»ä½ Windows æ没æçåè½éå¶é½ä¸è¶³ä¸ºæªãæ¯ç«ï¼ 32 ä½ç Windows ï¼ä¸ç®¡ä½ç§çæ¬ï¼æ¯ä¸ä¸ªæççæä½ç³»ç»ï¼ä¸ºå¹¿å¤§å®¢æ·æå¡äºåå¤å¹´ãç¸æ¯ä¹ä¸ï¼ .NET Framework å´æ¯ä¸ä¸ªæ°äºç©ã  éçè¶æ¥è¶å¤çå¼å人åå°ç产åºç¨ç¨åºè½¬å°æ管代ç ï¼å¼å人åæ´é¢ç¹å°ç 究åºå±æä½ç³»ç»ä»¥å¾æ¾åºä¸äºå ³é®åè½æ¾å¾å¾èªç¶ â è³å°ç®åæ¯å¦æ¤ã  å¼å¾åºå¹¸çæ¯ï¼å ¬å ±è¯è¨è¿è¡åº (CLR) ç interop åè½ï¼ç§°ä¸ºå¹³å°è°ç¨ (P/Invoke) ï¼é常å®åãå¨æ¬ä¸æ ä¸ï¼æå°éç¹ä»ç»å¦ä½å®é ä½¿ç¨ P/Invoke æ¥è°ç¨ Windows API å½æ°ãå½æ CLR ç COM Interop åè½æ¶ï¼ P/Invoke å½ä½åè¯ä½¿ç¨ï¼å½æ该åè½ç使ç¨æ¶ï¼åå°å ¶å½ä½å¨è¯ä½¿ç¨ãæ并ä¸æç®ç´æ¥ä»ç» COM Interop ï¼å 为å®æ¯ P/Invoke å ·ææ´å¥½çå¯è®¿é®æ§ï¼å´æ´å å¤æï¼è¿æç¹èªç¸çç¾ï¼è¿ä½¿å¾å° COM Interop ä½ä¸ºä¸æ 主é¢æ¥è®¨è®ºä¸å¤ªç®ææ¼è¦ã Â èµ°è¿ P/Invoke  é¦å ä»èå¯ä¸ä¸ªç®åç P/Invoke 示ä¾å¼å§ã让æ们çä¸çå¦ä½è°ç¨ Win32 MessageBeep å½æ°ï¼å®çéæ管声æå¦ä»¥ä¸ä»£ç æç¤ºï¼ Â BOOL MessageBeep(  UINT uType  // beep type );  为äºè°ç¨ MessageBeep ï¼æ¨éè¦å¨ C# ä¸å°ä»¥ä¸ä»£ç æ·»å å°ä¸ä¸ªç±»æç»æå®ä¹ä¸ï¼  [DllImport("User32.dll")] static extern Boolean MessageBeep(UInt32 beepType);  令人æ讶çæ¯ï¼åªéè¦è¿æ®µä»£ç å°±å¯ä»¥ä½¿æ管代ç è°ç¨éæ管ç MessageBeep API ãå®ä¸æ¯ä¸ä¸ªæ¹æ³è°ç¨ï¼èæ¯ä¸ä¸ªå¤é¨æ¹æ³å®ä¹ãï¼å¦å¤ï¼å®æ¥è¿äºä¸ä¸ªæ¥èª C è C# å 许çç´æ¥ç«¯å£ï¼å æ¤ä»¥å®ä¸ºèµ·ç¹æ¥ä»ç»ä¸äºæ¦å¿µæ¯æ帮å©çãï¼æ¥èªæ管代ç çå¯è½è°ç¨å¦ä¸æç¤ºï¼ Â MessageBeep(0);  请注æï¼ç°å¨ MessageBeep æ¹æ³è¢«å£°æ为 static ãè¿æ¯ P/Invoke æ¹æ³æè¦æ±çï¼å 为å¨è¯¥ Windows API ä¸æ²¡æä¸è´çå®ä¾æ¦å¿µãæ¥ä¸æ¥ï¼è¿è¦æ³¨æ该æ¹æ³è¢«æ 记为 extern ãè¿æ¯æ示ç¼è¯å¨è¯¥æ¹æ³æ¯éè¿ä¸ä¸ªä» DLL 导åºçå½æ°å®ç°çï¼å æ¤ä¸éè¦æä¾æ¹æ³ä½ã  说å°ç¼ºå°æ¹æ³ä½ï¼æ¨æ¯å¦æ³¨æå° MessageBeep 声æ并没æå å«ä¸ä¸ªæ¹æ³ä½ï¼ä¸å¤§å¤æ°ç®æ³ç±ä¸é´è¯è¨ (IL) æ令ç»æçæ管æ¹æ³ä¸åï¼ P/Invoke æ¹æ³åªæ¯å æ°æ®ï¼å®æ¶ (JIT) ç¼è¯å¨å¨è¿è¡æ¶éè¿å®å°æ管代ç ä¸éæ管ç DLL å½æ°è¿æ¥èµ·æ¥ãæ§è¡è¿ç§å°éæ管ä¸ççè¿æ¥æéçä¸ä¸ªéè¦ä¿¡æ¯å°±æ¯å¯¼åºéæ管æ¹æ³ç DLL çå称ãè¿ä¸ä¿¡æ¯æ¯ç± MessageBeep æ¹æ³å£°æä¹åç DllImport èªå®ä¹å±æ§æä¾çãå¨æ¬ä¾ä¸ï¼å¯ä»¥çå°ï¼ MessageBeep éæ管 API æ¯ç± Windows ä¸ç User32.dll 导åºçã  å°ç°å¨ä¸ºæ¢ï¼å ³äºè°ç¨ MessageBeep å°±å©ä¸¤ä¸ªè¯é¢æ²¡æä»ç»ï¼è¯·å顾ä¸ä¸ï¼è°ç¨ç代ç ä¸ä»¥ä¸æ示代ç ç段é常ç¸ä¼¼ï¼  [DllImport("User32.dll")] static extern Boolean MessageBeep(UInt32 beepType);  æåè¿ä¸¤ä¸ªè¯é¢æ¯ä¸æ°æ®å°éå¤ç (data marshaling) åä»æ管代ç å°éæ管å½æ°çå®é æ¹æ³è°ç¨æå ³çè¯é¢ãè°ç¨éæ管 MessageBeep å½æ°å¯ä»¥ç±æ¾å°ä½ç¨åå ç extern MessageBeep 声æçä»»ä½æ管代ç æ§è¡ã该è°ç¨ç±»ä¼¼äºä»»ä½å ¶ä»å¯¹éææ¹æ³çè°ç¨ãå®ä¸å ¶ä»ä»»ä½æ管æ¹æ³è°ç¨çå ±åä¹å¤å¨äºå¸¦æ¥äºæ°æ®å°éå¤ççéè¦ã  C# çè§åä¹ä¸æ¯å®çè°ç¨è¯æ³åªè½è®¿é® CLR æ°æ®ç±»åï¼ä¾å¦ System.UInt32 å System.Boolean ã C# æ¾ç¶ä¸è¯å« Windows API ä¸ä½¿ç¨çåºäº C çæ°æ®ç±»åï¼ä¾å¦ UINT å BOOL ï¼ï¼è¿äºç±»ååªæ¯ C è¯è¨ç±»åçç±»åå®ä¹èå·²ãæä»¥å½ Windows API å½æ° MessageBeep æ以ä¸æ¹å¼ç¼åæ¶ Â BOOL MessageBeep( UINT uType )  å¤é¨æ¹æ³å°±å¿ é¡»ä½¿ç¨ CLR ç±»åæ¥å®ä¹ï¼å¦æ¨å¨åé¢ç代ç ç段ä¸æçå°çãéè¦ä½¿ç¨ä¸åºç¡ API å½æ°ç±»åä¸åä½ä¸ä¹å ¼å®¹ç CLR ç±»åæ¯ P/Invoke è¾é¾ä½¿ç¨çä¸ä¸ªæ¹é¢ãå æ¤ï¼å¨æ¬ä¸æ çåé¢æå°ç¨å®æ´çç« èæ¥ä»ç»æ°æ®å°éå¤çã Â æ ·å¼ Â å¨ C# ä¸å¯¹ Windows API è¿è¡ P/Invoke è°ç¨æ¯å¾ç®åçãä½å¦æç±»åºæç»ä½¿æ¨çåºç¨ç¨åºååºå声ï¼åºè¯¥æ³æ¹è®¾æ³è°ç¨ Windows 使å®è¿è¡è¿é¡¹å·¥ä½ï¼æ¯åï¼ Â æ¯çãä½æ¯ä¸éæ©çæ¹æ³æå ³ï¼èä¸å ³ç³»ç大ï¼é常ï¼å¦æç±»åºæä¾æç§éå¾æ¥å®ç°æ¨çæå¾ï¼åæå¥½ä½¿ç¨ API èä¸è¦ç´æ¥è°ç¨éæ管代ç ï¼å 为 CLR ç±»åå Win32 ä¹é´å¨æ ·å¼ä¸æå¾å¤§çä¸åãæå¯ä»¥å°å ³äºè¿ä¸ªé®é¢ç建议å½ç»ä¸ºä¸å¥è¯ãå½æ¨è¿è¡ P/Invoke æ¶ï¼ä¸è¦ä½¿åºç¨ç¨åºé»è¾ç´æ¥å±äºä»»ä½å¤é¨æ¹æ³æå ¶ä¸çæ件ã å¦ææ¨éµå¾ªè¿ä¸ªå°è§åï¼ä»é¿è¿çç»å¸¸ä¼çå»è®¸å¤ç麻ç¦ã Â å¾ 1 ä¸ç代ç æ¾ç¤ºäºææ讨论ç MessageBeep å¤é¨æ¹æ³çæå°éå 代ç ãå¾ 1 ä¸å¹¶æ²¡æä»»ä½æ¾èçååï¼èåªæ¯å¯¹æ å è£ çå¤é¨æ¹æ³è¿è¡ä¸äºæ®éçæ¹è¿ï¼è¿å¯ä»¥ä½¿å·¥ä½æ´å è½»æ¾ä¸äºãä»é¡¶é¨å¼å§ï¼æ¨ä¼æ³¨æå°ä¸ä¸ªå为 Sound çå®æ´ç±»åï¼å®ä¸ç¨äº MessageBeep ãå¦ææéè¦ä½¿ç¨ Windows API å½æ° PlaySound æ¥æ·»å 对ææ¾æ³¢å½¢çæ¯æï¼åå¯ä»¥éç¨ Sound ç±»åãç¶èï¼æä¸ä¼å å ¬å¼åä¸ªå ¬å ±éææ¹æ³çç±»åèçæ°ãæ¯ç«è¿åªæ¯åºç¨ç¨åºä»£ç èå·²ãè¿åºè¯¥æ³¨æå°ï¼ Sound æ¯å¯å°çï¼å¹¶å®ä¹äºä¸ä¸ªç©ºçç§ææé å½æ°ãè¿äºåªæ¯ä¸äºç»èï¼ç®çæ¯ä½¿ç¨æ·ä¸ä¼é误å°ä» Sound æ´¾çç±»æè å建å®çå®ä¾ã Â å¾ 1 ä¸ç代ç çä¸ä¸ä¸ªç¹å¾æ¯ï¼ P/Invoke åºç°ä½ç½®çå®é å¤é¨æ¹æ³æ¯ Sound çç§ææ¹æ³ãè¿ä¸ªæ¹æ³åªæ¯ç±å ¬å ± MessageBeep æ¹æ³é´æ¥å ¬å¼ï¼åè æ¥å BeepTypes ç±»åçåæ°ãè¿ä¸ªé´æ¥çé¢å¤å±æ¯ä¸ä¸ªå¾å ³é®çç»èï¼å®æä¾äºä»¥ä¸å¥½å¤ãé¦å ï¼åºè¯¥å¨ç±»åºä¸å¼å ¥ä¸ä¸ªæªæ¥ç beep æ管æ¹æ³ï¼å¯ä»¥éå¤å°éè¿å ¬å ± MessageBeep æ¹æ³æ¥ä½¿ç¨æ管 API ï¼èä¸å¿ æ´æ¹åºç¨ç¨åºä¸çå ¶ä½ä»£ç ã  该å è£ æ¹æ³ç第äºä¸ªå¥½å¤æ¯ï¼å½æ¨è¿è¡ P/Invoke è°ç¨æ¶ï¼æ¨æ¾å¼äºå å访é®å²çªåå ¶ä»ä½çº§ç ´åçæå©ï¼è¿é常æ¯ç± CLR æä¾çãç¼å²æ¹æ³å¯ä»¥ä¿æ¤æ¨çåºç¨ç¨åºçå ¶ä½é¨åå å访é®å²çªå类似é®é¢çå½±åï¼å³ä½¿å®ä¸åä»»ä½äºèåªæ¯ä¼ éåæ°ï¼ã该ç¼å²æ¹æ³å°ç± P/Invoke è°ç¨å¼å ¥çä»»ä½æ½å¨çé误æ¬å°åã  å°ç§æå¤é¨æ¹æ³éèå¨å ¬å ±å è£ åé¢ç第ä¸åæ¶ä¹æ¯æåçä¸ä¸ªå¥½å¤æ¯ï¼æä¾äºå该æ¹æ³æ·»å ä¸äºæå°ç CLR æ ·å¼çæºä¼ãä¾å¦ï¼å¨å¾ 1 ä¸ï¼æå° Windows API å½æ°è¿åç Boolean 失败转æ¢ææ´å CLR çå¼å¸¸ãæè¿å®ä¹äºä¸ä¸ªå为 BeepTypes çæ举类åï¼å®çæå对åºäºå该 Windows API ä¸èµ·ä½¿ç¨çå®ä¹å¼ãç±äº C# ä¸æ¯æå®ä¹ï¼å æ¤å¯ä»¥ä½¿ç¨æ管æ举类åæ¥é¿å å¹»æ°åæ´ä¸ªåºç¨ç¨åºä»£ç æ©æ£ã  å è£ æ¹æ³çæåä¸ä¸ªå¥½å¤å¯¹äºç®åç Windows API å½æ°ï¼å¦ MessageBeep ï¼è¯ç¶æ¯å¾®ä¸è¶³éçãä½æ¯å½æ¨å¼å§è°ç¨æ´å¤æçéæ管å½æ°æ¶ï¼æ¨ä¼åç°ï¼æå¨å° Windows API æ ·å¼è½¬æ¢æ对 CLR æ´å å好çæ¹æ³æ带æ¥ç好å¤ä¼è¶æ¥è¶å¤ãè¶æ¯æç®å¨æ´ä¸ªåºç¨ç¨åºä¸éç¨ interop åè½ï¼è¶æ¯åºè¯¥è®¤çå°èèå è£ ç设计ãåæ¶æ认为ï¼å¨éé¢å对象çéæå è£ æ¹æ³ä¸ä½¿ç¨å¯¹ CLR å好çåæ°ä¹å¹¶éä¸å¯ä»¥ã  DLL Import å±æ§  ç°å¨æ¯æ´æ·±å ¥å°è¿è¡æ¢è®¨çæ¶åäºãå¨å¯¹æ管代ç è¿è¡ P/Invoke è°ç¨æ¶ï¼ DllImportAttribute ç±»åæ®æ¼çéè¦çè§è²ã DllImportAttribute ç主è¦ä½ç¨æ¯ç» CLR æ示åªä¸ª DLL 导åºæ¨æ³è¦è°ç¨çå½æ°ãç¸å ³ DLL çå称被ä½ä¸ºä¸ä¸ªæé å½æ°åæ°ä¼ éç» DllImportAttribute ã  å¦ææ¨æ æ³è¯å®åªä¸ª DLL å®ä¹äºæ¨è¦ä½¿ç¨ç Windows API å½æ°ï¼ Platform SDK ææ¡£å°ä¸ºæ¨æä¾æ好ç帮å©èµæºãå¨ Windows API å½æ°ä¸»é¢æå临è¿ç»å°¾çä½ç½®ï¼ SDK ææ¡£æå®äº C åºç¨ç¨åºè¦ä½¿ç¨è¯¥å½æ°å¿ é¡»é¾æ¥ç .lib æ件ãå¨å ä¹ææçæ åµä¸ï¼è¯¥ .lib æä»¶å ·æä¸å®ä¹è¯¥å½æ°çç³»ç» DLL æ件ç¸åçå称ãä¾å¦ï¼å¦æ该å½æ°éè¦ C åºç¨ç¨åºé¾æ¥å° Kernel32.lib ï¼å该å½æ°å°±å®ä¹å¨ Kernel32.dll ä¸ãæ¨å¯ä»¥å¨ MessageBeep ä¸æ¾å°æå ³ MessageBeep ç Platform SDK æ档主é¢ãå¨è¯¥ä¸»é¢ç»å°¾å¤ï¼æ¨ä¼æ³¨æå°å®æåºåºæä»¶æ¯ User32.lib ï¼è¿è¡¨æ MessageBeep æ¯ä» User32.dll ä¸å¯¼åºçã  å¯éç DllImportAttribute å±æ§  é¤äºæåºå®¿ä¸» DLL å¤ï¼ DllImportAttribute è¿å å«äºä¸äºå¯éå±æ§ï¼å ¶ä¸å个ç¹å«æè¶£ï¼ EntryPoint ã CharSet ã SetLastError å CallingConvention ã  EntryPoint å¨ä¸å¸æå¤é¨æ管æ¹æ³å ·æä¸ DLL 导åºç¸åçå称çæ åµä¸ï¼å¯ä»¥è®¾ç½®è¯¥å±æ§æ¥æ示导åºç DLL å½æ°çå ¥å£ç¹å称ãå½æ¨å®ä¹ä¸¤ä¸ªè°ç¨ç¸åéæ管å½æ°çå¤é¨æ¹æ³æ¶ï¼è¿ç¹å«æç¨ãå¦å¤ï¼å¨ Windows ä¸è¿å¯ä»¥éè¿å®ä»¬çåºå·å¼ç»å®å°å¯¼åºç DLL å½æ°ãå¦ææ¨éè¦è¿æ ·åï¼å诸å¦â #1âæâ#129âç EntryPoint å¼æ示 DLL ä¸éæ管å½æ°çåºå·å¼èä¸æ¯å½æ°åã  CharSet 对äºå符éï¼å¹¶éææçæ¬ç Windows é½æ¯åæ ·å建çã Windows 9x ç³»å产å缺å°éè¦ç Unicode æ¯æï¼è Windows NT å Windows CE ç³»ååä¸å¼å§å°±ä½¿ç¨ Unicode ãå¨è¿äºæä½ç³»ç»ä¸è¿è¡ç CLR å° Unicode ç¨äº String å Char æ°æ®çå é¨è¡¨ç¤ºãä½ä¹ä¸å¿ æ å¿ â å½è°ç¨ Windows 9x API å½æ°æ¶ï¼ CLR ä¼èªå¨è¿è¡å¿ è¦ç转æ¢ï¼å°å ¶ä» Unicode 转æ¢ä¸º ANSI ã  å¦æ DLL å½æ°ä¸ä»¥ä»»ä½æ¹å¼å¤çææ¬ï¼åå¯ä»¥å¿½ç¥ DllImportAttribute ç CharSet å±æ§ãç¶èï¼å½ Char æ String æ°æ®æ¯çå¼çä¸é¨åæ¶ï¼åºè¯¥å° CharSet å±æ§è®¾ç½®ä¸º CharSet.Auto ãè¿æ ·å¯ä»¥ä½¿ CLR æ ¹æ®å®¿ä¸» OS 使ç¨éå½çå符éãå¦æ没ææ¾å¼å°è®¾ç½® CharSet å±æ§ï¼åå ¶é»è®¤å¼ä¸º CharSet.Ansi ãè¿ä¸ªé»è®¤å¼æ¯æ缺ç¹çï¼å 为对äºå¨ Windows 2000 ã Windows XP å Windows NT? ä¸è¿è¡ç interop è°ç¨ï¼å®ä¼æ¶æå°å½±åææ¬åæ°å°éå¤ççæ§è½ã  åºè¯¥æ¾å¼å°éæ© CharSet.Ansi æ CharSet.Unicode ç CharSet å¼èä¸æ¯ä½¿ç¨ CharSet.Auto çå¯ä¸æ åµæ¯ï¼æ¨æ¾å¼å°æå®äºä¸ä¸ªå¯¼åºå½æ°ï¼è该å½æ°ç¹å®äºè¿ä¸¤ç§ Win32 OS ä¸çæä¸ç§ã ReadDirectoryChangesW API å½æ°å°±æ¯è¿æ ·çä¸ä¸ªä¾åï¼å®åªåå¨äºåºäº Windows NT çæä½ç³»ç»ä¸ï¼å¹¶ä¸åªæ¯æ Unicode ï¼å¨è¿ç§æ åµä¸ï¼æ¨åºè¯¥æ¾å¼å°ä½¿ç¨ CharSet.Unicode ã  ææ¶ï¼ Windows API æ¯å¦æå符éå ³ç³»å¹¶ä¸ææ¾ãä¸ç§å³ä¸ä¼æéç确认æ¹æ³æ¯å¨ Platform SDK ä¸æ£æ¥è¯¥å½æ°ç C è¯è¨å¤´æ件ãï¼å¦ææ¨æ æ³è¯å®è¦çåªä¸ªå¤´æ件ï¼åå¯ä»¥æ¥ç Platform SDK ææ¡£ä¸ååºçæ¯ä¸ª API å½æ°ç头æ件ãï¼å¦ææ¨åç°è¯¥ API å½æ°ç¡®å®å®ä¹ä¸ºä¸ä¸ªæ å°å°ä»¥ A æ W ç»å°¾çå½æ°åçå®ï¼åå符éä¸æ¨å°è¯è°ç¨çå½æ°æå ³ç³»ã Windows API å½æ°çä¸ä¸ªä¾åæ¯å¨ WinUser.h ä¸å£°æç GetMessage API ï¼æ¨ä¹è®¸ä¼æ讶å°åç°å®æ A å W 两ç§çæ¬ã  SetLastError é误å¤çé常éè¦ï¼ä½å¨ç¼ç¨æ¶ç»å¸¸è¢«éå¿ãå½æ¨è¿è¡ P/Invoke è°ç¨æ¶ï¼ä¹ä¼é¢ä¸´å ¶ä»çææ â å¤çæ管代ç ä¸ Windows API é误å¤çåå¼å¸¸ä¹é´çåºå«ãæå¯ä»¥ç»æ¨ä¸ç¹å»ºè®®ã  å¦ææ¨æ£å¨ä½¿ç¨ P/Invoke è°ç¨ Windows API å½æ°ï¼è对äºè¯¥å½æ°ï¼æ¨ä½¿ç¨ GetLastError æ¥æ¥æ¾æ©å±çé误信æ¯ï¼ååºè¯¥å¨å¤é¨æ¹æ³ç DllImportAttribute ä¸å° SetLastError å±æ§è®¾ç½®ä¸º true ãè¿éç¨äºå¤§å¤æ°å¤é¨æ¹æ³ã  è¿ä¼å¯¼è´ CLR å¨æ¯æ¬¡è°ç¨å¤é¨æ¹æ³ä¹åç¼åç± API å½æ°è®¾ç½®çé误ãç¶åï¼å¨å è£ æ¹æ³ä¸ï¼å¯ä»¥éè¿è°ç¨ç±»åºç System.Runtime.InteropServices.Marshal ç±»åä¸å®ä¹ç Marshal.GetLastWin32Error æ¹æ³æ¥è·åç¼åçé误å¼ãæç建议æ¯æ£æ¥è¿äºæææ¥èª API å½æ°çé误å¼ï¼å¹¶ä¸ºè¿äºå¼å¼åä¸ä¸ªå¯æç¥çå¼å¸¸ã对äºå ¶ä»ææ失败æ åµï¼å æ¬æ ¹æ¬å°±æ²¡ææå°ç失败æ åµï¼ï¼åå¼åå¨ System.ComponentModel å½å空é´ä¸å®ä¹ç Win32Exception ï¼å¹¶å° Marshal.GetLastWin32Error è¿åçå¼ä¼ éç»å®ãå¦ææ¨å头çä¸ä¸å¾ 1 ä¸ç代ç ï¼æ¨ä¼çå°æå¨ extern MessageBeep æ¹æ³çå ¬å ±å è£ ä¸å°±éç¨äºè¿ç§æ¹æ³ã  CallingConvention æå°å¨æ¤ä»ç»çæåä¹å¯è½æ¯æä¸éè¦çä¸ä¸ª DllImportAttribute å±æ§æ¯ CallingConvention ãéè¿æ¤å±æ§ï¼å¯ä»¥ç» CLR æ示åºè¯¥å°åªç§å½æ°è°ç¨çº¦å®ç¨äºå æ ä¸çåæ°ã CallingConvention.Winapi çé»è®¤å¼æ¯æ好çéæ©ï¼å®å¨å¤§å¤æ°æ åµä¸é½å¯è¡ãç¶èï¼å¦æ该è°ç¨ä¸èµ·ä½ç¨ï¼åå¯ä»¥æ£æ¥ Platform SDK ä¸ç声æ头æ件ï¼ççæ¨è°ç¨ç API å½æ°æ¯å¦æ¯ä¸ä¸ªä¸ç¬¦åè°ç¨çº¦å®æ åçå¼å¸¸ API ã  é常ï¼æ¬æºå½æ°ï¼ä¾å¦ Windows API å½æ°æ C- è¿è¡æ¶ DLL å½æ°ï¼çè°ç¨çº¦å®æè¿°äºå¦ä½å°åæ°æ¨å ¥çº¿ç¨å æ æä»çº¿ç¨å æ ä¸æ¸ é¤ã大å¤æ° Windows API å½æ°é½æ¯é¦å å°å½æ°çæåä¸ä¸ªåæ°æ¨å ¥å æ ï¼ç¶åç±è¢«è°ç¨çå½æ°è´è´£æ¸ ç该å æ ãç¸åï¼è®¸å¤ C- è¿è¡æ¶ DLL å½æ°é½è¢«å®ä¹ä¸ºæç §æ¹æ³åæ°å¨æ¹æ³ç¾åä¸åºç°ç顺åºå°å ¶æ¨å ¥å æ ï¼å°å æ æ¸ çå·¥ä½äº¤ç»è°ç¨è ã  幸è¿çæ¯ï¼è¦è®© P/Invoke è°ç¨å·¥ä½åªéè¦è®©å¤å´è®¾å¤ç解è°ç¨çº¦å®å³å¯ãé常ï¼ä»é»è®¤å¼ CallingConvention.Winapi å¼å§æ¯æ好çéæ©ãç¶åï¼å¨ C è¿è¡æ¶ DLL å½æ°åå°æ°å½æ°ä¸ï¼å¯è½éè¦å°çº¦å®æ´æ¹ä¸º CallingConvention.Cdecl ã  æ°æ®å°éå¤ç  æ°æ®å°éå¤çæ¯ P/Invoke å ·ææææ§çæ¹é¢ãå½å¨æ管åéæ管代ç ä¹é´ä¼ éæ°æ®æ¶ï¼ CLR éµå¾ªè®¸å¤è§åï¼å¾å°æå¼å人åä¼ç»å¸¸éå°å®ä»¬ç´è³å¯å°è¿äºè§åè®°ä½ãé¤éæ¨æ¯ä¸åç±»åºå¼å人åï¼å¦åå¨é常æ åµä¸æ²¡æå¿ è¦ææ¡å ¶ç»èã为äºæææå°å¨ CLR ä¸ä½¿ç¨ P/Invoke ï¼å³ä½¿åªå¶å°éè¦ interop çåºç¨ç¨åºå¼å人åä»ç¶åºè¯¥ç解æ°æ®å°éå¤ççä¸äºåºç¡ç¥è¯ã  å¨æ¬æä¸æ çå©ä½é¨åä¸ï¼æå°è®¨è®ºç®åæ°ååå符串æ°æ®çæ°æ®å°éå¤çãæå°ä»æåºæ¬çæ°åæ°æ®å°éå¤çå¼å§ï¼ç¶åä»ç»ç®åçæéå°éå¤çåå符串å°éå¤çã  å°éæ°ååé»è¾æ é  Windows OS 大é¨åæ¯ç¨ C ç¼åçãå æ¤ï¼ Windows API æç¨å°çæ°æ®ç±»åè¦ä¹æ¯ C ç±»åï¼è¦ä¹æ¯éè¿ç±»åå®ä¹æå®å®ä¹éæ°æ è®°ç C ç±»åã让æ们çç没ææéçæ°æ®å°éå¤çãç®åèµ·è§ï¼é¦å éç¹è®¨è®ºçæ¯æ°ååå¸å°å¼ã  å½éè¿å¼å Windows API å½æ°ä¼ éåæ°æ¶ï¼éè¦ç¥é以ä¸é®é¢ççæ¡ï¼  ? æ°æ®ä»æ ¹æ¬ä¸è®²æ¯æ´åçè¿æ¯æµ®ç¹åçï¼ Â ? å¦ææ°æ®æ¯æ´åçï¼åå®æ¯æ符å·çè¿æ¯æ 符å·çï¼ Â ? å¦ææ°æ®æ¯æ´åçï¼åå®çä½æ°æ¯å¤å°ï¼  ? å¦ææ°æ®æ¯æµ®ç¹åçï¼åå®æ¯å精度çè¿æ¯å精度çï¼ Â Â ææ¶çæ¡å¾ææ¾ï¼ä½ææ¶å´ä¸ææ¾ã Windows API 以åç§æ¹å¼éæ°å®ä¹äºåºæ¬ç C æ°æ®ç±»åãå¾ 2 ååºäº C å Win32 çä¸äºå ¬å ±æ°æ®ç±»ååå ¶è§èï¼ä»¥åä¸ä¸ªå ·æå¹é è§èçå ¬å ±è¯è¨è¿è¡åºç±»åã  é常ï¼åªè¦æ¨éæ©ä¸ä¸ªå ¶è§èä¸è¯¥åæ°ç Win32 ç±»åç¸å¹é ç CLR ç±»åï¼æ¨ç代ç å°±è½å¤æ£å¸¸å·¥ä½ãä¸è¿ä¹æä¸äºç¹ä¾ãä¾å¦ï¼å¨ Windows API ä¸å®ä¹ç BOOL ç±»åæ¯ä¸ä¸ªæ符å·ç 32 ä½æ´åãç¶èï¼ BOOL ç¨äºæ示 Boolean å¼ true æ false ãè½ç¶æ¨ä¸ç¨å° BOOL åæ°ä½ä¸º System.Int32 å¼å°éï¼ä½æ¯å¦æä½¿ç¨ System.Boolean ç±»åï¼å°±ä¼è·å¾æ´åéçæ å°ãå符类åçæ å°ç±»ä¼¼äº BOOL ï¼å 为æä¸ä¸ªç¹å®ç CLR ç±»å (System.Char) æåºå符çå«ä¹ã  å¨äºè§£è¿äºä¿¡æ¯ä¹åï¼éæ¥ä»ç»ç¤ºä¾å¯è½æ¯æ帮å©çãä¾ç¶éç¨ beep 主é¢ä½ä¸ºä¾åï¼è®©æ们æ¥è¯ä¸ä¸ Kernel32.dll ä½çº§ Beep ï¼å®ä¼éè¿è®¡ç®æºçæ¬å£°å¨åçå声ãè¿ä¸ªæ¹æ³ç Platform SDK ææ¡£å¯ä»¥å¨ Beep ä¸æ¾å°ãæ¬æº API æ以ä¸æ¹å¼è¿è¡è®°å½ï¼  BOOL Beep(  DWORD dwFreq,     // Frequency  DWORD dwDuration  // Duration in milliseconds );  å¨åæ°å°éå¤çæ¹é¢ï¼æ¨çå·¥ä½æ¯äºè§£ä»ä¹ CLR æ°æ®ç±»åä¸ Beep API å½æ°æ使ç¨ç DWORD å BOOL æ°æ®ç±»åç¸å ¼å®¹ãå顾ä¸ä¸å¾ 2 ä¸çå¾è¡¨ï¼æ¨å°çå° DWORD æ¯ä¸ä¸ª 32 ä½çæ 符å·æ´æ°å¼ï¼å¦å CLR ç±»å System.UInt32 ãè¿æå³çæ¨å¯ä»¥ä½¿ç¨ UInt32 å¼ä½ä¸ºéå¾ Beep ç两个åæ°ã BOOL è¿åå¼æ¯ä¸ä¸ªé常æ趣çæ åµï¼å 为该å¾è¡¨åè¯æ们ï¼å¨ Win32 ä¸ï¼ BOOL æ¯ä¸ä¸ª 32 ä½çæ符å·æ´æ°ãå æ¤ï¼æ¨å¯ä»¥ä½¿ç¨ System.Int32 å¼ä½ä¸ºæ¥èª Beep çè¿åå¼ãç¶èï¼ CLR ä¹å®ä¹äº System.Boolean ç±»åä½ä¸º Boolean å¼çè¯ä¹ï¼æ以åºè¯¥ä½¿ç¨å®æ¥æ¿ä»£ã CLR é»è®¤å° System.Boolean å¼å°é为 32 ä½çæ符å·æ´æ°ãæ¤å¤ææ¾ç¤ºçå¤é¨æ¹æ³å®ä¹æ¯ç¨äº Beep çç»æ P/Invoke æ¹æ³ï¼  [DllImport("Kernel32.dll", SetLastError=true)] static extern Boolean Beep(   UInt32 frequency, UInt32 duration);  æéåæ° Â è®¸å¤ Windows API å½æ°å°æéä½ä¸ºå®ä»¬çä¸ä¸ªæå¤ä¸ªåæ°ãæéå¢å äºå°éæ°æ®çå¤ææ§ï¼å 为å®ä»¬å¢å äºä¸ä¸ªé´æ¥å±ãå¦æ没ææéï¼æ¨å¯ä»¥éè¿å¼å¨çº¿ç¨å æ ä¸ä¼ éæ°æ®ãæäºæéï¼åå¯ä»¥éè¿å¼ç¨ä¼ éæ°æ®ï¼æ¹æ³æ¯å°è¯¥æ°æ®çå åå°åæ¨å ¥çº¿ç¨å æ ä¸ãç¶åï¼å½æ°éè¿å åå°åé´æ¥è®¿é®æ°æ®ã使ç¨æ管代ç 表示æ¤éå é´æ¥å±çæ¹å¼æå¤ç§ã Â å¨ C# ä¸ï¼å¦æå°æ¹æ³åæ°å®ä¹ä¸º ref æ out ï¼åæ°æ®éè¿å¼ç¨èä¸æ¯éè¿å¼ä¼ éãå³ä½¿æ¨æ²¡æä½¿ç¨ Interop ä¹æ¯è¿æ ·ï¼ä½åªæ¯ä»ä¸ä¸ªæ管æ¹æ³è°ç¨å°å¦ä¸ä¸ªæ管æ¹æ³ãä¾å¦ï¼å¦æéè¿ ref ä¼ é System.Int32 åæ°ï¼åå¨çº¿ç¨å æ ä¸ä¼ éçæ¯è¯¥æ°æ®çå°åï¼èä¸æ¯æ´æ°å¼æ¬èº«ãä¸é¢æ¯ä¸ä¸ªå®ä¹ä¸ºéè¿å¼ç¨æ¥æ¶æ´æ°å¼çæ¹æ³ç示ä¾ï¼  void FlipInt32(ref Int32 num){   num = -num; }  è¿éï¼ FlipInt32 æ¹æ³è·åä¸ä¸ª Int32 å¼çå°åã访é®æ°æ®ã对å®æ±åï¼ç¶åå°æ±åè¿çå¼èµç»åå§åéãå¨ä»¥ä¸ä»£ç ä¸ï¼ FlipInt32 æ¹æ³ä¼å°è°ç¨ç¨åºçåé x çå¼ä» 10 æ´æ¹ä¸º -10 ï¼ Â Int32 x = 10; FlipInt32(ref x);  å¨æ管代ç ä¸å¯ä»¥éç¨è¿ç§è½åï¼å°æéä¼ éç»éæ管代ç ãä¾å¦ï¼ FileEncryptionStatus API å½æ°ä»¥ 32 ä½æ 符å·ä½æ©ç çå½¢å¼è¿åæ件å å¯ç¶æã该 API æ以ä¸æ示æ¹å¼è¿è¡è®°å½ï¼  BOOL FileEncryptionStatus(  LPCTSTR lpFileName, // file name  LPDWORD lpStatus    // encryption status );  请注æï¼è¯¥å½æ°å¹¶ä¸ä½¿ç¨å®çè¿åå¼è¿åç¶æï¼èæ¯è¿åä¸ä¸ª Boolean å¼ï¼æ示è°ç¨æ¯å¦æåãå¨æåçæ åµä¸ï¼å®é çç¶æå¼æ¯éè¿ç¬¬äºä¸ªåæ°è¿åçãå®çå·¥ä½æ¹å¼æ¯è°ç¨ç¨åºå该å½æ°ä¼ éæåä¸ä¸ª DWORD åéçæéï¼è该 API å½æ°ç¨ç¶æå¼å¡«å æåçå åä½ç½®ã以ä¸ä»£ç ç段æ¾ç¤ºäºä¸ä¸ªè°ç¨éæ管 FileEncryptionStatus å½æ°çå¯è½å¤é¨æ¹æ³å®ä¹ï¼  [DllImport("Advapi32.dll", CharSet=CharSet.Auto)] static extern Boolean FileEncryptionStatus(String filename,   out UInt32 status);  该å®ä¹ä½¿ç¨ out å ³é®åæ¥ä¸º UInt32 ç¶æå¼æ示 by-ref åæ°ãè¿éæä¹å¯ä»¥éæ© ref å ³é®åï¼å®é ä¸å¨è¿è¡æ¶ä¼äº§çç¸åçæºå¨ç ã out å ³é®ååªæ¯ä¸ä¸ª by-ref åæ°çè§èï¼å®å C# ç¼è¯å¨æ示æä¼ éçæ°æ®åªå¨è¢«è°ç¨çå½æ°å¤é¨ä¼ éãç¸åï¼å¦æä½¿ç¨ ref å ³é®åï¼åç¼è¯å¨ä¼åå®æ°æ®å¯ä»¥å¨è¢«è°ç¨çå½æ°çå é¨åå¤é¨ä¼ éã  æ管代ç ä¸ out å ref åæ°çå¦ä¸ä¸ªå¾å¥½çæ¹é¢æ¯ï¼å°åä½ä¸º by-ref åæ°ä¼ éçåéå¯ä»¥æ¯çº¿ç¨å æ ä¸çä¸ä¸ªæ¬å°åéãä¸ä¸ªç±»æç»æçå ç´ ï¼ä¹å¯ä»¥æ¯å ·æåéæ°æ®ç±»åçæ°ç»ä¸çä¸ä¸ªå ç´ å¼ç¨ãè°ç¨ç¨åºçè¿ç§çµæ´»æ§ä½¿å¾ by-ref åæ°æ为å°éç¼å²åºæé以ååæ°å¼æéçä¸ä¸ªå¾å¥½çèµ·ç¹ãåªæå¨æåç° ref æ out åæ°ä¸ç¬¦åæçéè¦çæ åµä¸ï¼ææä¼èèå°æéå°é为æ´å¤æç CLR ç±»åï¼ä¾å¦ç±»ææ°ç»å¯¹è±¡ï¼ã  å¦ææ¨ä¸çæ C è¯æ³æè è°ç¨ Windows API å½æ°ï¼ææ¶å¾é¾ç¥éä¸ä¸ªæ¹æ³åæ°æ¯å¦éè¦æéãä¸ä¸ªå¸¸è§çæ示符æ¯çåæ°ç±»åæ¯å¦æ¯ä»¥åæ¯ P æ LP å¼å¤´çï¼ä¾å¦ LPDWORD æ PINT ãå¨è¿ä¸¤ä¸ªä¾åä¸ï¼ LP å P æ示åæ°æ¯ä¸ä¸ªæéï¼èå®ä»¬æåçæ°æ®ç±»ååå«ä¸º DWORD æ INT ãç¶èï¼å¨æäºæ åµä¸ï¼å¯ä»¥ç´æ¥ä½¿ç¨ C è¯è¨è¯æ³ä¸çæå· (*) å° API å½æ°å®ä¹ä¸ºæéã以ä¸ä»£ç ç段å±ç¤ºäºè¿æ¹é¢ç示ä¾ï¼  void TakesAPointer(DWORD* pNum);  å¯ä»¥çå°ï¼ä¸è¿°å½æ°çå¯ä¸ä¸ä¸ªåæ°æ¯æå DWORD åéçæéã  å½éè¿ P/Invoke å°éæéæ¶ï¼ ref å out åªç¨äºæ管代ç ä¸çå¼ç±»åãå½ä¸ä¸ªåæ°ç CLR ç±»åä½¿ç¨ struct å ³é®åå®ä¹æ¶ï¼å¯ä»¥è®¤ä¸ºè¯¥åæ°æ¯ä¸ä¸ªå¼ç±»åã Out å ref ç¨äºå°éæåè¿äºæ°æ®ç±»åçæéï¼å 为é常å¼ç±»ååéæ¯å¯¹è±¡ææ°æ®ï¼èå¨æ管代ç ä¸å¹¶æ²¡æ对å¼ç±»åçå¼ç¨ãç¸åï¼å½å°éå¼ç¨ç±»å对象æ¶ï¼å¹¶ä¸éè¦ ref å out å ³é®åï¼å 为åéå·²ç»æ¯å¯¹è±¡çå¼ç¨äºã  å¦ææ¨å¯¹å¼ç¨ç±»ååå¼ç±»åä¹é´çå·®å«ä¸æ¯å¾çæï¼è¯·æ¥é 2000 å¹´ 12 æ åè¡ç MSDN? Magazine ï¼å¨ .NET ä¸æ ç主é¢ä¸å¯ä»¥æ¾å°æ´å¤ä¿¡æ¯ã大å¤æ° CLR ç±»åé½æ¯å¼ç¨ç±»åï¼ç¶èï¼é¤äº System.String å System.Object ï¼ææçåºå ç±»åï¼ä¾å¦ System.Int32 å System.Boolean ï¼é½æ¯å¼ç±»åã  å°éä¸éæ (Opaque) æéï¼ä¸ç§ç¹æ®æ åµ Â ææ¶å¨ Windows API ä¸ï¼æ¹æ³ä¼ éæè¿åçæéæ¯ä¸éæçï¼è¿æå³ç该æéå¼ä»ææ¯è§åº¦è®²æ¯ä¸ä¸ªæéï¼ä½ä»£ç å´ä¸ç´æ¥ä½¿ç¨å®ãç¸åï¼ä»£ç å°è¯¥æéè¿åç» Windows 以便éåè¿è¡éç¨ã  ä¸ä¸ªé常常è§çä¾åå°±æ¯å¥æçæ¦å¿µãå¨ Windows ä¸ï¼å é¨æ°æ®ç»æï¼ä»æ件å°å±å¹ä¸çæé®ï¼å¨åºç¨ç¨åºä»£ç ä¸é½è¡¨ç¤ºä¸ºå¥æãå¥æå ¶å®å°±æ¯ä¸éæçæéææçæé宽度çæ°å¼ï¼åºç¨ç¨åºç¨å®æ¥è¡¨ç¤ºå é¨ç OS æé ã  å°æ°æ åµä¸ï¼ API å½æ°ä¹å°ä¸éææéå®ä¹ä¸º PVOID æ LPVOID ç±»åãå¨ Windows API çå®ä¹ä¸ï¼è¿äºç±»åææå°±æ¯è¯´è¯¥æé没æç±»åã  å½ä¸ä¸ªä¸éææéè¿åç»æ¨çåºç¨ç¨åºï¼æè æ¨çåºç¨ç¨åºææå¾å°ä¸ä¸ªä¸éææéï¼æ¶ï¼æ¨åºè¯¥å°åæ°æè¿åå¼å°é为 CLR ä¸çä¸ç§ç¹æ®ç±»å â System.IntPtr ãå½æ¨ä½¿ç¨ IntPtr ç±»åæ¶ï¼é常ä¸ä½¿ç¨ out æ ref åæ°ï¼å 为 IntPtr æ为ç´æ¥æææéãä¸è¿ï¼å¦ææ¨å°ä¸ä¸ªæéå°é为ä¸ä¸ªæéï¼å对 IntPtr ä½¿ç¨ by-ref åæ°æ¯åéçã Â å¨ CLR ç±»åç³»ç»ä¸ï¼ System.IntPtr ç±»åæä¸ä¸ªç¹æ®çå±æ§ãä¸åç³»ç»ä¸çå ¶ä»åºç±»åï¼ IntPtr 并没æåºå®ç大å°ãç¸åï¼å®å¨è¿è¡æ¶ç大å°æ¯ä¾åºå±æä½ç³»ç»çæ£å¸¸æé大å°èå®çãè¿æå³çå¨ 32 ä½ç Windows ä¸ï¼ IntPtr åéçå®½åº¦æ¯ 32 ä½çï¼èå¨ 64 ä½ç Windows ä¸ï¼å®æ¶ç¼è¯å¨ç¼è¯ç代ç ä¼å° IntPtr å¼çä½ 64 ä½çå¼ãå½å¨æ管代ç åéæ管代ç ä¹é´å°éä¸éææéæ¶ï¼è¿ç§èªå¨è°è大å°çç¹ç¹ååæç¨ã  请记ä½ï¼ä»»ä½è¿åææ¥åå¥æç API å½æ°å ¶å®æä½çå°±æ¯ä¸éææéãæ¨ç代ç åºè¯¥å° Windows ä¸çå¥æå°éæ System.IntPtr å¼ã  æ¨å¯ä»¥å¨æ管代ç ä¸å° IntPtr å¼å¼ºå¶è½¬æ¢ä¸º 32 ä½æ 64 ä½çæ´æ°å¼ï¼æå°åè 强å¶è½¬æ¢ä¸ºåè ãç¶èï¼å½ä½¿ç¨ Windows API å½æ°æ¶ï¼å 为æéåºæ¯ä¸éæçï¼æ以é¤äºåå¨åä¼ éç»å¤é¨æ¹æ³å¤ï¼ä¸è½å°å®ä»¬å¦åå®ç¨ãè¿ç§âåªéåå¨åä¼ éâè§åç两个ç¹ä¾æ¯å½æ¨éè¦åå¤é¨æ¹æ³ä¼ é null æéå¼åéè¦æ¯è¾ IntPtr å¼ä¸ null å¼çæ åµã为äºåå°è¿ä¸ç¹ï¼æ¨ä¸è½å°é¶å¼ºå¶è½¬æ¢ä¸º System.IntPtr ï¼èåºè¯¥å¨ IntPtr ç±»åä¸ä½¿ç¨ Int32.Zero éæå ¬å ±å段ï¼ä»¥ä¾¿è·å¾ç¨äºæ¯è¾æèµå¼ç null å¼ã  å°éææ¬ Â å¨ç¼ç¨æ¶ç»å¸¸è¦å¯¹ææ¬æ°æ®è¿è¡å¤çãææ¬ä¸º interop å¶é äºä¸äºéº»ç¦ï¼è¿æ两个åå ãé¦å ï¼åºå±æä½ç³»ç»å¯è½ä½¿ç¨ Unicode æ¥è¡¨ç¤ºå符串ï¼ä¹å¯è½ä½¿ç¨ ANSI ãå¨æå°æ°æ åµä¸ï¼ä¾å¦ MultiByteToWideChar API å½æ°ç两个åæ°å¨å符éä¸æ¯ä¸ä¸è´çã  第äºä¸ªåå æ¯ï¼å½éè¦è¿è¡ P/Invoke æ¶ï¼è¦å¤çææ¬è¿éè¦ç¹å«äºè§£å° C å CLR å¤çææ¬çæ¹å¼æ¯ä¸åçãå¨ C ä¸ï¼å符串å®é ä¸åªæ¯ä¸ä¸ªå符å¼æ°ç»ï¼é常以 null ä½ä¸ºç»æ符ã大å¤æ° Windows API å½æ°æ¯æç §ä»¥ä¸æ¡ä»¶å¤çå符串çï¼å¯¹äº ANSI ï¼å°å ¶ä½ä¸ºå符å¼æ°ç»ï¼å¯¹äº Unicode ï¼å°å ¶ä½ä¸ºå®½å符å¼æ°ç»ã  幸è¿çæ¯ï¼ CLR 被设计å¾ç¸å½çµæ´»ï¼å½å°éææ¬æ¶é®é¢å¾ä»¥è½»æ¾è§£å³ï¼èä¸ç¨å¨æ Windows API å½æ°ææä»æ¨çåºç¨ç¨åºå¾å°çæ¯ä»ä¹ãè¿éæ¯ä¸äºéè¦è®°ä½ç主è¦èèäºé¡¹ï¼  ? æ¯æ¨çåºç¨ç¨åºå API å½æ°ä¼ éææ¬æ°æ®ï¼è¿æ¯ API å½æ°åæ¨çåºç¨ç¨åºè¿åå符串æ°æ®ï¼æè äºè å ¼æï¼ Â ? æ¨çå¤é¨æ¹æ³åºè¯¥ä½¿ç¨ä»ä¹æ管类åï¼ Â ? API å½æ°ææå¾å°çæ¯ä»ä¹æ ¼å¼çéæ管åç¬¦ä¸²ï¼ Â Â æ们é¦å 解çæåä¸ä¸ªé®é¢ã大å¤æ° Windows API å½æ°é½å¸¦æ LPTSTR æ LPCTSTR å¼ãï¼ä»å½æ°è§åº¦çï¼å®ä»¬åå«æ¯å¯ä¿®æ¹åä¸å¯ä¿®æ¹çç¼å²åºï¼å å«ä»¥ null ç»æçå符æ°ç»ãâ C â代表常æ°ï¼æå³ç使ç¨è¯¥åæ°ä¿¡æ¯ä¸ä¼ä¼ éå°å½æ°å¤é¨ã LPTSTR ä¸çâ T â表æ该åæ°å¯ä»¥æ¯ Unicode æ ANSI ï¼åå³äºæ¨éæ©çå符éååºå±æä½ç³»ç»çå符éãå ä¸ºå¨ Windows API ä¸å¤§å¤æ°å符串åæ°é½æ¯è¿ä¸¤ç§ç±»åä¹ä¸ï¼æ以åªè¦å¨ DllImportAttribute ä¸éæ© CharSet.Auto ï¼ CLR å°±æé»è®¤çæ¹å¼å·¥ä½ã  ç¶èï¼æäº API å½æ°æèªå®ä¹ç DLL å½æ°éç¨ä¸åçæ¹å¼è¡¨ç¤ºå符串ãå¦ææ¨è¦ç¨å°ä¸ä¸ªè¿æ ·çå½æ°ï¼å°±å¯ä»¥éç¨ MarshalAsAttribute 修饰å¤é¨æ¹æ³çå符串åæ°ï¼å¹¶ææä¸ç§ä¸åäºé»è®¤ LPTSTR çåç¬¦ä¸²æ ¼å¼ãæå ³ MarshalAsAttribute çæ´å¤ä¿¡æ¯ï¼è¯·åé ä½äº MarshalAsAttribute Class ç Platform SDK æ档主é¢ã  ç°å¨è®©æ们çä¸ä¸å符串信æ¯å¨æ¨ç代ç åéæ管å½æ°ä¹é´ä¼ éçæ¹åãæ两ç§æ¹å¼å¯ä»¥ç¥éå¤çå符串æ¶ä¿¡æ¯çä¼ éæ¹åã第ä¸ä¸ªä¹æ¯æå¯é çä¸ä¸ªæ¹æ³å°±æ¯é¦å ç解åæ°çç¨éãä¾å¦ï¼æ¨æ£è°ç¨ä¸ä¸ªåæ°ï¼å®çå称类似 CreateMutex 并带æä¸ä¸ªå符串ï¼åå¯ä»¥æ³å该å符串信æ¯æ¯ä»åºç¨ç¨åºå API å½æ°ä¼ éçãåæ¶ï¼å¦ææ¨è°ç¨ GetUserName ï¼å该å½æ°çå称表æå符串信æ¯æ¯ä»è¯¥å½æ°åæ¨çåºç¨ç¨åºä¼ éçã  é¤äºè¿ç§æ¯è¾åççæ¹æ³å¤ï¼ç¬¬äºç§æ¥æ¾ä¿¡æ¯ä¼ éæ¹åçæ¹å¼å°±æ¯æ¥æ¾ API åæ°ç±»åä¸çåæ¯â C âãä¾å¦ï¼ GetUserName API å½æ°ç第ä¸ä¸ªåæ°è¢«å®ä¹ä¸º LPTSTR ç±»åï¼å®ä»£è¡¨ä¸ä¸ªæå Unicode æ ANSI å符串ç¼å²åºçé¿æéãä½æ¯ CreateMutex çå称åæ°è¢«ç±»åå为 LTCTSTR ã请注æï¼è¿éçç±»åå®ä¹æ¯ä¸æ ·çï¼ä½å¢å ä¸ä¸ªåæ¯â C âæ¥è¡¨æç¼å²åºä¸ºå¸¸æ°ï¼ API å½æ°ä¸è½åå ¥ã  ä¸æ¦æç¡®äºææ¬åæ°æ¯åªç¨ä½è¾å ¥è¿æ¯ç¨ä½è¾å ¥ / è¾åºï¼å°±å¯ä»¥ç¡®å®ä½¿ç¨åªç§ CLR ç±»åä½ä¸ºåæ°ç±»åãè¿éæä¸äºè§åãå¦æå符串åæ°åªç¨ä½è¾å ¥ï¼åä½¿ç¨ System.String ç±»åãå¨æ管代ç ä¸ï¼å符串æ¯ä¸åçï¼éåç¨äºä¸ä¼è¢«æ¬æº API å½æ°æ´æ¹çç¼å²åºã  å¦æå符串åæ°å¯ä»¥ç¨ä½è¾å ¥å / æè¾åºï¼åä½¿ç¨ System.StringBuilder ç±»åã StringBuilder ç±»åæ¯ä¸ä¸ªå¾æç¨çç±»åºç±»åï¼å®å¯ä»¥å¸®å©æ¨ææå°æ建å符串ï¼ä¹æ£å¥½å¯ä»¥å°ç¼å²åºä¼ éç»æ¬æºå½æ°ï¼ç±æ¬æºå½æ°ä¸ºæ¨å¡«å å符串æ°æ®ãä¸æ¦å½æ°è°ç¨è¿åï¼æ¨åªéè¦è°ç¨ StringBuilder 对象ç ToString å°±å¯ä»¥å¾å°ä¸ä¸ª String 对象ã  GetShortPathName API å½æ°è½å¾å¥½å°ç¨äºæ¾ç¤ºä»ä¹æ¶åä½¿ç¨ String ãä»ä¹æ¶åä½¿ç¨ StringBuilder ï¼å 为å®åªå¸¦æä¸ä¸ªåæ°ï¼ä¸ä¸ªè¾å ¥å符串ãä¸ä¸ªè¾åºå符串åä¸ä¸ªææè¾åºç¼å²åºçå符é¿åº¦çåæ°ã Â å¾ 3 æ示为å 注éçéæ管 GetShortPathName å½æ°ææ¡£ï¼å®åæ¶æåºäºè¾å ¥åè¾åºå符串åæ°ãå®å¼åºäºæ管çå¤é¨æ¹æ³å®ä¹ï¼ä¹å¦å¾ 3 æ示ã请注æ第ä¸ä¸ªåæ°è¢«å°é为 System.String ï¼å 为å®æ¯ä¸ä¸ªåªç¨ä½è¾å ¥çåæ°ã第äºä¸ªåæ°ä»£è¡¨ä¸ä¸ªè¾åºç¼å²åºï¼å®ä½¿ç¨äº System.StringBuilder ã  å°ç»  æ¬æä¸æ æä»ç»ç P/Invoke åè½è¶³å¤è°ç¨ Windows ä¸çè®¸å¤ API å½æ°ãç¶èï¼å¦ææ¨å¤§éç¨å° interop ï¼åä¼æç»åç°èªå·±å°éäºå¾å¤æçæ°æ®ç»æï¼çè³å¯è½éè¦å¨æ管代ç ä¸éè¿æéç´æ¥è®¿é®å åãå®é ä¸ï¼æ¬æºä»£ç ä¸ç interop å¯ä»¥æ¯ä¸ä¸ªå°ç»èåä½çº§æ¯ç¹èå¨éé¢ççæ£çæ½å¤æçåã CLR ã C# åæ管 C++ æä¾äºè®¸å¤æç¨çåè½ï¼ä¹è®¸ä»¥åæä¼å¨æ¬ä¸æ ä»ç»é«çº§ç P/Invoke è¯é¢ã  åæ¶ï¼åªè¦æ¨è§å¾ .NET Framework ç±»åºæ æ³ææ¾æ¨ç声é³æè 为æ¨æ§è¡å ¶ä»ä¸äºåè½ï¼æ¨å¯ä»¥ç¥éå¦ä½ååå§èä¼ç§ç Windows API 寻æ±ä¸äºå¸®å©ã  API( åºç¨ç¼ç¨æ¥å£ ) æ¯ç¨åºä¸å¤çå¨æ¥å£çå½ä»¤éãæ常ç¨çå°±æ¯å¨å¤é¨è°ç¨å¾®è½¯ WINDOWS å é¨çè¿ç¨ã WINDOWS API å æ¬æåçä½ å¯ä»¥ä½¿ç¨çå½æ°ãç»æã常éãè¿äºå½æ°æ¯ç¨ C è¯è¨åçï¼å¨ä½¿ç¨ä»ä»¬ä¹åï¼ä½ å¿ é¡»å£°æã å®ä¹ Dll çè¿ç¨å°ç¸å½çå¤æï¼çè³æ¯ VB è¿å¤æãä½ å¯ä»¥ä½¿ç¨ API Viewer å·¥å ·å¾å° API å½æ°ç声æï¼ä½æ¯å¿ 须注æçæ¯ï¼å®çåæ°ç±»åè· C# çä¸ä¸æ ·ã 大é¨åçé«çº§è¯è¨é½æ¯æ API ï¼å¾®è½¯å½æ°ç±»åº (MFC) å°è£ äºå¤§é¨åç Win32 API ã ODBC API 对æé«æ°æ®åºçæä½é度大æ好å¤ãä½¿ç¨ API ï¼å¯ä»¥è¯·æ±æ´åºå±çç³»ç»æå¡ã API ä»ç®åç对è¯æ¡å°å¤æçå å¯è¿ç®é½æä¾æ¯æãå¼åè åºè¯¥ç¥éå¦ä½å¨ä»ä»¬ç¨åºä¸ä½¿ç¨ API API æ许å¤ç±»åï¼ï¼é对ä¸åçæä½ç³»ç»ãå¤çå¨â¦â¦â¦â¦ï¼ OS specific API: æä½ç³»ç»ç¹æ API: æ¯ç§æä½ç³»ç»é½æä¸å¥å ¬ç¨ API åä¸æ API ãæ¯å¦ï¼ Windows NT æ¯æ MS-DOS, Win16, Win32, POSIX ( 便æºå¼æä½ç³»ç»æ¥å£ ) ï¼ OS/2 console API ï¼åæ¶ Windows 95 supports MS-DOS, Win16 å Win32 API ã Win16 å Win32 API: WIN16 æ¯åºäº 16 ä½çå¤çå¨ï¼å¹¶ä½¿ç¨ 16 ä½çå¼ï¼å®æ¯ä¸ä¸ªç¬ç«çå¹³å°ãæ¯å¦ï¼ä½ å¯ä»¥è¿è¡ TSR ç¨åºå¨ MS-DOS ç¯å¢ä¸ã WIN32 æ¯åºäº 32 ä½çå¤çå¨ï¼å¹¶ä½¿ç¨ 32 ä½çå¼ãä»å¯ç¨äºä»»ä½æä½ç³»ç»ï¼å®ç使ç¨èå´æ´å¹¿ã Win32 API has 32 prefix after the library name e.g. KERNEL32, USER32 etc? Win32 API ç DLL ä¸è¬é½å ·æ 32 çåç¼ï¼æ¯å¦ï¼ KERNEL32, USER32 çã ææç API é½å¨ä¸é¢ 3 个 DLL ä¸å®ç°çã Kernel User GDI 1. KERNEL å®çåºåæ¯ï¼ KERNEL32.DLL ï¼å®æ¯æä½ç³»ç»ç®¡çç API é Process loading. å è½½è¿ç¨ Context switching. File I/O. æ件æä½ Memory management. å å管ç æ¯å¦ï¼ GlobalMemoryStatus å½æ°è·å¾ç®åç³»ç»ç©çèæå åç使ç¨ä¿¡æ¯ã 2. USER å¨ WIN32 ä¸ï¼å®çåºåæ¯ USER32.DLL This allows managing the entire user interfaces such as å®ç®¡çå ¨é¨çç¨æ·çé¢ï¼æ¯å¦ï¼ Windows çªå£ Menus èå Dialog Boxes 对è¯æ¡ Icons etc., å¾æ ç æ¯å¦ï¼ DrawIcon ç»ä¸ä¸ªå¾æ å¨æå®ç设å¤ä¸ã 3. GDI (Graphical Device Interface) è¿ä¸ª DLL æ¯ GDI32.dll ï¼å®è´è´£å¾åçè¾åºï¼ä½¿ç¨ GDI ç»åºçªå£ï¼èåï¼å¯¹è¯æ¡ It can create Graphical Output. è¾åºå¾å æ¯å¦ï¼ CreateBitmap å½æ°å建ä¸ä¸ªæå®å®½åº¦ãé«åº¦åé¢è²æ ¼å¼çä½å¾ã C# ä¸ API çå·¥å ·å¯¹åå¦è æ¯ç¸å½ä¸éçãå¨ C# 使ç¨ä¸ä½¿ç¨ API ä¹åï¼ä½ åºè¯¥å ç¥é C# ä¸å¦ä½ä½¿ç¨ç»æãç±»å转æ¢ï¼å®å ¨ä¸ä¸å®å ¨ä»£ç çã 使ç¨å¤æç api ä¹åï¼æ们å ç¨ä¸ä¸ªç®åç MessageBox API ä½ä¸ºååãæå¼ä¸ä¸ª C# å·¥ç¨ï¼å¢å ä¸ä¸ªæé®ï¼å¨æé®çç¹å»äºä»¶ä¸ï¼æ们å°æ¾ç¤ºä¸ä¸ªä¿¡æ¯æ¡ã å¢å 使ç¨å¤é¨åºçå½å空é´ï¼ using System.Runtime.InteropServices; ä¸é¢å£°æ API [DllImport("User32.dll")] DllImport å±æ§ç¨æ¥æå®å å«å¤é¨æ¹æ³çå¨æè¿æ¥åºçä½ç½®ã "User32.dll" æåºäºåºåï¼ static ææå®ä¸å±äºç¹å®ç对象ã extern æææ¯ä¸ä¸ªå¤é¨çæ¹æ³ã带æ DllImport å±æ§çæ¹æ³å¿ 须带æ修饰符 extern ã MessageBox æ¯ä¸ä¸ªæ±æ°åï¼å¸¦å个åæ°è¿åä¸ä¸ª int åå¼ã è®¸å¤ API 使ç¨ç»ææ¥ä¼ éãè¿ååæ°ï¼è¿æ ·å¯ä»¥åå°å¤æ度ãå®ä¹å 许使ç¨è±¡ MessageBox å½æ°é£æ ·ï¼ä½¿ç¨åºå®çåæ°ã  å¨æé®çç¹å»äºä»¶ä¸å¢å ä¸é¢ä»£ç ï¼ protected void button1_Click (object sender, System.EventArgs e) { MessageBox (0,"API Message Box","API Demo",0); } ç¼è¯å¹¶è¿è¡ç¨åºï¼ç¹å»æé®ä»¥åï¼ä½ å°±å¯ä»¥çå°ä¸ä¸ªç± API è°ç¨çä¿¡æ¯æ¡ã Using structure 使ç¨ç»æ API ä¸ç»å¸¸ä½¿ç¨å¤æçç»æãä¸è¿ä¸æ¦ä½ æç½äºä»ä»¬ï¼å°æ¯å¾ç®åçã In next example we will use GetSystemInfo API which returns information about the current system. ä¸é¢çååï¼æä»¬ç¨ GetSystemInfo API å¾å°å½åç³»ç»çä¿¡æ¯ã 第ä¸æ¥ï¼å¢å ä¸ä¸ª C# çªå£ï¼å¹¶å¨ä¸é¢å¢å ä¸ä¸ªæé®ï¼å¨çªå£ä»£ç 页å¢å ä¸ä¸ªå½å空é´ï¼ using System.Runtime.InteropServices; 声æ GetSystemInfo çåæ°ç»æ : [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; } 声æ API å½æ°ï¼ [DllImport("kernel32")] static extern void GetSystemInfo(ref SYSTEM_INFO pSI); ref æ¯ä¸ä¸ªæ å¿åéä¼ éå½¢å¼çå ³é®åï¼å®ä½¿ä¼ å ¥ä¼ åºçåéæååä¸ä¸ªåéï¼ä¼ åä¼ éï¼ å¨æé®ç¹å»äºä»¶ä¸å¢å ä¸é¢ç代ç ï¼ protected void button1_Click (object sender, System.EventArgs e) { try { SYSTEM_INFO pSI = new SYSTEM_INFO(); GetSystemInfo(ref pSI); Once you retrieve the structure perform operations on required parameter æ¯å¦ï¼ listBox1.Items.Insert(0,pSI.dwActiveProcessorMask.ToString()); } catch(Exception er) { MessageBox.Show (er.Message); } } Â Â ç¨ Visual C# è°ç¨ Windows API å½æ°  å京æºæ¢°å·¥ä¸å¦é¢ç 00 çº§ï¼ 100085 ï¼åæä» Â Â Â Â Â Api å½æ°æ¯æç Windws åºç¨ç¨åºçåºç³ï¼æ¯ä¸ç§ Windows åºç¨ç¨åºå¼åå·¥å ·ï¼å®æä¾çåºå±å½æ°é½é´æ¥æç´æ¥å°è°ç¨äº Windows API å½æ°ï¼åæ¶ä¸ºäºå®ç°åè½æ©å±ï¼ä¸è¬ä¹é½æä¾äºè°ç¨ WindowsAPI å½æ°çæ¥å£ï¼ ä¹å°±æ¯è¯´å ·å¤è°ç¨å¨æè¿æ¥åºçè½åã Visual C# åå ¶å®å¼åå·¥å ·ä¸æ ·ä¹è½å¤è°ç¨å¨æé¾æ¥åºç API å½æ°ã .NET æ¡æ¶æ¬èº«æä¾äºè¿æ ·ä¸ç§æå¡ , å 许å管è¾ç代ç è°ç¨å¨æé¾æ¥åºä¸å®ç°çéå管è¾å½æ° , å æ¬æä½ç³»ç»æä¾ç Windows API å½æ°ãå®è½å¤å®ä½åè°ç¨è¾åºå½æ° , æ ¹æ®éè¦ï¼ç»ç»å ¶å个åæ° ( æ´åãå符串类åãæ°ç»ãåç»æçç ) è·¨è¶äºæä½è¾¹çã  ä¸é¢ä»¥ C# 为ä¾ç®åä»ç»è°ç¨ API çåºæ¬è¿ç¨ï¼  å¨æé¾æ¥åºå½æ°ç声æ  ãå¨æé¾æ¥åºå½æ°ä½¿ç¨åå¿ é¡»å£°æï¼ç¸å¯¹äº VB,C# å½æ°å£°ææ¾å¾æ´å ç½å¦ï¼åè éè¿ Api Viewer ç²è´´ä»¥åï¼å¯ä»¥ç´æ¥ä½¿ç¨ï¼èåè åéè¦å¯¹åæ°ä½äºé¢å¤çååå·¥ä½ã  ãå¨æé¾æ¥åºå½æ°å£°æé¨åä¸è¬ç±ä¸å两é¨åç»æï¼ä¸æ¯å½æ°åæç´¢å¼å·ï¼äºæ¯å¨æé¾æ¥åºçæ件åã  ã è¬å¦ï¼ä½ æ³è°ç¨ User32.DLL ä¸ç MessageBox å½æ°ï¼æä»¬å¿ é¡»ææå½æ°çåå MessageBoxA æ MessageBoxW ï¼ä»¥ååºåå User32.dll, æ们ç¥é Win32 API 对æ¯ä¸ä¸ªæ¶åå符串åå符çå½æ°ä¸è¬é½åå¨ä¸¤ä¸ªçæ¬ï¼ååèå符ç ANSI çæ¬åååèå符ç UNICODE çæ¬ã  ãä¸é¢æ¯ä¸ä¸ªè°ç¨ API å½æ°çä¾åï¼ Â [DllImport("KERNEL32.DLL", EntryPoint="MoveFileW", SetLastError=true, CharSet=CharSet.Unicode, ExactSpelling=true, CallingConvention=CallingConvention.StdCall)] public static extern bool MoveFile(String src, String dst);  ãå ¶ä¸å ¥å£ç¹ EntryPoint æ è¯å½æ°å¨å¨æé¾æ¥åºçå ¥å£ä½ç½®ï¼å¨ä¸ä¸ªå管è¾çå·¥ç¨ä¸ï¼ç®æ å½æ°çåå§ååååºå·å ¥å£ç¹ä¸ä» æ è¯ä¸ä¸ªè·¨è¶äºæä½çéçå½æ°ãèä¸ï¼ä½ è¿å¯ä»¥æè¿ä¸ªå ¥å£ç¹æ å°ä¸ºä¸ä¸ªä¸åçååï¼ä¹å°±æ¯å¯¹å½æ°è¿è¡éå½åãéå½åå¯ä»¥ç»è°ç¨å½æ°å¸¦æ¥ç§ç§ä¾¿å©ï¼éè¿éå½åï¼ä¸æ¹é¢æ们ä¸ç¨ä¸ºå½æ°ç大å°å伤éèçï¼åæ¶å®ä¹å¯ä»¥ä¿è¯ä¸å·²æçå½åè§åä¿æä¸è´ï¼å 许带æä¸ååæ°ç±»åçå½æ°å ±åï¼æ´éè¦çæ¯å®ç®åäºå¯¹ ANSI å Unicode çæ¬çè°ç¨ã CharSet ç¨äºæ è¯å½æ°è°ç¨æéç¨çæ¯ Unicode ææ¯ ANSI çæ¬ï¼ ExactSpelling ï¼ false å°åè¯ç¼è¯å¨ , 让ç¼è¯å¨å³å®ä½¿ç¨ Unicode æè æ¯ Ansi çæ¬ãå ¶å®çåæ°è¯·åè MSDN å¨çº¿å¸®å© .  ãå¨ C# ä¸ï¼ä½ å¯ä»¥å¨ EntryPoint åéè¿ååååºå·å£°æä¸ä¸ªå¨æé¾æ¥åºå½æ°ï¼å¦æå¨æ¹æ³å®ä¹ä¸ä½¿ç¨çå½æ°åä¸ DLL å ¥å£ç¹ç¸åï¼ä½ ä¸éè¦å¨ EntryPoint åæ¾ç¤ºå£°æå½æ°ãå¦åï¼ä½ å¿ é¡»ä½¿ç¨ä¸åå±æ§æ ¼å¼æ示ä¸ä¸ªååååºå·ã  [DllImport("dllname", EntryPoint="Functionname")] [DllImport("dllname", EntryPoint="#123")] å¼å¾æ³¨æçæ¯ï¼ä½ å¿ é¡»å¨æ°ååºå·åå âï¼â  ä¸é¢æ¯ä¸ä¸ªç¨ MsgBox æ¿æ¢ MessageBox ååçä¾åï¼ Â [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); } 许å¤å管è¾çå¨æé¾æ¥åºå½æ°ææä½ è½å¤ä¼ éä¸ä¸ªå¤æçåæ°ç±»åç»å½æ°ï¼è¬å¦ä¸ä¸ªç¨æ·å®ä¹çç»æç±»åæåæè å管è¾ä»£ç å®ä¹çä¸ä¸ªç±»æåï¼è¿æ¶ä½ å¿ é¡»æä¾é¢å¤çä¿¡æ¯æ ¼å¼åè¿ä¸ªç±»åï¼ä»¥ä¿æåæ°åæçå¸å±å对é½ã  C# æä¾äºä¸ä¸ª StructLayoutAttribute ç±»ï¼éè¿å®ä½ å¯ä»¥å®ä¹èªå·±çæ ¼å¼åç±»åï¼å¨å管è¾ä»£ç ä¸ï¼æ ¼å¼åç±»åæ¯ä¸ä¸ªç¨ StructLayoutAttribute 说æçç»ææç±»æåï¼éè¿å®è½å¤ä¿è¯å ¶å é¨æåé¢æçå¸å±ä¿¡æ¯ãå¸å±çéé¡¹å ±æä¸ç§ï¼  å¸å±é项  æè¿°  LayoutKind.Automatic 为äºæé«æçå 许è¿è¡æ对类åæåéæ°æåºã  注æï¼æ°¸è¿ä¸è¦ä½¿ç¨è¿ä¸ªé项æ¥è°ç¨ä¸å管è¾çå¨æé¾æ¥åºå½æ°ã  LayoutKind.Explicit 对æ¯ä¸ªåæç § FieldOffset å±æ§å¯¹ç±»åæåæåº Â LayoutKind.Sequential 对åºç°å¨å管è¾ç±»åå®ä¹å°æ¹çä¸å管è¾å åä¸çç±»åæåè¿è¡æåºã Â ä¼ éç»ææå  ä¸é¢çä¾å说æå¦ä½å¨å管è¾ä»£ç ä¸å®ä¹ä¸ä¸ªç¹åç©å½¢ç±»åï¼å¹¶ä½ä¸ºä¸ä¸ªåæ°ä¼ éç» User32.dll åºä¸ç PtInRect å½æ°ï¼  å½æ°çä¸å管è¾åå声æå¦ä¸ï¼  BOOL PtInRect(const RECT *lprc, POINT pt); 注æä½ å¿ é¡»éè¿å¼ç¨ä¼ é Rect ç»æåæ°ï¼å 为å½æ°éè¦ä¸ä¸ª Rect çç»ææéã  [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 PtInRect(ref Rect r, Point p); }Â ç±»ä¼¼ä½ å¯ä»¥è°ç¨ GetSystemInfo å½æ°è·å¾ç³»ç»ä¿¡æ¯ï¼  ? 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);  类æåçä¼ é  åæ ·åªè¦ç±»å ·æä¸ä¸ªåºå®çç±»æåå¸å±ï¼ä½ ä¹å¯ä»¥ä¼ éä¸ä¸ªç±»æåç»ä¸ä¸ªä¸å管è¾çå¨æé¾æ¥åºå½æ°ï¼ä¸é¢çä¾å主è¦è¯´æå¦ä½ä¼ éä¸ä¸ª sequential 顺åºå®ä¹ç MySystemTime ç±»ç» User32.dll ç GetSystemTime å½æ° , å½æ°ç¨ C/C++ è°ç¨è§èå¦ä¸ :  void GetSystemTime(SYSTEMTIME* SystemTime); ä¸åä¼ å¼ç±»å , ç±»æ»æ¯éè¿å¼ç¨ä¼ éåæ° . [C#] [StructLayout(LayoutKind.Sequential)] public class MySystemTime { public ushort wYear; public ushort wMonth; public ushort wDayOfWeek; public ushort wDay; public ushort wHour; public ushort wMinute; public ushort wSecond; public ushort wMilliseconds; } class Win32API { [DllImport("User32.dll")] public static extern void GetSystemTime(MySystemTime st); } åè°å½æ°çä¼ é : ä»å管è¾ç代ç ä¸è°ç¨å¤§å¤æ°å¨æé¾æ¥åºå½æ° , ä½ åªéå建ä¸ä¸ªå管è¾çå½æ°å®ä¹ï¼ç¶åè°ç¨å®å³å¯ , è¿ä¸ªè¿ç¨é常ç´æ¥ã  å¦æä¸ä¸ªå¨æé¾æ¥åºå½æ°éè¦ä¸ä¸ªå½æ°æéä½ä¸ºåæ°ï¼ä½ è¿éè¦å以ä¸å æ¥ï¼  é¦å ï¼ä½ å¿ é¡»åèæå ³è¿ä¸ªå½æ°çææ¡£ï¼ç¡®å®è¿ä¸ªå½æ°æ¯å¦éè¦ä¸ä¸ªåè°ï¼ç¬¬äºï¼ä½ å¿ é¡»å¨å管è¾ä»£ç ä¸å建ä¸ä¸ªåè°å½æ°ï¼æåï¼ä½ å¯ä»¥ææåè¿ä¸ªå½æ°çæéä½ä¸ºä¸ä¸ªåæ°åéç» DLL å½æ° ,.  åè°å½æ°åå ¶å®ç° : åè°å½æ°ç»å¸¸ç¨å¨ä»»å¡éè¦éå¤æ§è¡çåºå , è¬å¦ç¨äºæ举å½æ° , è¬å¦ Win32 API ä¸ç EnumFontFamilies( åä½æ举 ), EnumPrinters( æå°æº ), EnumWindows ( çªå£æ举 ) å½æ° . ä¸é¢ä»¥çªå£æä¸¾ä¸ºä¾ , è°è°å¦ä½éè¿è°ç¨ EnumWindow å½æ°éåç³»ç»ä¸åå¨çææçªå£  åä¸é¢å 个æ¥éª¤ : 1. å¨å®ç°è°ç¨åå åèå½æ°ç声æ  BOOL EnumWindows(WNDENUMPROC lpEnumFunc, LPARMAM IParam) æ¾ç¶è¿ä¸ªå½æ°éè¦ä¸ä¸ªåè°å½æ°å°åä½ä¸ºåæ° . 2. å建ä¸ä¸ªå管è¾çåè°å½æ° , è¿ä¸ªä¾å声æ为代表类å (delegate), ä¹å°±æ¯æ们æ说çåè° , å®å¸¦æ两个åæ° hwnd å lparam, 第ä¸ä¸ªåæ°æ¯ä¸ä¸ªçªå£å¥æï¼ç¬¬äºä¸ªåæ°ç±åºç¨ç¨åºå®ä¹ï¼ä¸¤ä¸ªåæ°å为æ´å½¢ã  ããå½è¿ä¸ªåè°å½æ°è¿åä¸ä¸ªéé¶å¼æ¶ï¼æ 示æ§è¡æåï¼é¶åæ示失败ï¼è¿ä¸ªä¾åæ»æ¯è¿å True å¼ï¼ä»¥ä¾¿æç»æ举ã  3. æåå建以代表对象 (delegate) ï¼å¹¶æå®ä½ä¸ºä¸ä¸ªåæ°ä¼ éç» EnumWindows å½æ°ï¼å¹³å°ä¼èªå¨å° æ代表转åæå½æ°è½å¤è¯å«çåè°æ ¼å¼ã  [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(" çªå£å¥æ为 "); Console.WriteLine(hwnd); return true; } }  æéç±»ååæ°ä¼ éï¼ Â ãå¨ Windows API å½æ°è°ç¨æ¶ï¼å¤§é¨åå½æ°éç¨æéä¼ éåæ°ï¼å¯¹ä¸ä¸ªç»æåéæéï¼æ们é¤äºä½¿ç¨ä¸é¢çç±»åç»ææ¹æ³ä¼ éåæ°ä¹å¤ï¼æ们ææ¶è¿å¯ä»¥éç¨æ°ç»ä¼ éåæ°ã  ãä¸é¢è¿ä¸ªå½æ°éè¿è°ç¨ GetUserName è·å¾ç¨æ·å  BOOL GetUserName( LPTSTR lpBuffer, // ç¨æ·åç¼å²åº  LPDWORD nSize // åæ¾ç¼å²åºå¤§å°çå°åæé  ); ã  [DllImport("Advapi32.dll", EntryPoint="GetComputerName", ExactSpelling=false, SetLastError=true)] static extern bool GetComputerName ( [MarshalAs(UnmanagedType.LPArray)] byte[] lpBuffer, ã [MarshalAs(UnmanagedType.LPArray)] Int32[] nSize ); ãè¿ä¸ªå½æ°æ¥å两个åæ°ï¼ char * å int *, å ä¸ºä½ å¿ é¡»åé ä¸ä¸ªå符串ç¼å²åºä»¥æ¥åå符串æéï¼ä½ å¯ä»¥ä½¿ç¨ String 类代æ¿è¿ä¸ªåæ°ç±»åï¼å½ç¶ä½ è¿å¯ä»¥å£°æä¸ä¸ªåèæ°ç»ä¼ é ANSI å符串ï¼åæ ·ä½ ä¹å¯ä»¥å£°æä¸ä¸ªåªæä¸ä¸ªå ç´ çé¿æ´åæ°ç»ï¼ä½¿ç¨æ°ç»åä½ä¸ºç¬¬äºä¸ªåæ°ãä¸é¢çå½æ°å¯ä»¥è°ç¨å¦ä¸ï¼  byte[] str=new byte[20]; Int32[] len=new Int32[1]; len[0]=20; GetComputerName (str,len); MessageBox.Show(System.Text.Encoding.ASCII.GetString(str)); ãæåéè¦æéçæ¯ï¼æ¯ä¸ç§æ¹æ³ä½¿ç¨åå¿ é¡»å¨æ件头å ä¸ï¼  ã using System.Runtime.InteropServices;Â è½¬è½½ï¼ http://www.cnblogs.com/zhangxianfeng/archive/2010/03/18/1689134.html åè http://www.cnblogs.com/cltsq/articles/api.html