本文提供此 API 參考文件的補充備註。
類別 SafeHandle 提供對控制代碼資源的關鍵性最終處理,防止控制代碼被垃圾收集提前回收,並避免被作業系統回收後用於參考未預期的非受控物件。
為什麼是SafeHandle?
雖然對 Object.Finalize 方法的覆寫允許在物件被垃圾收集時清理非管理的資源,但在某些情況下,垃圾收集可以在平台調用呼叫中執行方法時回收可終結的物件。 如果一個終結器釋放了傳遞至該平台調用呼叫的句柄,可能會導致句柄腐敗。 當您的方法在平台調用呼叫期間遭到封鎖時,也可以回收句柄,例如讀取檔案時。
更重要的是,因為 Windows 積極回收控制碼,這些控制碼可能被回收後指向其他資源,而該資源可能包含敏感數據。 這稱為回收攻擊,而且可能會損毀數據並成為安全性威脅。
SafeHandle 的功能
類別 SafeHandle 可簡化其中數個物件生命週期問題,並與P/Invoke整合,因此不會洩漏系統資源。 類別 SafeHandle 會藉由指派和釋放句柄來解決物件存留期問題,而不會中斷。 它包含重要的完成項,可確保句柄已關閉,而且保證會在非預期的 AppDomain 卸除期間執行,即使在假設平台調用呼叫處於損毀狀態的情況下也是如此。
因為 SafeHandle 繼承自 CriticalFinalizerObject,因此所有非關鍵完成項都會在任何關鍵完成項之前呼叫。 終結器會在相同垃圾收集階段的、不再存活的物件進行呼叫。 例如,FileStream物件可以執行一般終結器,以清除現有的緩衝數據,而不必擔心句柄被洩漏或重複利用的風險。 關鍵和非關鍵完成項之間的這種非常弱的順序不適合用於一般用途。 它主要是為了協助移轉現有的連結庫,方法是允許這些連結庫使用 SafeHandle 而不改變其語意。 此外,重要完成項及其所呼叫的任何專案,例如 SafeHandle.ReleaseHandle() 方法,都必須位於限制的執行區域中。 這會對完成項呼叫圖形內可撰寫的程式代碼施加條件約束。
平台調用操作會自動遞增被SafeHandle封裝的句柄的參考計數,並在完成時遞減它們。 這可確保句柄不會被意外回收或被意外關閉。
您可以在建構 SafeHandle 物件時指定基礎句柄的擁有權,方法是將值 ownsHandle
提供給類別建構函式中的 SafeHandle 自變數。 這會控制 SafeHandle 物件在處置之後是否會釋放句柄。 這對於具有特別要求的存留期的控制柄,或取用由其他人控制其存留期的控制柄,尤其有用。
衍生自SafeHandle的類別
SafeHandle 是操作系統句柄的抽象包裝類別。 衍生自這個類別很困難。 請改用命名空間中的 Microsoft.Win32.SafeHandles 衍生類別,以提供下列安全句柄:
- 檔案 (類別 SafeFileHandle )。
- 記憶體對應檔案 (類別 SafeMemoryMappedFileHandle )。
- 管道(類別 SafePipeHandle )。
- 記憶體檢視 (類別 SafeMemoryMappedViewHandle )。
- 密碼編譯建構 (SafeNCryptHandle、 SafeNCryptKeyHandleSafeNCryptProviderHandle、 和 SafeNCryptSecretHandle 類別)。
- 進程 (類別 SafeProcessHandle )。
- 登錄機碼 (類別 SafeRegistryHandle )。
- 等候句柄 (類別 SafeWaitHandle )。