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