SafeFileHandle Class
Represents a wrapper class for a file handle.
Assembly: mscorlib (in mscorlib.dll)
This class is derived from SafeHandleZeroOrMinusOneIsInvalid. A value of 0 or -1 is an invalid file handle.
The following code example demonstrates how to open a file using the SafeFileHandle class and the unmanaged CreateFile function.
using System; using Microsoft.Win32.SafeHandles; using System.Runtime.InteropServices; using System.ComponentModel; class SafeHandlesExample { static void Main() { try { UnmanagedFileLoader loader = new UnmanagedFileLoader("example.xml"); } catch (Exception e) { Console.WriteLine(e); } Console.ReadLine(); } } class UnmanagedFileLoader { public const short FILE_ATTRIBUTE_NORMAL = 0x80; public const short INVALID_HANDLE_VALUE = -1; public const uint GENERIC_READ = 0x80000000; public const uint GENERIC_WRITE = 0x40000000; public const uint CREATE_NEW = 1; public const uint CREATE_ALWAYS = 2; public const uint OPEN_EXISTING = 3; // Use interop to call the CreateFile function. // For more information about CreateFile, // see the unmanaged MSDN reference library. [DllImport("kernel32.dll", SetLastError = true, CharSet=CharSet.Unicode)] static extern SafeFileHandle CreateFile(string lpFileName, uint dwDesiredAccess, uint dwShareMode, IntPtr lpSecurityAttributes, uint dwCreationDisposition, uint dwFlagsAndAttributes, IntPtr hTemplateFile); private SafeFileHandle handleValue = null; public UnmanagedFileLoader(string Path) { Load(Path); } public void Load(string Path) { if (Path == null && Path.Length == 0) { throw new ArgumentNullException("Path"); } // Try to open the file. handleValue = CreateFile(Path, GENERIC_WRITE, 0, IntPtr.Zero, OPEN_EXISTING, 0, IntPtr.Zero); // If the handle is invalid, // get the last Win32 error // and throw a Win32Exception. if (handleValue.IsInvalid) { Marshal.ThrowExceptionForHR(Marshal.GetHRForLastWin32Error()); } } public SafeFileHandle Handle { get { // If the handle is valid, // return it. if (!handleValue.IsInvalid) { return handleValue; } else { return null; } } } }
-
SecurityPermission
for permission to call unmanaged code. Security action: LinkDemand. Associated enumeration: SecurityPermissionFlag.UnmanagedCode
System.Runtime.ConstrainedExecution.CriticalFinalizerObject
System.Runtime.InteropServices.SafeHandle
Microsoft.Win32.SafeHandles.SafeHandleZeroOrMinusOneIsInvalid
Microsoft.Win32.SafeHandles.SafeFileHandle
Windows 7, Windows Vista, Windows XP SP2, Windows XP Media Center Edition, Windows XP Professional x64 Edition, Windows XP Starter Edition, Windows Server 2008 R2, Windows Server 2008, Windows Server 2003, Windows Server 2000 SP4, Windows Millennium Edition, Windows 98
The .NET Framework and .NET Compact Framework do not support all versions of every platform. For a list of the supported versions, see .NET Framework System Requirements.
I decided to investigate scenerios in which what would the SafeFileHandle class do if the unmanaged handle was closed from another process. You will find some interesting things to consider when using SafeFileHandle.
The first step was to use CreateFile() using the SafeFileHandle class. I specify the file for exclusive access so no other process can have access.
The next was to open a new .NET IDE I loaded a custom class that enumerated file handles. When I found the handle to the file of interest (the locked file) I duplicated the handle and closed it.
I went back to .NET IDE that I called CreateFile() and inspected the SafeFileHandle.
1) The IsInvalid property returns FALSE
2) The IsClosed property returns FALSE
3) The DangerousGetHandle method returns the un-managed handle value.
Now, If you're not sure what this means I'll try to explain it.
The SafeFileHandle doesn't know or check if the unmanaged handle is valid. It also never updates the property information. You can't use these properties in this case to ensure that the handle indeed valid.
The chances of another process closing your handle to the file is very low but it's still possible and what you need to know is that if you want to use that SafeFileHandle instance with the FileStreamReader for example the properties IsInvalid and IsClosed will indicate no problems on the handle but when when you pass the SafeFileHandle to the FileStreamReader it's smart enough to throw an IOException.
Conclusion:
If you use the SafeFileHandle class and you want to read/write to the file the properties can't be used as a means of determining if the handle is still valid in such a case you must always catch the IOException instead.
- 3/9/2010
- eriklitze
Cheers...
- 11/6/2009
- Helmut Obertanner