再談System.ComponentModel.Win32Exception


如名稱的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");
}
正如您可能懷疑的那樣,第一個StartProcessFromPath()調用工作正常,我們看到記事本窗口彈出兩秒鍾,然后由於Kill()方法調用而消失。我們還可以從控制台日志輸出中獲得成功確認:
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
我們還確保輸出相關的Win32錯誤代碼,方法是在System.ComponentModel. Win32Exception,因此我們可以看到win32錯誤代碼是:2。 如果我們回到Win32錯誤代碼表,我們會發現2的值(即0x00000002)對應於Error_FILE_NOT_FOUND枚舉,並說明系統找不到指定的文件。當然,這個描述與System.ComponentModel.Win32Exception輸出我們收到的消息!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM