C#WindowsAPI库 > Shell32


shell32.dll


using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Runtime.InteropServices;
using System.Security;
using System.Text;

namespace WindowsAPI
{
    public enum FileFuncFlags
    {
        FO_MOVE = 0x1,
        FO_COPY = 0x2,
        FO_DELETE = 0x3,
        FO_RENAME = 0x4
    }
    [Flags]
    public enum FILEOP_FLAGS
    {
        FOF_MULTIDESTFILES = 0x1,
        FOF_CONFIRMMOUSE = 0x2,
        FOF_SILENT = 0x4,
        FOF_RENAMEONCOLLISION = 0x8,
        FOF_NOCONFIRMATION = 0x10,
        FOF_WANTMAPPINGHANDLE = 0x20,
        FOF_ALLOWUNDO = 0x40,
        FOF_FILESONLY = 0x80,
        FOF_SIMPLEPROGRESS = 0x100,
        FOF_NOCONFIRMMKDIR = 0x200,
        FOF_NOERRORUI = 0x400,
        FOF_NOCOPYSECURITYATTRIBS = 0x800,
        FOF_NORECURSION = 0x1000,
        FOF_NO_CONNECTED_ELEMENTS = 0x2000,
        FOF_WANTNUKEWARNING = 0x4000,
        FOF_NORECURSEREPARSE = 0x8000
    }
    [Flags]
    public enum ThumbnailOptions
    {
        None = 0x00,
        BiggerSizeOk = 0x01,
        InMemoryOnly = 0x02,
        IconOnly = 0x04,
        ThumbnailOnly = 0x08,
        InCacheOnly = 0x10,
    }
    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
    public struct SHFILEOPSTRUCT
    {
        public IntPtr hwnd;
        public FileFuncFlags wFunc;
        [MarshalAs(UnmanagedType.LPWStr)]
        public string pFrom;
        [MarshalAs(UnmanagedType.LPWStr)]
        public string pTo;
        public FILEOP_FLAGS fFlags;
        [MarshalAs(UnmanagedType.Bool)]
        public bool fAnyOperationsAborted;
        public IntPtr hNameMappings;
        [MarshalAs(UnmanagedType.LPWStr)]
        public string lpszProgressTitle;
    }
    public enum SIGDN
    {
        NORMALDISPLAY = 0,
        PARENTRELATIVEPARSING = 0x80018001,
        PARENTRELATIVEFORADDRESSBAR = 0x8001c001,
        DESKTOPABSOLUTEPARSING = 0x80028000,
        PARENTRELATIVEEDITING = 0x80031001,
        DESKTOPABSOLUTEEDITING = 0x8004c000,
        FILESYSPATH = 0x80058000,
        URL = 0x80068000
    }

    public enum HResult
    {
        Ok = 0x0000,
        False = 0x0001,
        InvalidArguments = unchecked((int)0x80070057),
        OutOfMemory = unchecked((int)0x8007000E),
        NoInterface = unchecked((int)0x80004002),
        Fail = unchecked((int)0x80004005),
        ElementNotFound = unchecked((int)0x80070490),
        TypeElementNotFound = unchecked((int)0x8002802B),
        NoObject = unchecked((int)0x800401E5),
        Win32ErrorCanceled = 1223,
        Canceled = unchecked((int)0x800704C7),
        ResourceInUse = unchecked((int)0x800700AA),
        AccessDenied = unchecked((int)0x80030005)
    }

