亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 編程 > C# > 正文

C#中調用Windows API的技術要點說明

2020-01-24 02:50:44
字體:
來源:轉載
供稿:網友

在.Net Framework SDK文檔中,關于調用Windows API的指示比較零散,并且其中稍全面一點的是針對Visual Basic .net講述的。本文將C#中調用API的要點匯集如下,希望給未在C#中使用過API的朋友一點幫助。另外如果安裝了Visual Studio .net的話,在C:/Program Files/Microsoft Visual 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中定義對應類或結構的例子:
復制代碼 代碼如下:

  /**********************************************
* API中定義原結構聲明
* OSVERSIONINFOA STRUCT
*  dwOSVersionInfoSize   DWORD      ?
*  dwMajorVersion        DWORD      ?
*  dwMinorVersion        DWORD      ?
*  dwBuildNumber         DWORD      ?
*  dwPlatformId          DWORD      ?
*  szCSDVersion          BYTE 128 dup (?)
* OSVERSIONINFOA ENDS
*
* OSVERSIONINFO  equ  <OSVERSIONINFOA>
*********************************************/
 
復制代碼 代碼如下:

 //.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 );

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
日本亚洲欧美三级| 第一福利永久视频精品| 97视频在线观看播放| 午夜精品久久久久久久白皮肤| 中文字幕亚洲情99在线| 亚洲护士老师的毛茸茸最新章节| 成人免费高清完整版在线观看| 欧美国产日韩xxxxx| 欧洲美女免费图片一区| 亚洲欧美在线免费观看| 亚洲春色另类小说| 久久天天躁日日躁| 亚洲欧美日韩精品久久奇米色影视| 热久久这里只有| 中文.日本.精品| 秋霞午夜一区二区| 久久6精品影院| 91大神福利视频在线| 久久成年人免费电影| 亚洲剧情一区二区| 国产91久久婷婷一区二区| 欧美成人午夜激情在线| 国产精品美腿一区在线看| 亚洲天堂久久av| 日韩成人av网址| 久久久久久久爱| 中文字幕日韩电影| 亚洲国产女人aaa毛片在线| 精品福利在线视频| 热久久免费国产视频| 精品福利在线观看| 一区二区在线视频播放| 亚洲精品福利在线观看| 日韩精品视频在线观看免费| 国产精品久久久久7777婷婷| 成人福利在线观看| 国产精品久久久久久网站| 久久久久成人网| 亚洲一区二区三区在线免费观看| 美日韩在线视频| 日韩国产高清视频在线| 亚洲国产天堂久久综合网| 亚洲精品一区中文字幕乱码| 久久久久久久久久av| 久久中文字幕视频| 高跟丝袜一区二区三区| 亚洲最大激情中文字幕| 97成人在线视频| 亚洲а∨天堂久久精品9966| 欧美成人精品h版在线观看| 日韩欧美国产黄色| 久久国产精品影视| 亚洲美女喷白浆| 亚洲精品欧美一区二区三区| 国产精品中文在线| 国产精品人人做人人爽| 91亚洲精品一区| 欧美日韩人人澡狠狠躁视频| 久久久视频免费观看| 亚洲free嫩bbb| 国内自拍欧美激情| 亚洲激情视频在线播放| 国产99久久精品一区二区永久免费| 久久影视电视剧凤归四时歌| 尤物yw午夜国产精品视频| 欧美麻豆久久久久久中文| 日韩精品欧美激情| 欧美一级电影久久| 亚洲欧美第一页| 欧美日韩视频在线| 精品一区二区亚洲| 中文字幕亚洲综合久久筱田步美| 久久精品国产亚洲精品2020| 国产精品久久久久久亚洲调教| 国产专区欧美专区| 日韩有码片在线观看| 亚洲国语精品自产拍在线观看| zzijzzij亚洲日本成熟少妇| 日韩一级裸体免费视频| 国产v综合ⅴ日韩v欧美大片| 91久久久亚洲精品| 日韩av中文字幕在线免费观看| 欧美华人在线视频| 中文字幕不卡在线视频极品| 国产精品久久久久久久久粉嫩av| 欧美激情视频一区| 最近中文字幕日韩精品| 亚洲成色www8888| 久久中文字幕在线视频| 国产精品福利在线观看| 国产精品吴梦梦| 热久久免费国产视频| 欧美日韩美女在线| 国产精品大陆在线观看| 性欧美激情精品| 97国产精品人人爽人人做| 久久精品2019中文字幕| 一区二区在线视频| 精品美女国产在线| 欧美大秀在线观看| 国产精品成人aaaaa网站| 国产一区二区三区欧美| 欧美色播在线播放| 亚洲精品中文字幕av| 亚洲色图第一页| 久久久中精品2020中文| 色香阁99久久精品久久久| 亚洲最大福利视频| 亚洲第一免费网站| 亚洲白虎美女被爆操| 国产在线播放91| 日韩电影中文字幕| 亚洲激情视频网站| 久久99久久久久久久噜噜| 欧美一区二区视频97| 大胆欧美人体视频| 国产一区二区三区在线免费观看| 午夜精品99久久免费| 91亚洲精品在线观看| 日本精品久久中文字幕佐佐木| 狠狠综合久久av一区二区小说| 亚洲第一页中文字幕| 国产日韩欧美自拍| 国产精品国产三级国产aⅴ9色| 亚洲国产精品久久久久秋霞蜜臀| 国产成人久久久| 伊人久久五月天| 欧美精品999| 性色av一区二区三区红粉影视| 欧美日韩国产中文精品字幕自在自线| 亚洲色图18p| 日韩小视频网址| 日韩精品极品视频免费观看| 亚洲性生活视频| 中文字幕国产日韩| 成人国产精品色哟哟| 亚洲精品国偷自产在线99热| 日韩久久午夜影院| 亚洲一区www| 精品在线小视频| 亚洲欧洲国产精品| 欧美精品成人91久久久久久久| 亚洲精品一区二区三区不| 久久精品99国产精品酒店日本| 日韩中文字幕国产精品| 一个色综合导航| 狠狠躁夜夜躁人人爽天天天天97| 欧美国产日产韩国视频| 91久久综合亚洲鲁鲁五月天| 亚洲国内高清视频| 国产999精品视频| 国产成人精品av在线| 日本中文字幕不卡免费| 亚洲欧美在线第一页| 亚洲淫片在线视频| 久久精品电影一区二区| 日韩少妇与小伙激情| 亚洲欧美日韩精品| 色午夜这里只有精品| 国产欧美va欧美va香蕉在| 欧美一级免费视频| 亚洲国产精彩中文乱码av在线播放| 亚洲桃花岛网站| 成人免费观看网址|