API函數是構築Windows應用程序的基石,是Windows編程的必備利器。每一種Windows應用程序開發工具都提供了間接或直接調用了Windows API函數的方法,或者是調用Windows API函數的接口,也就是說具備調用動態連接庫的能力。Visual C#和其它開發工具一樣也能夠調用動態鏈接庫的API函數。本文中筆者就結合實例向大家介紹在Visual C#中如何調用各種返回值的API,該實例就是一個通過API函數調用獲取系統信息的程序。
在Visual C#中調用API的基本過程:
首先,在調用API之前,你必須先導入System.Runtime.InteropServices這個名稱空間。該名稱空間包含了在Visual C#中調用API的一些必要集合,具體的方法如下:
using System.Runtime.InteropServices;
在導入了名稱空間後,我們要聲明在程序中所要用到的API函數。我們的程序主要是獲取系統的相關信息,所以用到的API函數都是返回系統信息的。先給出在Visual C#中聲明API的方法:
[DllImport("kernel32")] public static extern void GetWindowsDirectory(StringBuilder WinDir,int count);
其中,"DllImport"屬性用來從不可控代碼中調用一個方法,它指定了DLL的位置,該DLL中包含調用的外部方法;"kernel32"設定了類庫名;"public"指明函數的訪問類型為公有的;"static"修飾符聲明一個靜態元素,而該元素屬於類型本身而不是指定的對象;"extern"表示該方法將在工程外部執行,同時使用DllImport導入的方法必須使用"extern"修飾符;最後GetWindowsDirectory函數包含了兩個參數,一個為StringBuilder類型的,另一個為int類型的,該方法返回的內容存在於StringBuilder類型的參數中。同時,因為我們在這裡使用到了StringBuilder類,所以在程序的開始處,我們還得添加System.Text這個名稱空間,方法同上。
其他幾個API函數的聲明如下:
[DllImport("kernel32")] public static extern void GetSystemDirectory(StringBuilder SysDir,int count); [DllImport("kernel32")] public static extern void GetSystemInfo(ref CPU_INFO cpuinfo); [DllImport("kernel32")] public static extern void GlobalMemoryStatus(ref MEMORY_INFO meminfo); [DllImport("kernel32")] public static extern void GetSystemTime(ref SYSTEMTIME_INFO stinfo);
以上幾個API的作用分別是獲取系統路徑,獲得CPU相關信息,獲得內存的相關信息,獲得系統時間等。
在聲明完所有的API函數後,我們發現後三個函數分別用到了CPU_INFO、MEMORY_INFO、SYSTEMTIME_INFO等結構,這些結構並非是.Net內部的,它們從何而來?其實,我們在用到以上API調用時均需用到以上結構,我們將函數調用獲得的信息存放在以上的結構體中,最後返回給程序輸出。這些結構體比較復雜,但是如果開發者能夠熟練運用,那麼整個API世界將盡在開發者的掌握之中。以下就是上述結構體的聲明:
//定義以下各結構 //定義CPU的信息結構 [StructLayout(LayoutKind.Sequential)] public struct CPU_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; } //定義內存的信息結構 [StructLayout(LayoutKind.Sequential)] public struct MEMORY_INFO { public uint dwLength; public uint dwMemoryLoad; public uint dwTotalPhys; public uint dwAvailPhys; public uint dwTotalPageFile; public uint dwAvailPageFile; public uint dwTotalVirtual; public uint dwAvailVirtual; } //定義系統時間的信息結構 [StructLayout(LayoutKind.Sequential)] public struct SYSTEMTIME_INFO { public ushort wYear; public ushort wMonth; public ushort wDayOfWeek; public ushort wDay; public ushort wHour; public ushort wMinute; public ushort wSecond; public ushort wMilliseconds; }
結構體定義的主體部分和C++中的沒多大差別,具體每個結構體內部成員的定義可參考聯機幫助中的SDK文檔。同時,我們還發現在每個結構體定義的上面都有一句用中括號括起來的說明性文字。這些說明都是有關結構體成員的布局的,共有三種選項,分別說明如下: