在文件路径中获取带有表情符号的文件图标

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