天天看點

P/Invoke .NET調用win32API

項目:無線無源測溫軟體系統

         項目中,用到使用P/Invoke在.NET調用win32API,實作對ini配置檔案的讀寫功能!因為有一些配置資訊需要儲存下來,以便在下一次啟動程式完成初始化,這實際上是一種類持久化。将  

         一些資訊寫入INI檔案(initialization file)中,可完成簡單的持久化支援。

Windows提供了API接口用于操作INI檔案,其支援的INI檔案格式一般如下:

===============================

[Section1]

Key11=value11

Key12=value12

[Section2]

Key21=value21

Key22=value22

...

[SectionN]

KeyN1=valueN1

KeyN2=valueN2

一般一個INI檔案可有N個節,每節可有n個鍵名及值對應,每個鍵名及其值以等式形式占一行。

一般鍵的名稱可任取,不過建議用有意義的字元及詞構成。值一般可為整數和字元串,其它類型要進行轉換。

常見的系統配置檔案:

C:/boot.ini

C:/WINDOWS/win.ini

C:/WINDOWS/system.ini

C:/WINDOWS/desktop.ini

C:/WINDOWS/Resources/Themes/Windows Classic.theme

注意,字元串存貯在INI檔案中時沒有引号;key和value之間的等号前後不容空格;注釋以分号“;”開頭。

P/Invoke .NET調用win32API
P/Invoke .NET調用win32API

但是令人遺憾的是C#所使用的.NET架構下的公共類庫并沒有提供直接操作INI檔案的類,是以唯一比較理想的方法就是調用API函數。

然後,.Net架構下的類庫是基于托管代碼的,而API函數是基于非托管代碼的,(在運作庫的控制下執行的代碼稱作托管代碼。相反,在運作庫之外運作的代碼稱作非托管代碼。)如何實作托管代碼與非托管代碼之間的操作呢?.Net架構的System.Runtime.InteropServices命名空間下提供各種各樣支援COM interop及平台調用服務的成員,

在受控代碼與非受控代碼進行互動時會産生一個事務(transition) ,這通常發生在使用平台調用服務(Platform Invocation Services),即P/Invoke

平台調用是一種服務,它使托管代碼能夠調用 DLL 中實作的非托管函數,如調用系統的 API 或與 COM 對象打交道,通過 System.Runtime.InteropServices 命名空間

為了從托管代碼中調用非托管的DLL中函數,你要建立一個P/Invoke包裝(Wrapper)。一個P/Invoke包裝是一個.net兼 容的方法聲明,用來建立P/Invoke包裝的文法與建立托管方法的聲明文法本質上是一樣的。唯一不同是P/Invoke包裝不包含函數體,而隻有方法 名、傳回值類型和參數資訊。并且,P/Invoke包裝使用了DllImport屬性。這個屬性是用來定位包含有目标函數的非托管的DLL。

其中最重要的屬性之一DllImportAttribute可以用來定義用于通路非托管API的平台調用方法,它提供了對從非托管DLL導出的函數進行調用所必需的資訊。下面就來看一下如何實作C#與API函數的互操作。

讀操作:

[DllImport("kernel32")]

P/Invoke .NET調用win32API

private static extern int GetPrivateProfileString(string section, string key, string defVal, StringBuilder retVal, int size, string filePath); 

P/Invoke .NET調用win32API

section:要讀取的段落名

P/Invoke .NET調用win32API

key: 要讀取的鍵

P/Invoke .NET調用win32API

defVal: 讀取異常的情況下的預設值

P/Invoke .NET調用win32API

retVal: key所對應的值,如果該key不存在則傳回空值

P/Invoke .NET調用win32API

size: 值允許的大小

P/Invoke .NET調用win32API

filePath: INI檔案的完整路徑和檔案名

[DllImport("kernel32")] 

private static extern long WritePrivateProfileString(string section, string key, string val, string filePath); 

section: 要寫入的段落名

key: 要寫入的鍵,如果該key存在則覆寫寫入

val: key所對應的值

歡迎關注微信公衆号:大資料從業者

繼續閱讀