using System; using System.IO; using System.Security; using System.Text; using Vanara.PInvoke; using static Vanara.PInvoke.Kernel32; using static Vanara.PInvoke.Macros; using static Vanara.PInvoke.Shell32; using static Vanara.PInvoke.User32; // ReSharper disable UnusedMember.Global // ReSharper disable MemberCanBePrivate.Global // ReSharper disable MemberCanBeProtected.Global // ReSharper disable UnusedAutoPropertyAccessor.Global namespace Vanara.Windows.Shell { /// Specifies the executable file type. public enum ExecutableType { /// The file executable type is not able to be determined. Nonexecutable = 0, /// The file is an MS-DOS .exe, .com, or .bat file. // ReSharper disable once InconsistentNaming DOS, /// The file is a Microsoft Win32®-based console application. Win32Console, /// The file is a Windows application. Windows, } /// The type of icon to be returned from . [Flags] public enum ShellIconType { /// Retrieve the file's small icon. Small = SHGFI.SHGFI_SMALLICON, /// Retrieve the file's large icon. Large = SHGFI.SHGFI_LARGEICON, /// Retrieve a Shell-sized icon. ShellDefinedSize = SHGFI.SHGFI_SHELLICONSIZE, /// Add the link overlay to the file's icon LinkOverlay = SHGFI.SHGFI_LINKOVERLAY, /// Retrieve the file's open icon. Open = SHGFI.SHGFI_OPENICON, /// Blend the file's icon with the system highlight color. Selected = SHGFI.SHGFI_SELECTED } /// Information and icons for any shell file. public class ShellFileInfo : FileSystemInfo { private string _name; /// Initializes a new instance of the ShellFileInfo class, which acts as a wrapper for a file path within the Windows Shell. /// The fully qualified name of the new file, or the relative file name. public ShellFileInfo(string fileName) { OriginalPath = fileName; FullPath = Path.GetFullPath(fileName); SetName(Path.GetFileName(fileName)); GetInfo(); } /// Initializes a new instance of the class. protected ShellFileInfo() { } /// Initializes a new instance of the ShellFileInfo class, which acts as a wrapper for a file path within the Windows Shell. /// The ID list. public ShellFileInfo(PIDL pidl) { var sb = new StringBuilder(MAX_PATH, MAX_PATH); if (!SHGetPathFromIDList(pidl, sb)) throw new ArgumentException("Invalid identifier list."); OriginalPath = sb.ToString(); FullPath = sb.ToString(); SetName(Path.GetFileName(sb.ToString())); GetInfo(); } /// Gets the display name for the file. public string DisplayName { get; private set; } /// Gets the executable type of the file. public ExecutableType ExecutableType { get; private set; } /// Gets a value indicating whether the file or directory exists. public override bool Exists { [SecuritySafeCritical] get { try { return ((int)Attributes & 0x10) == 0; } catch { return false; } } } /// Gets the icon location for this file. /// The . public IconLocation IconLocation { get { var shfi = new SHFILEINFO(); var ret = SHGetFileInfo(FullPath, 0, ref shfi, SHFILEINFO.Size, SHGFI.SHGFI_ICONLOCATION); if (ret == IntPtr.Zero) { ret = SHGetFileInfo(FullPath, 0, ref shfi, SHFILEINFO.Size, SHGFI.SHGFI_ICONLOCATION | SHGFI.SHGFI_ICON); if (ret != IntPtr.Zero) DestroyIcon(shfi.hIcon); } return ret != IntPtr.Zero ? new IconLocation(shfi.szDisplayName, shfi.iIcon) : new IconLocation(); } } /// Gets the index of the icon overlay. /// The index of the icon overlay, or -1 if no overlay is set. public int IconOverlayIndex { get { var shfi = new SHFILEINFO(); var ret = SHGetFileInfo(FullPath, 0, ref shfi, SHFILEINFO.Size, SHGFI.SHGFI_ICON | SHGFI.SHGFI_USEFILEATTRIBUTES | SHGFI.SHGFI_OVERLAYINDEX | SHGFI.SHGFI_LINKOVERLAY); if (ret == IntPtr.Zero) return -1; DestroyIcon(shfi.hIcon); return (shfi.iIcon >> 24) - 1; } } /// Gets the large icon for the file. public SafeHICON LargeIcon => GetIcon(); /// Gets the size, in bytes, of the current link file. /// The length in bytes of the file. public long Length => new FileInfo(FullPath).Length; /// /// For files, gets the name of the file. For directories, gets the name of the last directory in the hierarchy if a hierarchy exists. Otherwise, the /// Name property gets the name of the directory. /// public override string Name => _name; // Gets the size the file requires on disk taking into account NTFS compression. // REQUIRES DEPENDENCY ON Vanara.SystemServices // public ulong PhysicalLength => new FileInfo(FullPath).GetPhysicalLength(); /// Gets the shell item attributes. /// The shell item attributes. public SFGAO ShellAttributes { get; private set; } /// Gets the small icon for the file. public SafeHICON SmallIcon => GetIcon(ShellIconType.Small); /// Gets the icon for this shell item from the system. /// The system icon on success; null on failure. public SafeHICON SystemIcon => ShellImageList.GetSystemIcon(FullPath); /// Gets the type name for the file. public string TypeName { get; private set; } /// Permanently deletes the file. public override void Delete() { File.Delete(FullPath); } /// Gets the icon defined by the set of flags provided. /// Flags to specify type of the icon. /// if successful; null otherwise. public SafeHICON GetIcon(ShellIconType iconType = ShellIconType.Large) => ShellImageList.GetFileIcon(FullPath, iconType); /// Returns a that represents this instance. /// A that represents this instance. public override string ToString() => FullPath; /// Sets the name. /// The name. protected void SetName(string name) { _name = name; } /// Gets the information. private void GetInfo() { var shfi = new SHFILEINFO(); // Get display name, type, and attributes var ret = SHGetFileInfo(FullPath, 0, ref shfi, SHFILEINFO.Size, SHGFI.SHGFI_DISPLAYNAME | SHGFI.SHGFI_TYPENAME | SHGFI.SHGFI_ATTRIBUTES); if (ret != IntPtr.Zero) { ShellAttributes = (SFGAO)shfi.dwAttributes; TypeName = shfi.szTypeName.Clone().ToString(); DisplayName = shfi.szDisplayName.Clone().ToString(); } else throw new FileLoadException(); // Get executable type ret = SHGetFileInfo(FullPath, 0, ref shfi, SHFILEINFO.Size, SHGFI.SHGFI_EXETYPE); ExecutableType = ExecutableType.Nonexecutable; if (ret != IntPtr.Zero) { var loWord = LOWORD(ret); if (HIWORD(ret) == 0x0000) { if (loWord == 0x5A4D) ExecutableType = ExecutableType.DOS; else if (loWord == 0x4550) ExecutableType = ExecutableType.Win32Console; } else if (loWord == 0x454E || loWord == 0x4550 || loWord == 0x454C) ExecutableType = ExecutableType.Windows; } } } }