最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

C#中調(diào)用Windows API的技術(shù)要點(diǎn)說明

 更新時(shí)間:2014年01月22日 09:58:45   作者:  
本篇文章主要是對C#中調(diào)用Windows API的技術(shù)要點(diǎn)進(jìn)行了詳細(xì)的介紹,需要的朋友可以過來參考下,希望對大家有所幫助

在.Net Framework SDK文檔中,關(guān)于調(diào)用Windows API的指示比較零散,并且其中稍全面一點(diǎn)的是針對Visual Basic .net講述的。本文將C#中調(diào)用API的要點(diǎn)匯集如下,希望給未在C#中使用過API的朋友一點(diǎn)幫助。另外如果安裝了Visual Studio .net的話,在C:\Program Files\Microsoft Visual Studio .NET\FrameworkSDK\Samples\Technologies\Interop\PlatformInvoke\WinAPIs\CS目錄下有大量的調(diào)用API的例子。

一、調(diào)用格式

復(fù)制代碼 代碼如下:

 using System.Runtime.InteropServices; //引用此名稱空間,簡化后面的代碼
...
//使用DllImportAttribute特性來引入api函數(shù),注意聲明的是空方法,即方法體為空。
[DllImport("user32.dll")]
public static extern ReturnType FunctionName(type arg1,type arg2,...);
//調(diào)用時(shí)與調(diào)用其他方法并無區(qū)別

可以使用字段進(jìn)一步說明特性,用逗號隔開,如:
復(fù)制代碼 代碼如下:

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

DllImportAttribute特性的公共字段如下:
1、CallingConvention 指示向非托管實(shí)現(xiàn)傳遞方法參數(shù)時(shí)所用的 CallingConvention 值。
CallingConvention.Cdecl : 調(diào)用方清理堆棧。它使您能夠調(diào)用具有 varargs 的函數(shù)。
CallingConvention.StdCall : 被調(diào)用方清理堆棧。它是從托管代碼調(diào)用非托管函數(shù)的默認(rèn)約定。

2、CharSet 控制調(diào)用函數(shù)的名稱版本及指示如何向方法封送 String 參數(shù)。

此字段被設(shè)置為 CharSet 值之一。如果 CharSet 字段設(shè)置為 Unicode,則所有字符串參數(shù)在傳遞到非托管實(shí)現(xiàn)之前都轉(zhuǎn)換成 Unicode 字符。這還導(dǎo)致向 DLL EntryPoint 的名稱中追加字母“W”。如果此字段設(shè)置為 Ansi,則字符串將轉(zhuǎn)換成 ANSI 字符串,同時(shí)向 DLL EntryPoint 的名稱中追加字母“A”。

大多數(shù) Win32 API 使用這種追加“W”或“A”的約定。如果 CharSet 設(shè)置為 Auto,則這種轉(zhuǎn)換就是與平臺(tái)有關(guān)的(在 Windows NT 上為 Unicode,在 Windows 98 上為 Ansi)。CharSet 的默認(rèn)值為 Ansi。CharSet 字段也用于確定將從指定的 DLL 導(dǎo)入哪個(gè)版本的函數(shù)。

CharSet.Ansi 和 CharSet.Unicode 的名稱匹配規(guī)則大不相同。對于 Ansi 來說,如果將 EntryPoint 設(shè)置為“MyMethod”且它存在的話,則返回“MyMethod”。如果 DLL 中沒有“MyMethod”,但存在“MyMethodA”,則返回“MyMethodA”。

對于 Unicode 來說則正好相反。如果將 EntryPoint 設(shè)置為“MyMethod”且它存在的話,則返回“MyMethodW”。如果 DLL 中不存在“MyMethodW”,但存在“MyMethod”,則返回“MyMethod”。如果使用的是 Auto,則匹配規(guī)則與平臺(tái)有關(guān)(在 Windows NT 上為 Unicode,在 Windows 98 上為 Ansi)。如果 ExactSpelling 設(shè)置為 true,則只有當(dāng) DLL 中存在“MyMethod”時(shí)才返回“MyMethod”。

3、EntryPoint 指示要調(diào)用的 DLL 入口點(diǎn)的名稱或序號。
如果你的方法名不想與api函數(shù)同名的話,一定要指定此參數(shù),例如:

復(fù)制代碼 代碼如下:

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

