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;
}
}
}
}