SafeHandle Class
Collapse the table of content
Expand the table of content

SafeHandle Class


Represents a wrapper class for operating system handles. This class must be inherited.

Namespace:   System.Runtime.InteropServices
Assembly:  mscorlib (in mscorlib.dll)

	UnmanagedCode = true)]
public abstract class SafeHandle : CriticalFinalizerObject, IDisposable

System_CAPS_protmethodSafeHandle(IntPtr, Boolean)

Initializes a new instance of the SafeHandle class with the specified invalid handle value.


Gets a value indicating whether the handle is closed.


When overridden in a derived class, gets a value indicating whether the handle value is invalid.


Marks the handle for releasing and freeing resources.


Manually increments the reference counter on SafeHandle instances.


Returns the value of the handle field.


Manually decrements the reference counter on a SafeHandle instance.


Releases all resources used by the SafeHandle class.


Releases the unmanaged resources used by the SafeHandle class specifying whether to perform a normal dispose operation.


Determines whether the specified object is equal to the current object.(Inherited from Object.)


Frees all resources associated with the handle.(Overrides CriticalFinalizerObject.Finalize().)


Serves as the default hash function. (Inherited from Object.)


Gets the Type of the current instance.(Inherited from Object.)


Creates a shallow copy of the current Object.(Inherited from Object.)


When overridden in a derived class, executes the code required to free the handle.


Sets the handle to the specified pre-existing handle.


Marks a handle as no longer used.


Returns a string that represents the current object.(Inherited from Object.)


Specifies the handle to be wrapped.

The SafeHandle class provides critical finalization of handle resources, preventing handles from being reclaimed prematurely by garbage collection and from being recycled by Windows to reference unintended unmanaged objects.

This topic includes the following sections:

Why SafeHandle?
What SafeHandle does
Classes derived from SafeHandle

Before the .NET Framework version 2.0, all operating system handles could only be encapsulated in the IntPtr managed wrapper object. While this was a convenient way to interoperate with native code, handles could be leaked by asynchronous exceptions, such as a thread aborting unexpectedly or a stack overflow. These asynchronous exceptions are an obstacle to cleaning up operating system resources, and they can occur almost anywhere in your app.

Although overrides to the Object.Finalize method allow cleanup of unmanaged resources when an object is being garbage collected, in some circumstances, finalizable objects can be reclaimed by garbage collection while executing a method within a platform invoke call. If a finalizer frees the handle passed to that platform invoke call, it could lead to handle corruption. The handle could also be reclaimed while your method is blocked during a platform invoke call, such as while reading a file.

More critically, because Windows aggressively recycles handles, a handle could be recycled and point to another resource that might contain sensitive data. This is known as a recycle attack and can potentially corrupt data and be a security threat.

The SafeHandle class simplifies several of these object lifetime issues, and is integrated with platform invoke so that operating system resources are not leaked. The SafeHandle class resolves object lifetime issues by assigning and releasing handles without interruption. It contains a critical finalizer that ensures that the handle is closed and is guaranteed to run during unexpected AppDomain unloads, even in cases when the platform invoke call is assumed to be in a corrupted state.

Because SafeHandle inherits from CriticalFinalizerObject, all the noncritical finalizers are called before any of the critical finalizers. The finalizers are called on objects that are no longer live during the same garbage collection pass. For example, a FileStream object can run a normal finalizer to flush out existing buffered data without the risk of the handle being leaked or recycled. This very weak ordering between critical and noncritical finalizers is not intended for general use. It exists primarily to assist in the migration of existing libraries by allowing those libraries to use SafeHandle without altering their semantics. Additionally, the critical finalizer and anything it calls, such as the SafeHandle.ReleaseHandle() method, must be in a constrained execution region. This imposes constraints on what code can be written within the finalizer's call graph.

Platform invoke operations automatically increment the reference count of handles encapsulated by a SafeHandle and decrement them upon completion. This ensures that the handle will not be recycled or closed unexpectedly.

You can specify ownership of the underlying handle when constructing SafeHandle objects by supplying a value to the ownsHandle argument in the SafeHandle class constructor. This controls whether the SafeHandle object will release the handle after the object has been disposed. This is useful for handles with peculiar lifetime requirements or for consuming a handle whose lifetime is controlled by someone else.