4、ExactSpelling 指示是否應(yīng)修改非托管 DLL 中的入口點(diǎn)的名稱,以與 CharSet 字段中指定的 CharSet 值相對應(yīng)。如果為 true,則當(dāng) DllImportAttribute.CharSet 字段設(shè)置為 CharSet 的 Ansi 值時(shí),向方法名稱中追加字母 A,當(dāng) DllImportAttribute.CharSet 字段設(shè)置為 CharSet 的 Unicode 值時(shí),向方法的名稱中追加字母 W。此字段的默認(rèn)值是 false。

5、PreserveSig 指示托管方法簽名不應(yīng)轉(zhuǎn)換成返回 HRESULT、并且可能有一個(gè)對應(yīng)于返回值的附加 [out, retval] 參數(shù)的非托管簽名。

6、SetLastError 指示被調(diào)用方在從屬性化方法返回之前將調(diào)用 Win32 API SetLastError。 true 指示調(diào)用方將調(diào)用 SetLastError,默認(rèn)為 false。運(yùn)行時(shí)封送拆收器將調(diào)用 GetLastError 并緩存返回的值,以防其被其他 API 調(diào)用重寫。用戶可通過調(diào)用 GetLastWin32Error 來檢索錯(cuò)誤代碼。

二、參數(shù)類型:

1、數(shù)值型直接用對應(yīng)的就可。(DWORD -> int , WORD -> Int16)
2、API中字符串指針類型 -> .net中string
3、API中句柄 (dWord)  -> .net中IntPtr
4、API中結(jié)構(gòu)   -> .net中結(jié)構(gòu)或者類。注意這種情況下,要先用StructLayout特性限定聲明結(jié)構(gòu)或類

公共語言運(yùn)行庫利用StructLayoutAttribute控制類或結(jié)構(gòu)的數(shù)據(jù)字段在托管內(nèi)存中的物理布局,即類或結(jié)構(gòu)需要按某種方式排列。如果要將類傳遞給需要指定布局的非托管代碼,則顯式控制類布局是重要的。它的構(gòu)造函數(shù)中用LayoutKind值初始化 StructLayoutAttribute 類的新實(shí)例。 LayoutKind.Sequential 用于強(qiáng)制將成員按其出現(xiàn)的順序進(jìn)行順序布局。

LayoutKind.Explicit 用于控制每個(gè)數(shù)據(jù)成員的精確位置。利用 Explicit, 每個(gè)成員必須使用 FieldOffsetAttribute 指示此字段在類型中的位置。如:

復(fù)制代碼 代碼如下:

 [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結(jié)構(gòu),在.net中定義對應(yīng)類或結(jié)構(gòu)的例子:
復(fù)制代碼 代碼如下:

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

 //.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中聲明為結(jié)構(gòu)
[ StructLayout( LayoutKind.Sequential )] 
public struct OSVersionInfo2
{
public int OSVersionInfoSize;
public int majorVersion;
public int minorVersion;
public int buildNumber;
public int platformId;

復(fù)制代碼 代碼如下:

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

此例中用到MashalAs特性,它用于描述字段、方法或參數(shù)的封送處理格式。用它作為參數(shù)前綴并指定目標(biāo)需要的數(shù)據(jù)類型。例如,以下代碼將兩個(gè)參數(shù)作為數(shù)據(jù)類型長指針封送給 Windows API 函數(shù)的字符串 (LPStr):
復(fù)制代碼 代碼如下:

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

注意結(jié)構(gòu)作為參數(shù)時(shí)候,一般前面要加上ref修飾符,否則會(huì)出現(xiàn)錯(cuò)誤:對象的引用沒有指定對象的實(shí)例。
復(fù)制代碼 代碼如下:

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

三、如何保證使用托管對象的平臺(tái)調(diào)用成功?
如果在調(diào)用平臺(tái) invoke 后的任何位置都未引用托管對象,則垃圾回收器可能將完成該托管對象。這將釋放資源并使句柄無效,從而導(dǎo)致平臺(tái)invoke 調(diào)用失敗。用 HandleRef 包裝句柄可保證在平臺(tái) invoke 調(diào)用完成前,不對托管對象進(jìn)行垃圾回收。

例如下面:

復(fù)制代碼 代碼如下:

 FileStream fs = new FileStream( "a.txt", FileMode.Open );
StringBuilder buffer = new StringBuilder( 5 );
int read = 0;
ReadFile(fs.Handle, buffer, 5, out read, 0 ); //調(diào)用Win API中的ReadFile函數(shù)

由于fs是托管對象,所以有可能在平臺(tái)調(diào)用還未完成時(shí)候被垃圾回收站回收。將文件流的句柄用HandleRef包裝后,就能避免被垃圾站回收:
復(fù)制代碼 代碼如下:

 [ 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 );

相關(guān)文章

  • C#9.0:Init相關(guān)總結(jié)

    C#9.0:Init相關(guān)總結(jié)

    這篇文章主要介紹了C#9.0:Init的相關(guān)資料,幫助大家更好的理解和學(xué)習(xí)新版的c#,感興趣的朋友可以了解下
    2021-02-02
  • C#檢測遠(yuǎn)程計(jì)算機(jī)端口是否打開的方法

    C#檢測遠(yuǎn)程計(jì)算機(jī)端口是否打開的方法

    這篇文章主要介紹了C#檢測遠(yuǎn)程計(jì)算機(jī)端口是否打開的方法,實(shí)例分析了C#實(shí)現(xiàn)檢測遠(yuǎn)程端口開啟的技巧,需要的朋友可以參考下
    2015-03-03
  • C#引用類型作為方法的參數(shù)分析

    C#引用類型作為方法的參數(shù)分析

    這篇文章主要介紹了C#引用類型作為方法的參數(shù)分析,以實(shí)例的形式較為詳細(xì)的分析了參數(shù)的傳值問題,需要的朋友可以參考下
    2014-11-11
  • C#基于自定義事件EventArgs實(shí)現(xiàn)發(fā)布訂閱模式

    C#基于自定義事件EventArgs實(shí)現(xiàn)發(fā)布訂閱模式

    這篇文章介紹了C#基于自定義事件EventArgs實(shí)現(xiàn)發(fā)布訂閱模式的方法,文中通過示例代碼介紹的非常詳細(xì)。對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2022-05-05
  • DevExpress的DateEdit設(shè)置顯示日期和時(shí)間的方法

    DevExpress的DateEdit設(shè)置顯示日期和時(shí)間的方法

    本文主要介紹了DevExpress的DateEdit設(shè)置顯示日期和時(shí)間的方法,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2022-08-08
  • C#實(shí)現(xiàn)根據(jù)銀行卡卡號判斷銀行名

    C#實(shí)現(xiàn)根據(jù)銀行卡卡號判斷銀行名

    這篇文章主要介紹了C#實(shí)現(xiàn)根據(jù)銀行卡卡號判斷銀行名,是從其他網(wǎng)友的java程序改編而來,有需要的小伙伴可以參考下。
    2015-07-07
  • Unity3D實(shí)現(xiàn)扭動(dòng)擠壓瀏覽效果

    Unity3D實(shí)現(xiàn)扭動(dòng)擠壓瀏覽效果

    這篇文章主要為大家詳細(xì)介紹了Unity3D實(shí)現(xiàn)扭動(dòng)擠壓瀏覽效果,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2019-02-02
  • C#實(shí)現(xiàn)快遞api接口調(diào)用方法

    C#實(shí)現(xiàn)快遞api接口調(diào)用方法

    這篇文章主要介紹了C#實(shí)現(xiàn)快遞api接口調(diào)用方法,主要是通過快遞API網(wǎng)接口的服務(wù),使用的時(shí)候直接申請個(gè)接口UID即可,有需要的小伙伴來參考下吧。
    2015-03-03
  • 在C#中 webbrowser的使用心得

    在C#中 webbrowser的使用心得

    最近用webbrowser做了個(gè)東西,期間有點(diǎn)小曲折,而且網(wǎng)上的解決方法也基本都是淺嘗輒止,特此在這里發(fā)一下同大家分享。

    2013-04-04
  • C# 生成隨機(jī)數(shù)的代碼

    C# 生成隨機(jī)數(shù)的代碼

    這篇文章主要介紹了C# 生成隨機(jī)數(shù)的代碼的相關(guān)資料,非常的簡單實(shí)用,需要的朋友可以參考下
    2015-03-03

最新評論

高清| 开阳县| 瓮安县| 邹城市| 棋牌| 江川县| 元阳县| 从化市| 福鼎市| 克什克腾旗| 阿鲁科尔沁旗| 无棣县| 石柱| 眉山市| 淳化县| 德安县| 云龙县| 新营市| 凤阳县| 疏附县| 恩施市| 泌阳县| 天门市| 眉山市| 景东| 汾阳市| 商都县| 嘉善县| 瑞安市| 盖州市| 哈尔滨市| 视频| 吐鲁番市| 盘锦市| 微博| 塘沽区| 元谋县| 南充市| 龙泉市| 曲周县| 陆良县|