diff --git a/src/Camelot.Services.Environment/Implementations/EnvironmentPathService.cs b/src/Camelot.Services.Environment/Implementations/EnvironmentPathService.cs index 983f69b2..888a09d7 100644 --- a/src/Camelot.Services.Environment/Implementations/EnvironmentPathService.cs +++ b/src/Camelot.Services.Environment/Implementations/EnvironmentPathService.cs @@ -16,4 +16,6 @@ public class EnvironmentPathService : IEnvironmentPathService public string GetFileName(string path) => Path.GetFileName(path); public string GetExtension(string path) => Path.GetExtension(path); + + public char GetDirectorySeparator() => Path.DirectorySeparatorChar; } \ No newline at end of file diff --git a/src/Camelot.Services.Environment/Interfaces/IEnvironmentPathService.cs b/src/Camelot.Services.Environment/Interfaces/IEnvironmentPathService.cs index 2e129149..2dbd1f1f 100644 --- a/src/Camelot.Services.Environment/Interfaces/IEnvironmentPathService.cs +++ b/src/Camelot.Services.Environment/Interfaces/IEnvironmentPathService.cs @@ -13,4 +13,6 @@ public interface IEnvironmentPathService string GetFileName(string path); string GetExtension(string path); + + char GetDirectorySeparator(); } \ No newline at end of file diff --git a/src/Camelot.Services/PathService.cs b/src/Camelot.Services/PathService.cs index 53ca2b54..07059e4a 100644 --- a/src/Camelot.Services/PathService.cs +++ b/src/Camelot.Services/PathService.cs @@ -63,6 +63,12 @@ public string GetFileName(string path) return string.IsNullOrEmpty(fileName) ? path : fileName; } + /// + /// Returns the extension of the given path, without the prefix of dot. + /// This is intentionally returns different result than + /// + /// public string GetExtension(string path) { if (path.StartsWith(".")) diff --git a/src/Camelot.ViewModels.Windows/ShellIcons/WindowsIconTypes.cs b/src/Camelot.ViewModels.Windows/ShellIcons/WindowsIconTypes.cs index d75686ee..1a90a128 100644 --- a/src/Camelot.ViewModels.Windows/ShellIcons/WindowsIconTypes.cs +++ b/src/Camelot.ViewModels.Windows/ShellIcons/WindowsIconTypes.cs @@ -8,13 +8,15 @@ public static bool IsIconThatRequiresExtract(string fileName, string extension) { throw new ArgumentNullException(nameof(fileName)); } - + if (string.IsNullOrEmpty(extension)) + { + throw new ArgumentNullException(nameof(extension)); + } if (fileName.Contains('?') || fileName.Contains(',')) { return true; // icon in indexed resource } - - var extensionsOfIcoFiles = new List { ".ico", ".exe", ".dll" , ".cpl", ".appref-ms", ".msc" }; + var extensionsOfIcoFiles = new List { "ico", "exe", "dll" , "cpl", "appref-ms", "msc" }; return extensionsOfIcoFiles.Contains(extension); } diff --git a/src/Camelot.ViewModels.Windows/ShellIcons/WindowsShellIconsService.cs b/src/Camelot.ViewModels.Windows/ShellIcons/WindowsShellIconsService.cs index 6b5d3c0f..d8b09320 100644 --- a/src/Camelot.ViewModels.Windows/ShellIcons/WindowsShellIconsService.cs +++ b/src/Camelot.ViewModels.Windows/ShellIcons/WindowsShellIconsService.cs @@ -25,17 +25,12 @@ public ImageModel GetIconForExtension(string extension) { if (string.IsNullOrEmpty(extension)) { - throw new ArgumentNullException(nameof(extension)); + throw new ArgumentException(extension, nameof(extension)); } - if (!extension.StartsWith(".")) + if (extension.ToLower() == "lnk") { - throw new ArgumentException(nameof(extension)); - } - - if (extension.ToLower() == ".lnk") - { - throw new ArgumentException("Need to resolve .lnk first"); + throw new ArgumentException("Need to resolve 'lnk' first"); } var iconFilename = ShellIcon.GetIconForExtension(extension); @@ -65,11 +60,10 @@ public ImageModel GetIconForPath(string path) { throw new ArgumentOutOfRangeException(nameof(path)); } - - var ext = GetExtension(path); - if (ext == ".lnk") + var ext = GetExtensionAsLowerCase(path); + if (ext == "lnk") { - throw new ArgumentException("Need to resolve .lnk first"); + throw new ArgumentException("Need to resolve 'lnk' first"); } return LoadIcon(path); @@ -84,7 +78,7 @@ private ImageModel LoadIcon(string path) ImageModel result; - var needsExtract = WindowsIconTypes.IsIconThatRequiresExtract(path, GetExtension(path)); + var needsExtract = WindowsIconTypes.IsIconThatRequiresExtract(path, GetExtensionAsLowerCase(path)); if (needsExtract) { var icon = IconExtractor.ExtractIcon(path); @@ -118,18 +112,18 @@ public ShellIconType GetIconType(string filename) throw new ArgumentNullException(nameof(filename)); } - var ext = GetExtension(filename); - - // next extensions require that the icon will be resolved by full path, + var ext = GetExtensionAsLowerCase(filename); + // Next extensions require that the icon will be resolved by full path, // and not just the extension itself. - var extensionForFullPaths = new[] { ".exe", ".cpl", ".appref-ms", ".msc" }; + // As per stanards of this project, extension don't have dot prefix. + var extensionForFullPaths = new[] { "exe", "cpl", "appref-ms", "msc" }; return extensionForFullPaths.Contains(ext) ? ShellIconType.FullPath : ShellIconType.Extension; } - private string GetExtension(string filename) + private string GetExtensionAsLowerCase(string filename) { return _pathService.GetExtension(filename).ToLower(); } diff --git a/src/Camelot.ViewModels.Windows/ShellIcons/WindowsShellLinksService.cs b/src/Camelot.ViewModels.Windows/ShellIcons/WindowsShellLinksService.cs index 482b8c4c..56e2c5e5 100644 --- a/src/Camelot.ViewModels.Windows/ShellIcons/WindowsShellLinksService.cs +++ b/src/Camelot.ViewModels.Windows/ShellIcons/WindowsShellLinksService.cs @@ -25,8 +25,7 @@ public bool IsShellLink(string path) } var ext = _pathService.GetExtension(path).ToLower(); - - return ext == ".lnk"; + return ext == "lnk"; } public string ResolveLink(string path) diff --git a/src/Camelot.ViewModels.Windows/WinApi/ShellIcon.cs b/src/Camelot.ViewModels.Windows/WinApi/ShellIcon.cs index dcb5d0d5..bc3a6d9a 100644 --- a/src/Camelot.ViewModels.Windows/WinApi/ShellIcon.cs +++ b/src/Camelot.ViewModels.Windows/WinApi/ShellIcon.cs @@ -1,4 +1,5 @@ using Camelot.Services.Windows.WinApi; +using System.Diagnostics; namespace Camelot.ViewModels.Windows.WinApi; @@ -11,17 +12,35 @@ public static string GetIconForExtension(string extension) throw new ArgumentNullException(nameof(extension)); } - if (!extension.StartsWith(".")) - { - throw new ArgumentException(nameof(extension)); - } + // But to work with Windows API, we still need to add dot prefix... + extension = "." + extension; const Win32.AssocF assocFlag = Win32.AssocF.None; var currentAppIcon = Win32.AssocQueryString(assocFlag, Win32.AssocStr.AppIconRreference, extension); - return string.IsNullOrEmpty(currentAppIcon) - ? Win32.AssocQueryString(assocFlag, Win32.AssocStr.DefaultIcon, extension) - : currentAppIcon; + string result; + if (IsValid(currentAppIcon)) + { + result = currentAppIcon; + } + else + { + // fallback to use default + result = Win32.AssocQueryString(assocFlag, Win32.AssocStr.DefaultIcon, extension); + } + return result; + } + + private static bool IsValid(string icon) + { + if (string.IsNullOrEmpty(icon)) + return false; + if (icon.TrimStart().StartsWith("%")) + { + // looks like because of invalid values in registry + return false; + } + return true; } } diff --git a/src/Camelot.ViewModels.Windows/WinApi/ShellLinkResolver.cs b/src/Camelot.ViewModels.Windows/WinApi/ShellLinkResolver.cs index 5fa795dc..5f2c0ffd 100644 --- a/src/Camelot.ViewModels.Windows/WinApi/ShellLinkResolver.cs +++ b/src/Camelot.ViewModels.Windows/WinApi/ShellLinkResolver.cs @@ -26,7 +26,7 @@ public string ResolveLink(string path) } var ext = _pathService.GetExtension(path).ToLower(); - if (ext != ".lnk") + if (ext != "lnk") { throw new ArgumentNullException(nameof(path)); }