diff --git a/SafeExamBrowser.UserInterface.Shared/Utilities/IconLoader.cs b/SafeExamBrowser.UserInterface.Shared/Utilities/IconLoader.cs index 982b5c19..befb1427 100644 --- a/SafeExamBrowser.UserInterface.Shared/Utilities/IconLoader.cs +++ b/SafeExamBrowser.UserInterface.Shared/Utilities/IconLoader.cs @@ -7,8 +7,10 @@ */ using System; +using System.Drawing; using System.IO; using System.Runtime.InteropServices; +using System.Text; using System.Windows; using System.Windows.Interop; using System.Windows.Media; @@ -18,6 +20,7 @@ namespace SafeExamBrowser.UserInterface.Shared.Utilities { public static class IconLoader { + private const int MAX_PATH_CHARS = 260; private const uint SHGFI_ICON = 0x100; private const uint SHGFI_LARGEICON = 0x0; private const uint SHGFI_SMALLICON = 0x1; @@ -35,15 +38,36 @@ namespace SafeExamBrowser.UserInterface.Shared.Utilities public static ImageSource LoadIconFor(FileInfo file) { - using (var icon = System.Drawing.Icon.ExtractAssociatedIcon(file.FullName)) + try { - return Imaging.CreateBitmapSourceFromHIcon(icon.Handle, Int32Rect.Empty, BitmapSizeOptions.FromEmptyOptions()); + using (var icon = Icon.ExtractAssociatedIcon(file.FullName)) + { + return Imaging.CreateBitmapSourceFromHIcon(icon.Handle, Int32Rect.Empty, BitmapSizeOptions.FromEmptyOptions()); + } + } + catch + { + // Icon.ExtractAssociatedIcon(...) has proven to be error-prone, especially for network paths. Thus we try to use the native API + // in those cases, see also https://stackoverflow.com/questions/1842226/how-to-get-the-associated-icon-from-a-network-share-file. + var builder = new StringBuilder(MAX_PATH_CHARS); + + builder.Append(file.FullName); + + var handle = ExtractAssociatedIcon(IntPtr.Zero, builder, out _); + + using (var icon = Icon.FromHandle(handle)) + { + return Imaging.CreateBitmapSourceFromHIcon(icon.Handle, Int32Rect.Empty, BitmapSizeOptions.FromEmptyOptions()); + } } } [DllImport("user32.dll")] private static extern int DestroyIcon(IntPtr hIcon); + [DllImport("shell32.dll", CharSet = CharSet.Unicode)] + static extern IntPtr ExtractAssociatedIcon(IntPtr hInst, StringBuilder lpIconPath, out ushort lpiIcon); + [DllImport("shell32.dll", CharSet = CharSet.Unicode)] private static extern IntPtr SHGetFileInfo(string pszPath, uint dwFileAttributes, ref SHFILEINFO psfi, uint cbSizeFileInfo, uint uFlags);