    [ComImportAttribute()]
    [InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)]
    public interface IShellItemImageFactory
    {
        [PreserveSig]
        HResult GetImage(
        [In, MarshalAs(UnmanagedType.Struct)] NativeSize size,
        [In] ThumbnailOptions flags,
        [Out] out IntPtr phbm);
    }

    [StructLayout(LayoutKind.Sequential)]
    public struct NativeSize
    {
        private int width;
        private int height;

        public int Width { set { width = value; } }
        public int Height { set { height = value; } }
    };

    [StructLayout(LayoutKind.Sequential)]
    public struct RGBQUAD
    {
        public byte rgbBlue;
        public byte rgbGreen;
        public byte rgbRed;
        public byte rgbReserved;
    }
    /// <summary>
    /// 接口?
    /// </summary>
    [ComImport]
    [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
    public interface IShellItem
    {
        void BindToHandler(IntPtr pbc,
            [MarshalAs(UnmanagedType.LPStruct)] Guid bhid,
            [MarshalAs(UnmanagedType.LPStruct)] Guid riid,
            out IntPtr ppv);

        void GetParent(out IShellItem ppsi);
        void GetDisplayName(SIGDN sigdnName, out IntPtr ppszName);
        void GetAttributes(uint sfgaoMask, out uint psfgaoAttribs);
        void Compare(IShellItem psi, uint hint, out int piOrder);
    };
    public class Shell32
    {
        /// <summary>
        /// 对文件进行删除复制移动等操作
        /// </summary>
        /// <param name="lpFileOp"></param>
        /// <returns></returns>
        [DllImport("shell32.dll", CharSet = CharSet.Unicode)]
        public static extern int SHFileOperation([In] ref SHFILEOPSTRUCT lpFileOp);
        /// <summary>
        /// ???
        /// </summary>
        public const string IShellItem2Guid = "7E9FB0D3-919F-4307-AB2E-9B1860310C43";
        /// <summary>
        /// 对系统文件进行操作
        /// </summary>
        /// <param name="path"></param>
        /// <param name="pbc"></param>
        /// <param name="riid"></param>
        /// <param name="shellItem"></param>
        /// <returns></returns>
        [DllImport("shell32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
        public static extern int SHCreateItemFromParsingName([MarshalAs(UnmanagedType.LPWStr)] string path, IntPtr pbc, ref Guid riid, [MarshalAs(UnmanagedType.Interface)] out IShellItem shellItem);
        /// <summary>
        /// 调用shell32,启用系统的复制文件功能
        /// </summary>
        /// <param name="fs"></param>
        /// <param name="fo"></param>
        /// <returns></returns>
        public static bool CopyFiles(IEnumerable<string> fs, System.IO.DirectoryInfo fo)
        {
            var sb = new StringBuilder();
            foreach (var f in fs) sb.Append($"{f}\0");
            SHFILEOPSTRUCT op = new SHFILEOPSTRUCT()
            {
                hwnd = IntPtr.Zero,
                wFunc = FileFuncFlags.FO_COPY,
                pFrom = sb.ToString() + "\0",// 需要注意,最后需要加入"\0"表示字符串结束,如果需要拷贝多个文件,则 file1 + "\0" + file2 + "\0"...
                pTo = fo.FullName + "\0",// 需要注意,最后需要加入"\0"表示字符串结束
                hNameMappings = IntPtr.Zero,
                fFlags = FILEOP_FLAGS.FOF_NOCONFIRMMKDIR,
                fAnyOperationsAborted = false
            };
            int ret = SHFileOperation(ref op);
            return ret == 0;
        }
        /// <summary>
        /// 移动文件
        /// </summary>
        /// <param name="fs"></param>
        /// <param name="fo"></param>
        /// <returns></returns>
        public static bool MoveFiles(IEnumerable<string> fs, System.IO.DirectoryInfo fo)
        {
            var sb = new StringBuilder();
            foreach (var f in fs) sb.Append($"{f}\0");
            SHFILEOPSTRUCT op = new SHFILEOPSTRUCT()
            {
                hwnd = IntPtr.Zero,
                wFunc = FileFuncFlags.FO_MOVE,
                pFrom = sb.ToString() + "\0",// 需要注意,最后需要加入"\0"表示字符串结束,如果需要拷贝多个文件,则 file1 + "\0" + file2 + "\0"...
                pTo = fo.FullName + "\0",// 需要注意,最后需要加入"\0"表示字符串结束
                hNameMappings = IntPtr.Zero,
                fFlags = FILEOP_FLAGS.FOF_NOCONFIRMMKDIR,
                fAnyOperationsAborted = false
            };
            int ret = SHFileOperation(ref op);
            return ret == 0;
        }
        /// <summary>
        /// 删除指定的文件或者文件夹,递归删除
        /// </summary>
        /// <param name="fs"></param>
        /// <returns></returns>
        public static bool MoveFilesToRecycle(IEnumerable<string> fs)
        {
            var sb = new StringBuilder();
            foreach (var f in fs) sb.Append($"{f}\0");
            SHFILEOPSTRUCT op = new SHFILEOPSTRUCT()
            {
                hwnd = IntPtr.Zero,
                wFunc = FileFuncFlags.FO_DELETE,
                pFrom = sb.ToString() + "\0",// 需要注意,最后需要加入"\0"表示字符串结束,如果需要拷贝多个文件,则 file1 + "\0" + file2 + "\0"...
                pTo = "\0",// 需要注意,最后需要加入"\0"表示字符串结束
                hNameMappings = IntPtr.Zero,
                fFlags = FILEOP_FLAGS.FOF_ALLOWUNDO,//FOF_ALLOWUNDO可以将文件移动到回收站
                fAnyOperationsAborted = false
            };
            int ret = SHFileOperation(ref op);
            return ret == 0;
        }
        /// <summary>
        /// 获取指定文件的缩略图的句柄
        /// </summary>
        /// <param name="fileName"></param>
        /// <param name="width"></param>
        /// <param name="height"></param>
        /// <param name="options"></param>
        /// <returns></returns>
        public static IntPtr GetBitmapHandle(string fileName, int width, int height, ThumbnailOptions options)
        {
            Guid shellItem2Guid = new Guid(IShellItem2Guid);
            int retCode = SHCreateItemFromParsingName(fileName, IntPtr.Zero, ref shellItem2Guid, out IShellItem nativeShellItem);
            if (retCode != 0) throw Marshal.GetExceptionForHR(retCode);
            NativeSize nativeSize = new NativeSize()
            {
                Width = width,
                Height = height
            };
            HResult hr = ((IShellItemImageFactory)nativeShellItem).GetImage(nativeSize, options, out var hBitmap);
#pragma warning disable CA1416 // 验证平台兼容性
            Marshal.ReleaseComObject(nativeShellItem);
#pragma warning restore CA1416 // 验证平台兼容性
            if (hr == HResult.Ok) return hBitmap;
            throw Marshal.GetExceptionForHR((int)hr);
        }
    }
}