如名稱的Win32部分所示System.ComponentModel.Win32Exception僅在處理傳統樣式的應用程序或代碼時發生-應用程序必須調用直接操作系統調用,例如嘗試執行其他應用程序。在本文中,我們將深入探討System.ComponentModel.Win32異常。更詳細地說,包括它在.NET異常層次結構中的位置。我們還將深入研究一些函數C#代碼示例,以更好地說明如何System.ComponentModel.Win32Exceptions可能會在自己的編碼中被拋出!
要點
- 所有 .NET exceptions 繼承自 System.Exception base class, 或者繼承自inherited class.
- System.SystemException 繼承自 System.Exception class.
- System.Runtime.InteropServices.ExternalException 直接繼承自System.SystemException.
- 最后, System.ComponentModel.Win32Exception 繼承自 System.Runtime.InteropServices.ExternalException.
什么時候用它呢?
這個System.ComponentModel.Win32異常是在使用內部win32樣式的操作系統調用時發生錯誤時在.NET應用程序中發生的最基本的異常類型。這些問題可能不同,從無效路徑和文件找不到錯誤到網絡地址問題和資源管理問題。因為System.ComponentModel.Win32Exceptions是舊形式異常的包裝器,您可能遇到的每個可能的錯誤都有自己的NativeErrorCode屬性值,它是一個32位整數,引用與引發的異常相關聯的Win32錯誤代碼值。
我們的示例代碼開始。整個代碼段如下所示,之后我們將更詳細地討論它:
using System.Diagnostics; using Utility; namespace Airbrake.ComponentModel.Win32Exception { class Program { static void Main(string[] args) { StartProcessFromPath("c:/windows/notepad.exe"); Logging.LineSeparator(); StartProcessFromPath("c:/windows/invalid.exe"); } static void StartProcessFromPath(string path) { try { // Create a new process with StartInfo.FileName set to provided path. var process = new Process { StartInfo = { FileName = path } }; // Attempt to start the process using provided executable path. var success = process.Start(); if (success) { Logging.Log($"Successfully launched '{process.ProcessName.ToString()}' process!"); // Sleep for two seconds to allow time for window to be shown. System.Threading.Thread.Sleep(2000); // Kill process. process.Kill(); Logging.Log($"Killed '{process.ProcessName.ToString()}' process."); } else { // This code never executes since we're catching // an exception from the process.Start() invocation line. } } catch (System.ComponentModel.Win32Exception exception) { // Indicate failure to start. Logging.Log($"Unable to start process with executable path '{path}'."); // Output caught exception. Logging.Log(exception); Logging.Log($"Native Win32 Error Code: {exception.NativeErrorCode}"); } } } } using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Reflection; using System.Text; namespace Utility { /// <summary> /// Houses all logging methods for various debug outputs. /// </summary> public static class Logging { /// <summary> /// Outputs to <see cref="System.Diagnostics.Debug.WriteLine"/> if DEBUG mode is enabled, /// otherwise uses standard <see cref="Console.WriteLine"/>. /// </summary> /// <param name="value">Value to be output to log.</param> public static void Log(string value) { #if DEBUG Debug.WriteLine(value); #else Console.WriteLine(value); #endif } /// <summary> /// When <see cref="Exception"/> parameter is passed, modifies the output to indicate /// if <see cref="Exception"/> was expected, based on passed in `expected` parameter. /// <para>Outputs the full <see cref="Exception"/> type and message.</para> /// </summary> /// <param name="exception">The <see cref="Exception"/> to output.</param> /// <param name="expected">Boolean indicating if <see cref="Exception"/> was expected.</param> public static void Log(Exception exception, bool expected = true) { string value = $"[{(expected ? "EXPECTED" : "UNEXPECTED")}] {exception.ToString()}: {exception.Message}"; #if DEBUG Debug.WriteLine(value); #else Console.WriteLine(value); #endif } /// <summary> /// Outputs a dashed line separator to <see cref="System.Diagnostics.Debug.WriteLine"/> /// if DEBUG mode is enabled, otherwise uses standard <see cref="Console.WriteLine"/>. /// </summary> public static void LineSeparator() { #if DEBUG Debug.WriteLine(new string('-', 20)); #else Console.WriteLine(new string('-', 20)); #endif } } }
我們的大多數示例都發生在StartProcessFromPath()方法中,該方法接受一個應指向可執行文件的字符串路徑值。然后,我們實例化一個新進程,並嘗試用.start()方法啟動它。.Start()方法返回一個布爾值,指示嘗試是否成功,因此我們只需使用該布爾值來執行一些額外的邏輯,例如將一些信息輸出到日志以指示成功或失敗,以及一個小的Sleep()周期,以便我們有時間查看新啟動的窗口(如果適用)。最后我們用.Kill()方法終止進程。
static void StartProcessFromPath(string path) { try { // Create a new process with StartInfo.FileName set to provided path. var process = new Process { StartInfo = { FileName = path } }; // Attempt to start the process using provided executable path. var success = process.Start(); if (success) { Logging.Log($"Successfully launched '{process.ProcessName.ToString()}' process!"); // Sleep for two seconds to allow time for window to be shown. System.Threading.Thread.Sleep(2000); // Kill process. process.Kill(); Logging.Log($"Killed '{process.ProcessName.ToString()}' process."); } else { // This code never executes since we're catching // an exception from the process.Start() invocation line. } } catch (System.ComponentModel.Win32Exception exception) { // Indicate failure to start. Logging.Log($"Unable to start process with executable path '{path}'."); // Output caught exception. Logging.Log(exception); Logging.Log($"Native Win32 Error Code: {exception.NativeErrorCode}"); } }
為了說明成功和失敗,我們的Main()方法嘗試啟動notepad.exe 以及invalid.exe
:
static void Main(string[] args) { StartProcessFromPath("c:/windows/notepad.exe"); Logging.LineSeparator(); StartProcessFromPath("c:/windows/invalid.exe"); }
Successfully launched 'notepad' process! Killed 'notepad' process.
另一方面,我們的第二個StartProcessFromPath()調用invalid.exe
失敗並拋出System.ComponentModel.Win32Exception我們的方式:
Unable to start process with executable path: 'c:/windows/invalid.exe'. [EXPECTED] System.ComponentModel.Win32Exception (0x80004005): The system cannot find the file specified Native Win32 Error Code: 2