在文件路径中获取带有表情符号的文件图标
Get file icons with Emoji in the file path
通常获取文件图标效果很好with this approach。
但是如果你的路径包含任何表情符号,就像这样:
会抛出异常
System.ArgumentException:“Arg_ArgumentException Arg_ParamName_Name”
有人知道怎么处理吗?
终于找到解决方法:SHGetFileInfoW。
https://docs.microsoft.com/en-us/windows/win32/api/shellapi/nf-shellapi-shgetfileinfow
SHGetFileInfoW 可以处理类型LPCWSTR,然后可以解码unicode 表情符号。
[Flags]
public enum ShellGetFileInfoFlags : uint
{
/// <summary>
/// Modify SHGFI_ICON, causing the function to retrieve the file's large icon. The SHGFI_ICON flag must also be set.
/// </summary>
LargeIcon = 0x0,
/// <summary>
/// Modify SHGFI_ICON, causing the function to retrieve the file's small icon. Also used to modify SHGFI_SYSICONINDEX,
/// causing the function to return the handle to the system image list that contains small icon images. The SHGFI_ICON
/// and/or SHGFI_SYSICONINDEX flag must also be set.
/// </summary>
SmallIcon = 0x1,
/// <summary>
/// Retrieve the handle to the icon that represents the file and the index of the icon within the system image list.
/// The handle is copied to
/// the hIcon member of the structure specified by psfi, and the index is copied to the iIcon member.
/// </summary>
Icon = 0x100,
/// <summary>
/// Indicates that the function should not attempt to access the file specified by pszPath. Rather, it
/// should act as if the file specified by pszPath exists with the file attributes passed in dwFileAttributes.
/// This flag cannot be combined with the SHGFI_ATTRIBUTES, SHGFI_EXETYPE, or SHGFI_PIDL flags.
/// </summary>
UseFileAttributes = 0x10
}
//Struct used by SHGetFileInfo function
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
protected struct SHFILEINFOW
{
public IntPtr hIcon;
public int iIcon;
public uint dwAttributes;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)]
public string szDisplayName;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 80)]
public string szTypeName;
};
[DllImport("shell32.dll", CharSet = CharSet.Unicode, ExactSpelling = true)]
protected static extern IntPtr SHGetFileInfo(string pszPath, uint dwFileAttributes, ref SHFILEINFO psfi, uint cbSizeFileInfo, ShellGetFileInfoFlags uFlags);
public static BitmapSource GetFolderIcon(string path)
{
try
{
if (Directory.Exists(path))
{
var shinfo = new SHFILEINFOW();
SHGetFileInfoW(path, 0, ref shinfo, (uint)Marshal.SizeOf(shinfo), ShellGetFileInfoFlags.Icon | ShellGetFileInfoFlags.LargeIcon);
using var i = System.Drawing.Icon.FromHandle(shinfo.hIcon);
return i.ToBitmap().ToBitmapSource();
}
}
catch (Exception e)
{
SimpleLogHelper.Fatal(path, e);
}
return null;
}
通常获取文件图标效果很好with this approach。
但是如果你的路径包含任何表情符号,就像这样:
会抛出异常
System.ArgumentException:“Arg_ArgumentException Arg_ParamName_Name”
有人知道怎么处理吗?
终于找到解决方法:SHGetFileInfoW。
https://docs.microsoft.com/en-us/windows/win32/api/shellapi/nf-shellapi-shgetfileinfow
SHGetFileInfoW 可以处理类型LPCWSTR,然后可以解码unicode 表情符号。
[Flags]
public enum ShellGetFileInfoFlags : uint
{
/// <summary>
/// Modify SHGFI_ICON, causing the function to retrieve the file's large icon. The SHGFI_ICON flag must also be set.
/// </summary>
LargeIcon = 0x0,
/// <summary>
/// Modify SHGFI_ICON, causing the function to retrieve the file's small icon. Also used to modify SHGFI_SYSICONINDEX,
/// causing the function to return the handle to the system image list that contains small icon images. The SHGFI_ICON
/// and/or SHGFI_SYSICONINDEX flag must also be set.
/// </summary>
SmallIcon = 0x1,
/// <summary>
/// Retrieve the handle to the icon that represents the file and the index of the icon within the system image list.
/// The handle is copied to
/// the hIcon member of the structure specified by psfi, and the index is copied to the iIcon member.
/// </summary>
Icon = 0x100,
/// <summary>
/// Indicates that the function should not attempt to access the file specified by pszPath. Rather, it
/// should act as if the file specified by pszPath exists with the file attributes passed in dwFileAttributes.
/// This flag cannot be combined with the SHGFI_ATTRIBUTES, SHGFI_EXETYPE, or SHGFI_PIDL flags.
/// </summary>
UseFileAttributes = 0x10
}
//Struct used by SHGetFileInfo function
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
protected struct SHFILEINFOW
{
public IntPtr hIcon;
public int iIcon;
public uint dwAttributes;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)]
public string szDisplayName;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 80)]
public string szTypeName;
};
[DllImport("shell32.dll", CharSet = CharSet.Unicode, ExactSpelling = true)]
protected static extern IntPtr SHGetFileInfo(string pszPath, uint dwFileAttributes, ref SHFILEINFO psfi, uint cbSizeFileInfo, ShellGetFileInfoFlags uFlags);
public static BitmapSource GetFolderIcon(string path)
{
try
{
if (Directory.Exists(path))
{
var shinfo = new SHFILEINFOW();
SHGetFileInfoW(path, 0, ref shinfo, (uint)Marshal.SizeOf(shinfo), ShellGetFileInfoFlags.Icon | ShellGetFileInfoFlags.LargeIcon);
using var i = System.Drawing.Icon.FromHandle(shinfo.hIcon);
return i.ToBitmap().ToBitmapSource();
}
}
catch (Exception e)
{
SimpleLogHelper.Fatal(path, e);
}
return null;
}