此類型在System.ComponentModel命名空間內,而不是你可能認為的System.Runtime.InteropServices命名空間內。
但是他的父類:ExternalException,則是在System.Runtime.InteropServices命名空間內。
ExternalException的父類是SystemException(當然現在SystemException和ApplicationException該繼承哪個界限已經很模糊了)。注意ExternalException多了一個ErrorCode屬性返回的是父類Exception的HResult屬性,同時在ExternalException的建構函式中可以設定HResult屬性,但是Win32Exception並沒有使用這個HResult的,Win32Exception僅設定父類的Message屬性,也就是說Win32Exception中的ExternalException的ErrorCode始終是保持預設值的。
而Win32Exception自己定義了一個屬性值:NativeErrorCode,同樣是int類型。Win32Exception可以設定三個屬性,NativeErrorCode,Exception的Message,和Exception的InnerException屬性。InnerException沒有特殊的地方,前兩個屬性有這樣的特點:
1. 可以通過建構函式設定他們的值。
2. 如果只設定NativeErrorCode,那麼Message會是相應Win32錯誤碼的文字描述。
3. 如果只設定Message,那麼NativeErrorCode會是Marshal.GetLastWin32Error方法的傳回值。
4. 如果什麼都不設定,那麼2和3都會被應用。
這些都是非常有用的,尤其是第2項,這個可以代替另一個Win32 API:FormatMessage,開發人員就不需要再次平台叫用FormatMessage API,直接使用Win32Exception則可以。
比如隨便舉一個Win32錯誤碼:17,代表“無法將檔案移動到不同的磁碟中”(可以參考:System Error Codes)
代碼:
Console.WriteLine(new System.ComponentModel.Win32Exception(17).Message);
輸出(我的系統是英文的,在中文系統會輸出中文):
The system cannot move the file to a different disk drive
接下來試試自動調用GetLastWin32Error方法,隨便試一個API比如DeleteFile API。這樣定義平台叫用:
//+ using System.Runtime.InteropServices;
[DllImport("kernel32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool DeleteFile(string lpFileName);
如果出錯的話,可以一般是這樣處理錯誤:
//+ using System.Runtime.InteropServices;
if (!DeleteFile("123"))
{
//擷取錯誤碼
int errorCode = Marshal.GetLastWin32Error();
//輸出錯誤資訊
//使用FormatMessage或者Win32Exception.Message
}
其實還可以更快的,就是用Win32Exception的預設建構函式:
//+ using System.ComponentModel;
if (!DeleteFile("123"))
Console.WriteLine(new Win32Exception().Message);
此時Marshal.GetLastWin32Error和Win32錯誤碼的描述都會被解決,於是代碼會輸出“檔案未找到”的字樣:
The system cannot find the file specified