Since NT 3.1, the NTFS file system has supported multiple data-streams for files. There has never been built-in support for viewing or manipulating these additional streams, but the Windows API functions include support for them with a special file syntax:
Filename.ext:StreamName. Even Win9x machines can access the alternative data streams of files on any NTFS volume they have access to, e.g. through a mapped drive. Because the
Scripting.FileSystemObject and many other libraries call the
CreateFile API behind the scenes, even scripts have been able to access alternative streams quite easily (although enumerating the existing streams has always been tricky).
In .NET, however, it seems someone decided to add some checking to the format of filenames. If you attempt to open a
FileStream on an alternative stream, you will get a "Path Format not supported" exception. I have been unable to find any class in the CLR that provides support for alternative data streams, so I decided to roll my own.
I originally wrote this code six years ago, targeting v1 of the .NET Framework. Looking at the code now, it seems quite messy, and has several bugs and problems which were mentioned in the comments. I have since completely re-written the code for .NET v3.5, and (hopefully) fixed the bugs.
The new code is not compatible with the original version. However, I have included a sample compatibility wrapper which maps the old API to the new API. You can find these files under the "other/Compatibility wrapper" folder in the download.
FileSystemInfoclass rather than the
FileInfoclass. This allows you to access alternate data streams attached to folders as well as files. (Suggested by Dan Elebash)
SafeFileHandleinstead of
IntPtrfor the file handle.
BackupReadwith the
bAbortparameter set to
trueafter enumerating the streams. (Reported by scooter_jsm)
The
AlternateDataStreamInfo class represents the details of an individual stream, and provides methods to create, open or delete the stream.
The static
FileSystem class provides methods to retrieve the list of streams for a file, retrieve a specific stream from a file, determine whether a stream exists, and delete a specific stream.
All methods on the
FileSystem class offer overloads which accept either a path or a
FileSystemInfo object. The overloads which accept a
FileSystemInfo object can also be invoked as extension methods.
using System; using System.Drawing; using System.Drawing.Imaging; using System.IO; using Trinet.Core.IO.Ntfs; ... FileInfo file = new FileInfo(path); // List the additional streams for a file: foreach (AlternateDataStreamInfo s in file.ListAlternateDataStreams()) { Console.WriteLine("{0} - {1} bytes", s.Name, s.Size); } // Read the "Zone.Identifier" stream, if it exists: if (file.AlternateDataStreamExists("Zone.Identifier")) { Console.WriteLine("Found zone identifier stream:"); AlternateDataStreamInfo s = file.GetAlternateDataStream("Zone.Identifier", FileMode.Open); using (TextReader reader = s.OpenText()) { Console.WriteLine(reader.ReadToEnd()); } // Delete the stream: s.Delete(); } else { Console.WriteLine("No zone identifier stream found."); } // Alternative method to delete the stream: file.DeleteAlternateDataStream("Zone.Identifier");
If you want more information on NTFS programming, or the C++ code I based this on, see Dino Esposito's MSDN article from March 2000: [^].
General
News
Question
Answer
Joke
Rant
Admin