none
Searching the Alternate Data Stream of files RRS feed

  • Question

  • Hello,

    I'm need to build an application that will allow someone to search for a string inside of the alternate data stream of files. We have files (word, powerpoint, excel, text, .pdf) that have XML stored in the alternate data streams. I'm trying to find a way to let a user enter a string into a text box, select a folder location, then have the application search through each file in the selected directory for that string. Then display a list of the files that have that string in their streams.  Any help or ideas is appreciated.

    Friday, February 22, 2019 6:10 PM

All replies

  • .NET doesn't support the alternate file streams directly.  There are third party libraries available on NuGet that add support for it such as this. You can use that to enumerate the streams and then access the contents. Alternatively you can just call to Win32 which supports them natively. I think the wrapper in NuGet would be cleaner.

    Interestingly PowerShell does support this out of the box via Get-Item and the stream property. I haven't looked at the implementation though.


    Michael Taylor http://www.michaeltaylorp3.net

    Friday, February 22, 2019 6:41 PM
    Moderator
  • You can enumerate streams to be able to open and read them, with APIs :

    [DllImport("Kernel32.dll", SetLastError = true, CharSet = CharSet.Auto)]
    public static extern IntPtr FindFirstStreamW(string lpFileName, STREAM_INFO_LEVELS InfoLevel, out WIN32_FIND_STREAM_DATA lpFindStreamData, int dwFlags);
    
    [DllImport("Kernel32.dll", SetLastError = true, CharSet = CharSet.Auto)]
    public static extern bool FindNextStreamW(IntPtr hFindStream, ref WIN32_FIND_STREAM_DATA lpFindStreamData);
    
    [DllImport("Kernel32.dll", SetLastError = true, CharSet = CharSet.Auto)]
    public static extern bool FindClose(IntPtr hFindFile);
    
    public enum STREAM_INFO_LEVELS
    {
        FindStreamInfoStandard,
        FindStreamInfoMaxInfoLevel
    }
    
    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
    public struct WIN32_FIND_STREAM_DATA
    {
        public LARGE_INTEGER StreamSize;
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = MAX_PATH + 36)]
        public string cStreamName;
    }
    
    public const int MAX_PATH = 260;
    public const int INVALID_HANDLE_VALUE = -1;

    Friday, February 22, 2019 9:08 PM