├── Done.gif ├── How To Use.gif ├── App.xaml.cs ├── App.xaml ├── README.md ├── FileIconConsole ├── app.manifest ├── LnkHelper.cs ├── FileIconConsole.csproj ├── ConsoleHelper.cs ├── User32.cs ├── Program.cs ├── ExplorerHelper.cs ├── RegBuilder.cs └── MD5Helper.cs ├── LICENSE ├── FileIconMOD.csproj ├── MainWindow.xaml ├── MD5Helper.cs └── MainWindow.xaml.cs /Done.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sillsun/FileIconMOD/HEAD/Done.gif -------------------------------------------------------------------------------- /How To Use.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sillsun/FileIconMOD/HEAD/How To Use.gif -------------------------------------------------------------------------------- /App.xaml.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Configuration; 4 | using System.Data; 5 | using System.Linq; 6 | using System.Windows; 7 | 8 | namespace FileIconMOD 9 | { 10 | /// 11 | /// App.xaml 的交互逻辑 12 | /// 13 | public partial class App : Application 14 | { 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /App.xaml: -------------------------------------------------------------------------------- 1 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # FileIconMOD 2 | This is a tool which can change files' icon in simple way。 3 | 4 | # 这工具能轻松修改指定类别的文件的图标 5 | 6 | # How to use it 7 | ![image](https://github.com/sillsun/FileIconMOD/blob/master/How%20To%20Use.gif) 8 | 9 | # Done 10 | ![image](https://github.com/sillsun/FileIconMOD/blob/master/Done.gif) 11 | 12 | 13 | # 新版本更新 14 | 1. 优化代码。 15 | 2. 优化交互。 16 | 3. 将需要管理员权限的代码的功能移到FileIconConsole,避免拖拽获取路径的功能应为权限问题而失效。 17 | -------------------------------------------------------------------------------- /FileIconConsole/app.manifest: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /FileIconConsole/LnkHelper.cs: -------------------------------------------------------------------------------- 1 | using IWshRuntimeLibrary; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Text; 6 | 7 | namespace FileIconConsole 8 | { 9 | internal class LnkHelper 10 | { 11 | public static IWshShortcut GetShortcutInfo(string path) 12 | { 13 | WshShell shell = new WshShell(); 14 | IWshShortcut shortcut = (IWshShortcut)shell.CreateShortcut(path); 15 | return shortcut; 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /FileIconConsole/FileIconConsole.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | net40 6 | app.manifest 7 | 8 | 9 | 10 | 11 | 12 | tlbimp 13 | 0 14 | 1 15 | f935dc20-1cf0-11d0-adb9-00c04fd58a0b 16 | 0 17 | false 18 | true 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 sillsun 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /FileIconConsole/ConsoleHelper.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | 6 | namespace FileIconConsole 7 | { 8 | internal class ConsoleHelper 9 | { 10 | 11 | public static Dictionary ConvertToArgDic(string[] args) 12 | { 13 | var argDic = new Dictionary(); 14 | if (args != null) 15 | { 16 | string key = null; 17 | List value = new List(); 18 | for (int i = 0; i < args.Length; i++) 19 | { 20 | if (args[i].StartsWith("-")) 21 | { 22 | if (key != null) 23 | { 24 | if (!argDic.ContainsKey(key)) 25 | { 26 | argDic.Add(key, value.ToArray()); 27 | } 28 | } 29 | key = args[i].ToLower(); 30 | value.Clear(); 31 | } 32 | else 33 | { 34 | value.Add(args[i]); 35 | } 36 | } 37 | if (key != null) 38 | { 39 | if (!argDic.ContainsKey(key)) 40 | { 41 | argDic.Add(key, value.ToArray()); 42 | } 43 | } 44 | } 45 | return argDic; 46 | } 47 | 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /FileIconConsole/User32.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Runtime.InteropServices; 5 | using System.Text; 6 | 7 | namespace FileIconConsole 8 | { 9 | internal class User32 10 | { 11 | public delegate bool CallBack(int hwnd, int y); 12 | 13 | //该函数枚举所有屏幕上的顶层窗口,并将窗口句柄传送给应用程序定义的回调函数。 14 | //回调函数返回FALSE将停止枚举,否则EnumWindows函数继续到所有顶层窗口枚举完为止。 15 | [DllImport("user32.dll")] 16 | public static extern int EnumWindows(CallBack x, int y); 17 | 18 | //该函数将指定窗口的标题条文本(如果存在)拷贝到一个缓存区内 19 | [DllImport("user32.dll")] 20 | public static extern int GetWindowText(int hwnd, StringBuilder lptrString, int nMaxCount); 21 | 22 | //该函数获得一个指定子窗口的父窗口句柄 23 | [DllImport("user32.dll")] 24 | public static extern int GetParent(int hwnd); 25 | 26 | //该函数获得给定窗口的可视状态。 27 | [DllImport("user32.dll")] 28 | public static extern bool IsWindowVisible(int hwnd); 29 | 30 | //获取窗体类名 31 | [DllImport("User32.Dll ")] 32 | public static extern void GetClassName(IntPtr hwnd, StringBuilder s, int nMaxCount); 33 | 34 | //获取窗体的子窗体句柄 35 | [DllImport("User32.dll ")] 36 | public static extern IntPtr FindWindowEx(IntPtr parent, IntPtr childe, string strclass, string FrmText); 37 | 38 | 39 | /// 根据句柄获取类名 40 | public static string GetFormClassName(IntPtr ptr) 41 | { 42 | StringBuilder nameBiulder = new StringBuilder(255); 43 | GetClassName(ptr, nameBiulder, 255); 44 | return nameBiulder.ToString(); 45 | } 46 | 47 | /// 根据句柄获取窗口标题 48 | public static string GetFormTitle(IntPtr ptr) 49 | { 50 | StringBuilder titleBiulder = new StringBuilder(255); 51 | GetWindowText((int)ptr, titleBiulder, 255); 52 | return titleBiulder.ToString(); 53 | } 54 | 55 | 56 | 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /FileIconConsole/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.IO; 3 | using System.Text; 4 | using System.Linq; 5 | namespace FileIconConsole 6 | { 7 | internal class Program 8 | { 9 | static void Main(string[] args) 10 | { 11 | try 12 | { 13 | var argDic = ConsoleHelper.ConvertToArgDic(args); 14 | foreach (var item in argDic) 15 | { 16 | Console.WriteLine($"{item.Key} : {item.Value.FirstOrDefault()}"); 17 | } 18 | 19 | if (argDic.TryGetValue("-type", out var type)) 20 | { 21 | var reg = new RegBuilder(argDic); 22 | using (StreamWriter sr = new StreamWriter("run.reg", false, Encoding.Default)) 23 | { 24 | sr.Write(reg.ToString()); 25 | } 26 | var p1 = System.Diagnostics.Process.Start("regedit.exe", "/s run.reg"); 27 | p1.WaitForExit(); 28 | } 29 | 30 | 31 | RestartExplorer(); 32 | } 33 | catch (Exception ex) 34 | { 35 | Console.ForegroundColor = ConsoleColor.Red; 36 | Console.WriteLine(ex.ToString()); 37 | Console.ReadLine(); 38 | } 39 | 40 | 41 | 42 | } 43 | 44 | static void RestartExplorer() 45 | { 46 | var paths = ExplorerHelper.GetOpenedDirectory(); 47 | 48 | var p2 = System.Diagnostics.Process.Start("cmd.exe", "/c taskkill /f /im Explorer.exe"); 49 | p2.WaitForExit(); 50 | var p3 = System.Diagnostics.Process.Start("cmd.exe", "/c start explorer.exe"); 51 | p3.WaitForExit(); 52 | 53 | paths.Reverse(); 54 | paths.ForEach(p => 55 | { 56 | if (Directory.Exists(p)) 57 | { 58 | var pp = System.Diagnostics.Process.Start("cmd.exe", $"/c explorer.exe {p}"); 59 | pp.WaitForExit(); 60 | Console.WriteLine($"Start : {p}"); 61 | } 62 | }); 63 | } 64 | } 65 | 66 | 67 | 68 | } 69 | -------------------------------------------------------------------------------- /FileIconConsole/ExplorerHelper.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | 6 | namespace FileIconConsole 7 | { 8 | internal class ExplorerHelper 9 | { 10 | public static List GetOpenedDirectory() 11 | { 12 | var paths = new List(); 13 | User32.EnumWindows((hwnd, IParam) => 14 | { 15 | int pHwnd = User32.GetParent(hwnd); 16 | //如果再没有父窗口并且为可视状态的窗口,则遍历 17 | if (pHwnd == 0 && User32.IsWindowVisible(hwnd) == true) 18 | { 19 | IntPtr cabinetWClassIntPtr = new IntPtr(hwnd); 20 | string cabinetWClassName = User32.GetFormClassName(cabinetWClassIntPtr); 21 | //如果类名为CabinetWClass ,则为explorer窗口,可以通过spy++查看窗口类型 22 | if (cabinetWClassName.Equals("CabinetWClass", StringComparison.OrdinalIgnoreCase)) 23 | { 24 | //下面为一层层往下查找,直到找到资源管理器的地址窗体,通过他获取窗体地址 25 | IntPtr workerWIntPtr = User32.FindWindowEx(cabinetWClassIntPtr, IntPtr.Zero, "WorkerW", null); 26 | IntPtr reBarWindow32IntPtr = User32.FindWindowEx(workerWIntPtr, IntPtr.Zero, "ReBarWindow32", null); 27 | IntPtr addressBandRootIntPtr = User32.FindWindowEx(reBarWindow32IntPtr, IntPtr.Zero, "Address Band Root", null); 28 | IntPtr msctls_progress32IntPtr = User32.FindWindowEx(addressBandRootIntPtr, IntPtr.Zero, "msctls_progress32", null); 29 | IntPtr breadcrumbParentIntPtr = User32.FindWindowEx(msctls_progress32IntPtr, IntPtr.Zero, "Breadcrumb Parent", null); 30 | IntPtr toolbarWindow32IntPtr = User32.FindWindowEx(breadcrumbParentIntPtr, IntPtr.Zero, "ToolbarWindow32", null); 31 | 32 | 33 | string title = User32.GetFormTitle(toolbarWindow32IntPtr); 34 | int index = title.IndexOf(':') + 1; 35 | string path = title.Substring(index, title.Length - index).TrimStart(); 36 | paths.Add(path); 37 | } 38 | } 39 | return true; 40 | }, 0); 41 | 42 | return paths; 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /FileIconMOD.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {9709F215-27B8-470E-A23C-DEA12C06019B} 8 | WinExe 9 | FileIconMOD 10 | FileIconMOD 11 | v4.0 12 | 512 13 | {60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} 14 | 4 15 | true 16 | 17 | 18 | AnyCPU 19 | true 20 | full 21 | false 22 | bin\Debug\ 23 | DEBUG;TRACE 24 | prompt 25 | 4 26 | 27 | 28 | AnyCPU 29 | pdbonly 30 | true 31 | bin\Release\ 32 | TRACE 33 | prompt 34 | 4 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 4.0 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | MSBuild:Compile 54 | Designer 55 | 56 | 57 | MSBuild:Compile 58 | Designer 59 | 60 | 61 | App.xaml 62 | Code 63 | 64 | 65 | MainWindow.xaml 66 | Code 67 | 68 | 69 | 70 | 71 | 72 | Code 73 | 74 | 75 | True 76 | True 77 | Resources.resx 78 | 79 | 80 | True 81 | Settings.settings 82 | True 83 | 84 | 85 | ResXFileCodeGenerator 86 | Resources.Designer.cs 87 | 88 | 89 | SettingsSingleFileGenerator 90 | Settings.Designer.cs 91 | 92 | 93 | 94 | 95 | Always 96 | 97 | 98 | 99 | 100 | -------------------------------------------------------------------------------- /FileIconConsole/RegBuilder.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using System.Linq; 5 | using System.Text; 6 | 7 | namespace FileIconConsole 8 | { 9 | internal class RegBuilder 10 | { 11 | StringBuilder sb = new StringBuilder(); 12 | 13 | string Extension = null; 14 | string IconPath = null; 15 | string ExePath = null; 16 | bool IsClean = false; 17 | 18 | 19 | public override string ToString() 20 | { 21 | return sb.ToString(); 22 | } 23 | 24 | public RegBuilder(Dictionary argDic) 25 | { 26 | if (argDic.TryGetValue("-type", out var type)) 27 | { 28 | Extension = type[0].StartsWith(".") ? type[0].Substring(1) : type[0]; 29 | } 30 | 31 | if (argDic.ContainsKey("-clean")) 32 | { 33 | IsClean = true; 34 | } 35 | 36 | if (argDic.TryGetValue("-icon", out var icon)) 37 | { 38 | IconPath = icon[0]; 39 | } 40 | 41 | if (argDic.TryGetValue("-open", out var open)) 42 | { 43 | ExePath = open[0]; 44 | } 45 | 46 | 47 | Create(); 48 | AppendIcon(); 49 | AppendOpenCommand(); 50 | } 51 | 52 | 53 | 54 | void Create() 55 | { 56 | sb.AppendLine("Windows Registry Editor Version 5.00"); 57 | if (IsClean) 58 | { 59 | sb.AppendLine($"[-HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\FileExts\\.{Extension}]"); 60 | sb.AppendLine($"[-HKEY_CLASSES_ROOT\\.{Extension}]"); 61 | sb.AppendLine($"[-HKEY_CLASSES_ROOT\\{Extension}_xxfile\\DefaultIcon]"); 62 | sb.AppendLine($"[-HKEY_CLASSES_ROOT\\{Extension}_xxfile\\shell\\open\\command]"); 63 | } 64 | 65 | if (IconPath != null || ExePath != null) 66 | { 67 | sb.AppendLine($"[HKEY_CLASSES_ROOT\\.{Extension}]"); 68 | sb.AppendLine($"@=\"{Extension}_xxfile\""); 69 | } 70 | 71 | } 72 | 73 | 74 | 75 | public void AppendIcon() 76 | { 77 | if (IconPath != null) 78 | { 79 | var newIconPath = CopyIcon(IconPath); 80 | sb.AppendLine($"[HKEY_CLASSES_ROOT\\{Extension}_xxfile\\DefaultIcon]"); 81 | sb.AppendLine($"@=\"{newIconPath.Replace("\\", "\\\\")}\""); 82 | } 83 | 84 | } 85 | 86 | static string CopyIcon(string iconPath) 87 | { 88 | if (iconPath == null) 89 | { 90 | return iconPath; 91 | } 92 | string xxIconSavePath = @"C:\Windows\System32\xxicon"; 93 | if (!Directory.Exists(xxIconSavePath)) 94 | { 95 | Directory.CreateDirectory(xxIconSavePath); 96 | } 97 | 98 | if (File.Exists(iconPath)) 99 | { 100 | var iconFile = new FileInfo(iconPath); 101 | var iconMd5 = MD5Helper.CalcMD5L(iconFile); 102 | var newIconName = $"{iconMd5}{iconFile.Extension}"; 103 | 104 | var newPath = $"{xxIconSavePath}\\{newIconName}"; 105 | if (!File.Exists(newPath)) 106 | { 107 | File.Copy(iconPath, newPath); 108 | } 109 | return newPath; 110 | } 111 | else 112 | { 113 | return iconPath; 114 | } 115 | } 116 | 117 | 118 | 119 | 120 | 121 | public void AppendOpenCommand() 122 | { 123 | if (ExePath != null) 124 | { 125 | if (File.Exists(ExePath)) 126 | { 127 | var fileInfo = new FileInfo(ExePath); 128 | if (fileInfo.Extension == ".lnk") 129 | { 130 | ExePath = LnkHelper.GetShortcutInfo(ExePath).TargetPath; 131 | } 132 | } 133 | sb.AppendLine($"[HKEY_CLASSES_ROOT\\{Extension}_xxfile\\shell\\open\\command]"); 134 | sb.AppendLine($"@=\"\\\"{ExePath.Replace("\\", "\\\\")}\\\" \\\"%1\\\"\""); 135 | } 136 | 137 | } 138 | 139 | 140 | } 141 | } 142 | -------------------------------------------------------------------------------- /MainWindow.xaml: -------------------------------------------------------------------------------- 1 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 |