这几天开发遇到一个需求:
将自定义文件后缀添加默认图标双击
自定义的文件后缀可以自动关联到指定的应用程序并自动打开
上述第一、二两点其实是一个需求,本质是和注册表有关的操作,在注册表中写入默认图标、默认文件后缀、指定打开文件,一旦明白这个思路代码就非常清晰了。
代码中我们写入了两个注册表。
第一个结构如下图所示,其中DefaultIcon定义的是默认图标地址,Command中存放的是指定识别的软件的运行exe路径。
第二个注册表如下图所示,将默认文件后缀和第一个注册表进行关联,这样就可以进行识别。
添加进去之后,我们发现双击文件可以打开软件,但是默认图标并没有刷新,经过查询,需要重启,但这样不是太low了吗,难道每个用户安装一次软件都要重启吗,这时候就需要实现自动对注册表进行刷新,直接引用即可,代码如下。
[DllImport("shell32.dll")] public static extern void SHChangeNotify(uint wEventId, uint uFlags, IntPtr dwItem1, IntPtr dwItem2); SHChangeNotify(0x8000000, 0, IntPtr.Zero, IntPtr.Zero);
using System; using System.Collections.Generic; using System.Windows.Forms; using Microsoft.Win32; namespace AppC { static class Program { /// <summary> /// 应用程序的主入口点。 /// </summary> [STAThread] static void Main(string[] args) { Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); /// 是否通过关联打开的软件 if (args.Length > 0) { string path=""; for(int i=0;i<args.Length;i++) path+=args[i]+" "; path=path.TrimEnd(' '); Console.WriteLine(path); Console.ReadKey(); //Application.Run(new mainForm(path)); } else { string keyName; string keyValue; keyName = "C2File"; keyValue = "C2文件"; RegistryKey isExCommand = null; bool isCreateRegistry = true; try { /// 检查 文件关联是否创建 isExCommand = Registry.ClassesRoot.OpenSubKey(keyName); if (isExCommand == null) { isCreateRegistry = true; } else { if (isExCommand.GetValue("Create").ToString() == Application.ExecutablePath.ToString()) { isCreateRegistry = false; } else { Registry.ClassesRoot.DeleteSubKeyTree(keyName); isCreateRegistry = true; } } } catch (Exception) { isCreateRegistry = true; } /// 假如 文件关联 还没有创建,或是关联位置已被改变 //if (isCreateRegistry) { try { RegistryKey key, keyico; key = Registry.ClassesRoot.CreateSubKey(keyName); key.SetValue("Create", Application.ExecutablePath.ToString()); keyico = key.CreateSubKey("DefaultIcon"); keyico.SetValue("", Application.ExecutablePath + ",0"); /* string icoFind = Path.Combine("Resources", "C2", "Icon"); string icoFile = Path.Combine(System.Windows.Forms.Application.StartupPath, icoFind, "Icon.ico"); iconKey.SetValue(String.Empty, icoFile); */ key.SetValue("", keyValue); key = key.CreateSubKey("Shell"); key = key.CreateSubKey("Open"); key = key.CreateSubKey("Command"); /// 关联的位置 key.SetValue("", Application.ExecutablePath.ToString() + @" %1/"); /// 关联的文件扩展名, keyName = ".c2"; keyValue = "C2File"; key = Registry.ClassesRoot.CreateSubKey(keyName); key.SetValue("", keyValue); } catch (Exception) { } } //Application.Run(new mainForm("")); } } } }
但是还有一个问题,就是打包,由于我们对注册表的写入是写在Main函数里的,如果用Visual Studio自带的工具进行打包的话,也就是说每次用户在打开软件都会进行一次注册表读写的判断,虽然用户不感知,但是这样并不好。所以我们并不打算将注册表的写入放在Main函数中,而是使用Inno Script Studio这个工具进行美化,将注册表的写入放在里面,这样用户只会在安装的时候写入注册表,删除软件注册表也会自动清空。
#define MyAppExeName "软件.exe" #define AppIconName "默认图标路径" [Registry] Root:HKCU;Subkey: "{#MyRegInstallPath_sk}" ; ValueType:string; ValueName:"{#MyRegInstallPath_vn}"; ValueData:"{app}";Flags:uninsdeletekeyifempty Root: HKCR; Subkey: ".c2"; Flags: uninsdeletekey Root: HKCR; Subkey: ".c2"; ValueType: string; ValueName: ""; ValueData: "C2File" Root: HKCR; Subkey: "C2File"; Flags: uninsdeletekey Root: HKCR; Subkey: "C2File\DefaultIcon"; Flags: uninsdeletekey Root: HKCR; Subkey: "C2File\DefaultIcon"; ValueType: string; ValueName: ""; ValueData: "{app}\{#AppIconName}"; Flags: Root: HKCR; Subkey: "C2File\shell"; Flags: uninsdeletekey Root: HKCR; Subkey: "C2File\shell\open"; Flags: uninsdeletekey Root: HKCR; Subkey: "C2File\shell\open\command"; Flags: uninsdeletekey Root: HKCR; Subkey: "C2File\shell\open\command"; ValueType: string; ValueName: ""; ValueData: "{app}\{#MyAppExeName} ""%1"""; Flags:
声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。
评论(0)