SafeHandle is an abstract wrapper class for operating system handles. Deriving from this class is difficult. Instead, use the derived classes in the Microsoft.Win32.SafeHandles namespace that provide safe handles for the following:

Notes to Inheritors:

To create a class derived from SafeHandle, you must know how to create and free an operating system handle. This process is different for different handle types because some use the CloseHandle function, while others use more specific functions such as UnmapViewOfFile or FindClose. For this reason, you must create a derived class of SafeHandle for each operating system handle type that you want to wrap in a safe handle.


Writing your own classes derived from SafeHandle is an advanced programming feature. The .NET Framework provides a set of prewritten classes derived from SafeHandle in the Microsoft.Win32.SafeHandles namespace. These classes are designed to provide common functionality supporting file and operating system handles.

When you inherit from SafeHandle, you must override the following members: IsInvalid and ReleaseHandle.

You should also provide a default constructor that calls the base constructor with a value that represent an invalid handle value, and a Boolean value indicating whether the native handle is owned by the SafeHandle and consequently should be freed when that SafeHandle has been disposed.

Legacy Code Example

The following code example creates a custom safe handle for an operating system file handle, deriving from SafeHandleZeroOrMinusOneIsInvalid. It reads bytes from a file and displays their hexadecimal values. It also contains a fault testing harness that causes the thread to abort, but the handle value is freed. When using an IntPtr to represent handles, the handle is occasionally leaked due to the asynchronous thread abort.

You will need a text file in the same folder as the compiled application. Assuming that you name the application "HexViewer", the command line usage is:

HexViewer <filename> -Fault

Optionally specify -Fault to intentionally attempt to leak the handle by aborting the thread in a certain window. Use the Windows Perform.exe tool to monitor handle counts while injecting faults.

// Example of BitConverter class methods.
using System;

class BitConverterDemo
    public static void Main( )
        const string formatter = "{0,25}{1,30}";

        double  aDoubl  = 0.1111111111111111111;
        float   aSingl  = 0.1111111111111111111F;
        long    aLong   = 1111111111111111111;
        int     anInt   = 1111111111;
        short   aShort  = 11111;
        char    aChar   = '*';
        bool    aBool   = true;

            "This example of methods of the BitConverter class" +
            "\ngenerates the following output.\n" );
        Console.WriteLine( formatter, "argument", "byte array" );
        Console.WriteLine( formatter, "--------", "----------" );

        // Convert values to Byte arrays and display them.
        Console.WriteLine( formatter, aDoubl, 
            BitConverter.ToString( BitConverter.GetBytes( aDoubl ) ) );
        Console.WriteLine( formatter, aSingl, 
            BitConverter.ToString( BitConverter.GetBytes( aSingl ) ) );
        Console.WriteLine( formatter, aLong, 
            BitConverter.ToString( BitConverter.GetBytes( aLong ) ) );
        Console.WriteLine( formatter, anInt, 
            BitConverter.ToString( BitConverter.GetBytes( anInt ) ) );
        Console.WriteLine( formatter, aShort, 
            BitConverter.ToString( BitConverter.GetBytes( aShort ) ) );
        Console.WriteLine( formatter, aChar, 
            BitConverter.ToString( BitConverter.GetBytes( aChar ) ) );
        Console.WriteLine( formatter, aBool, 
            BitConverter.ToString( BitConverter.GetBytes( aBool ) ) );

This example of methods of the BitConverter class
generates the following output.

                 argument                    byte array
                 --------                    ----------
        0.111111111111111       1C-C7-71-1C-C7-71-BC-3F
                0.1111111                   39-8E-E3-3D
      1111111111111111111       C7-71-C4-2B-AB-75-6B-0F
               1111111111                   C7-35-3A-42
                    11111                         67-2B
                        *                         2A-00
                     True                            01

for full trust for inheritors. This member cannot be inherited by partially trusted code.


requires full trust for the immediate caller. This member cannot be used by partially trusted or transparent code.

Universal Windows Platform
Available since 4.5
.NET Framework
Available since 2.0
Portable Class Library
Supported in: portable .NET platforms
Available since 2.0
Windows Phone Silverlight
Available since 7.0
Windows Phone
Available since 8.1

Any public static (Shared in Visual Basic) members of this type are thread safe. Any instance members are not guaranteed to be thread safe.

Return to top
© 2015 Microsoft