Răsfoiți Sursa

更新3.2版本

蓝点lilac 4 ani în urmă
părinte
comite
c68f10d070
80 a modificat fișierele cu 2218 adăugiri și 1110 ștergeri
  1. BIN
      AppImage.png
  2. 2 2
      ContextMenuManager.sln
  3. 1 1
      ContextMenuManager/App.config
  4. 7 1
      ContextMenuManager/AppConfig.cs
  5. 67 58
      ContextMenuManager/AppImage.cs
  6. 15 4
      ContextMenuManager/AppString.cs
  7. 33 38
      ContextMenuManager/BluePointLilac.Controls/MyListBox.cs
  8. 2 1
      ContextMenuManager/BluePointLilac.Controls/MyMainForm.cs
  9. 20 3
      ContextMenuManager/BluePointLilac.Controls/MyStatusBar.cs
  10. 17 10
      ContextMenuManager/BluePointLilac.Controls/MyToolBar.cs
  11. 22 0
      ContextMenuManager/BluePointLilac.Methods/ComboBoxExtension.cs
  12. 0 7
      ContextMenuManager/BluePointLilac.Methods/ControlExtension.cs
  13. 139 0
      ContextMenuManager/BluePointLilac.Methods/ElevatedFileDroper.cs
  14. 28 6
      ContextMenuManager/BluePointLilac.Methods/ExternalProgram.cs
  15. 58 1
      ContextMenuManager/BluePointLilac.Methods/FileExtension.cs
  16. 1 0
      ContextMenuManager/BluePointLilac.Methods/ImageExtension.cs
  17. 61 44
      ContextMenuManager/BluePointLilac.Methods/ObjectPath.cs
  18. 5 4
      ContextMenuManager/BluePointLilac.Methods/RegTrustedInstaller.cs
  19. 23 8
      ContextMenuManager/BluePointLilac.Methods/RegistryEx.cs
  20. 1 1
      ContextMenuManager/BluePointLilac.Methods/RichTextBoxExtension.cs
  21. 307 0
      ContextMenuManager/BluePointLilac.Methods/ShellLink.cs
  22. 2 2
      ContextMenuManager/BluePointLilac.Methods/SingleInstance.cs
  23. 319 0
      ContextMenuManager/BluePointLilac.Methods/WinXHasher.cs
  24. 1 1
      ContextMenuManager/BluePointLilac.Methods/WindowsOsVersion.cs
  25. 0 202
      ContextMenuManager/BluePointLilac.Methods/WshShortcut.cs
  26. 21 16
      ContextMenuManager/ContextMenuManager.csproj
  27. 22 16
      ContextMenuManager/Controls/AboutApp.cs
  28. 0 151
      ContextMenuManager/Controls/AddGuidDicDialog.cs
  29. 3 1
      ContextMenuManager/Controls/EnhanceMenusItem.cs
  30. 7 3
      ContextMenuManager/Controls/EnhanceMenusList.cs
  31. 11 6
      ContextMenuManager/Controls/FileExtensionDialog.cs
  32. 7 2
      ContextMenuManager/Controls/GuidBlockedItem.cs
  33. 10 1
      ContextMenuManager/Controls/Interfaces/IChkVisibleItem.cs
  34. 2 0
      ContextMenuManager/Controls/Interfaces/IFoldGroupItem.cs
  35. 6 5
      ContextMenuManager/Controls/Interfaces/ITsiAdministratorItem.cs
  36. 1 1
      ContextMenuManager/Controls/Interfaces/ITsiDeleteItem.cs
  37. 150 4
      ContextMenuManager/Controls/Interfaces/ITsiGuidItem.cs
  38. 16 18
      ContextMenuManager/Controls/Interfaces/ITsiIconItem.cs
  39. 6 2
      ContextMenuManager/Controls/Interfaces/ITsiRegExportItem.cs
  40. 8 8
      ContextMenuManager/Controls/Interfaces/ITsiShortcutCommandItem.cs
  41. 8 1
      ContextMenuManager/Controls/Interfaces/ITsiTextItem.cs
  42. 2 2
      ContextMenuManager/Controls/NewItem.cs
  43. 3 2
      ContextMenuManager/Controls/NewLnkFileDialog.cs
  44. 1 1
      ContextMenuManager/Controls/NewOpenWithDialog.cs
  45. 18 5
      ContextMenuManager/Controls/NewShellDialog.cs
  46. 2 1
      ContextMenuManager/Controls/OpenWithList.cs
  47. 22 4
      ContextMenuManager/Controls/RuleItem.cs
  48. 14 8
      ContextMenuManager/Controls/SelectDialog.cs
  49. 17 10
      ContextMenuManager/Controls/SendToItem.cs
  50. 5 6
      ContextMenuManager/Controls/SendToList.cs
  51. 9 5
      ContextMenuManager/Controls/ShellItem.cs
  52. 343 69
      ContextMenuManager/Controls/ShellList.cs
  53. 11 17
      ContextMenuManager/Controls/ShellNewItem.cs
  54. 71 65
      ContextMenuManager/Controls/ShellNewList.cs
  55. 1 2
      ContextMenuManager/Controls/ShellStoreDialog.cs
  56. 2 3
      ContextMenuManager/Controls/ShellSubMenuDialog.cs
  57. 0 1
      ContextMenuManager/Controls/ThirdRulesList.cs
  58. 2 0
      ContextMenuManager/Controls/TranslateDialog.cs
  59. 14 15
      ContextMenuManager/Controls/WinXItem.cs
  60. 7 42
      ContextMenuManager/Controls/WinXList.cs
  61. 3 3
      ContextMenuManager/GuidInfo.cs
  62. 45 27
      ContextMenuManager/MainForm.cs
  63. 5 5
      ContextMenuManager/Properties/App.manifest
  64. 2 2
      ContextMenuManager/Properties/AssemblyInfo.cs
  65. 12 22
      ContextMenuManager/Properties/Resources.Designer.cs
  66. 6 9
      ContextMenuManager/Properties/Resources.resx
  67. BIN
      ContextMenuManager/Properties/Resources/HashLnk/HashLnk_32.exe
  68. BIN
      ContextMenuManager/Properties/Resources/HashLnk/HashLnk_64.exe
  69. BIN
      ContextMenuManager/Properties/Resources/Images/Jump.png
  70. 18 8
      ContextMenuManager/Properties/Resources/Texts/AppLanguageDic.ini
  71. 59 16
      ContextMenuManager/Properties/Resources/Texts/EnhanceMenusDic.xml
  72. 78 59
      ContextMenuManager/Properties/Resources/Texts/GuidInfosDic.ini
  73. 3 3
      ContextMenuManager/Updater.cs
  74. 12 3
      Donate.md
  75. 1 2
      README-en.md
  76. 1 2
      README.md
  77. 3 3
      Update.ini
  78. 3 41
      languages/en-US.ini
  79. 3 13
      languages/ja-JP.ini
  80. 11 5
      languages/zh-CN.ini

BIN
AppImage.png


+ 2 - 2
ContextMenuManager.sln

@@ -1,7 +1,7 @@
 
 Microsoft Visual Studio Solution File, Format Version 12.00
-# Visual Studio 15
-VisualStudioVersion = 15.0.28307.1267
+# Visual Studio Version 16
+VisualStudioVersion = 16.0.31005.135
 MinimumVisualStudioVersion = 10.0.40219.1
 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ContextMenuManager", "ContextMenuManager\ContextMenuManager.csproj", "{EF7E60E9-3565-42BA-AFB3-7FE73A1B011C}"
 EndProject

+ 1 - 1
ContextMenuManager/App.config

@@ -2,7 +2,7 @@
 <configuration>
   <startup>
     
-  <supportedRuntime version="v2.0.50727"/></startup>
+  <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0"/></startup>
   <runtime>
     <legacyCorruptedStateExceptionsPolicy enabled="true"/>
     <EnableWindowsFormsHighDpiAutoResizing enabled="true"/>

+ 7 - 1
ContextMenuManager/AppConfig.cs

@@ -36,7 +36,7 @@ namespace ContextMenuManager
         public static string WebThirdRulesDic = $@"{WebDicsDir}\{THIRDRULESDICXML}";
         public static string UserThirdRulesDic = $@"{UserDicsDir}\{THIRDRULESDICXML}";
         public static string WebEnhanceMenusDic = $@"{WebDicsDir}\{ENHANCEMENUSICXML}";
-        public static string UserEnhanceMenusDic = $@"{UserDicsDir}\{ENHANCEMENUSICXML}";
+        public static string UserEnhanceMenusDic = $@"{WebDicsDir}\{ENHANCEMENUSICXML}";
         public static string WebUwpModeItemsDic = $@"{UserDicsDir}\{UWPMODEITEMSDICXML}";
         public static string UserUwpModeItemsDic = $@"{UserDicsDir}\{UWPMODEITEMSDICXML}";
         public static string HashLnkExePath = $@"{ProgramsDir}\HashLnk.exe";
@@ -159,5 +159,11 @@ namespace ContextMenuManager
                 SetGeneralValue("Version", value);
             }
         }
+
+        public static bool HideDisabledItems
+        {
+            get => GetGeneralValue("HideDisabledItems") == "1";
+            set => SetGeneralValue("HideDisabledItems", value ? 1 : 0);
+        }
     }
 }

+ 67 - 58
ContextMenuManager/AppImage.cs

@@ -7,87 +7,96 @@ namespace ContextMenuManager
     public static class AppImage
     {
         private static readonly double Scale = HighDpi.DpiScale / 1.5;
-        ///<summary>主页图标</summary>
+        ///<summary>主页</summary>
         public static readonly Image Home = Resources.Home.ResizeImage(Scale);
-        ///<summary>文件类型图标</summary>
+        ///<summary>文件类型</summary>
         public static readonly Image Type = Resources.Type.ResizeImage(Scale);
-        ///<summary>五角星图标</summary>
+        ///<summary>五角星</summary>
         public static readonly Image Star = Resources.Star.ResizeImage(Scale);
-        ///<summary>刷新图标</summary>
+        ///<summary>刷新</summary>
         public static readonly Image Refresh = Resources.Refresh.ResizeImage(Scale);
-        ///<summary>关于问号图标</summary>
+        ///<summary>关于问号</summary>
         public static readonly Image About = Resources.About.ResizeImage(Scale);
-        ///<summary>设置按钮图标</summary>
+        ///<summary>设置按钮</summary>
         public static readonly Image Setting = Resources.Setting.ResizeImage(Scale);
-        ///<summary>开关打开状态图片</summary>
+        ///<summary>开关打开状态</summary>
         public static readonly Image TurnOn = Resources.TurnOn.ResizeImage(Scale);
-        ///<summary>开关关闭状态图片</summary>
+        ///<summary>开关关闭状态</summary>
         public static readonly Image TurnOff = Resources.TurnOff.ResizeImage(Scale);
-        ///<summary>编辑子项图标</summary>
+        ///<summary>编辑子项</summary>
         public static readonly Image SubItems = Resources.SubItems.ResizeImage(Scale);
-        ///<summary>删除图标</summary>
+        ///<summary>删除</summary>
         public static readonly Image Delete = Resources.Delete.ResizeImage(Scale);
-        ///<summary>添加图标</summary>
+        ///<summary>添加</summary>
         public static readonly Image AddNewItem = Resources.Add.ResizeImage(Scale);
-        ///<summary>添加已有项目图标</summary>
+        ///<summary>添加已有项目</summary>
         public static readonly Image AddExisting = Resources.AddExisting.ResizeImage(Scale);
-        ///<summary>添加分割线图标</summary>
+        ///<summary>添加分割线</summary>
         public static readonly Image AddSeparator = Resources.AddSeparator.ResizeImage(Scale);
-        ///<summary>打开图标</summary>
+        ///<summary>打开</summary>
         public static readonly Image Open = Resources.Open.ResizeImage(Scale);
-        ///<summary>下载图标</summary>
+        ///<summary>下载</summary>
         public static readonly Image DownLoad = Resources.DownLoad.ResizeImage(Scale);
-        ///<summary>翻译图标</summary>
+        ///<summary>翻译</summary>
         public static readonly Image Translate = Resources.Translate.ResizeImage(Scale);
-        ///<summary>上图标</summary>
+        ///<summary>上</summary>
         public static readonly Image Up = Resources.Up.ResizeImage(Scale);
-        ///<summary>下图标</summary>
+        ///<summary>下</summary>
         public static readonly Image Down = Up.RotateImage(RotateFlipType.Rotate180FlipNone);
-        ///<summary>新建项目图标</summary>
+        ///<summary>新建项目</summary>
         public static readonly Image NewItem = Resources.NewItem.ResizeImage(Scale);
-        ///<summary>新建文件夹图标</summary>
+        ///<summary>新建文件夹</summary>
         public static readonly Image NewFolder = Resources.NewFolder.ResizeImage(Scale);
-        ///<summary>自定义图标</summary>
+        ///<summary>自定义</summary>
         public static readonly Image Custom = Resources.Custom.ResizeImage(Scale);
-        ///<summary>选择图标</summary>
+        ///<summary>选择</summary>
         public static readonly Image Select = Resources.Select.ResizeImage(Scale);
-        ///<summary>Microsoft Store图标</summary>
+        ///<summary>跳转</summary>
+        public static readonly Image Jump = Resources.Jump.ResizeImage(Scale);
+        ///<summary>Microsoft Store</summary>
         public static readonly Image MicrosoftStore = Resources.MicrosoftStore.ResizeImage(Scale);
-        ///<summary>dll文件默认图标</summary>
-        public static readonly Image DllDefaultIcon = ResourceIcon.GetExtensionIcon(".dll").ToBitmap();
-        ///<summary>资源不存在图标</summary>
-        public static readonly Image NotFound = ResourceIcon.GetIcon("imageres.dll", -2).ToBitmap();
+        ///<summary>系统文件</summary>
+        public static readonly Image SystemFile = GetIconImage("imageres.dll", -67);
+        ///<summary>资源不存在</summary>
+        public static readonly Image NotFound = GetIconImage("imageres.dll", -2);
         ///<summary>管理员小盾牌</summary>
-        public static readonly Image Shield = ResourceIcon.GetIcon("imageres.dll", -78).ToBitmap();
-        ///<summary>资源管理器图标</summary>
-        public static readonly Image Explorer = ResourceIcon.GetIcon("explorer.exe", 0).ToBitmap();
-        ///<summary>命令提示符图标</summary>
-        public static readonly Image Cmd = ResourceIcon.GetIcon("cmd.exe", 0).ToBitmap();
-        ///<summary>重启Explorer图标</summary>
-        public static readonly Image RestartExplorer = ResourceIcon.GetIcon("shell32.dll", 238).ToBitmap();
-        ///<summary>网络驱动器图标</summary>
-        public static readonly Image NetworkDrive = ResourceIcon.GetIcon("imageres.dll", -33).ToBitmap();
-        ///<summary>发送到图标</summary>
-        public static readonly Image SendTo = ResourceIcon.GetIcon("imageres.dll", -185).ToBitmap();
-        ///<summary>回收站图标</summary>
-        public static readonly Image RecycleBin = ResourceIcon.GetIcon("imageres.dll", -55).ToBitmap();
-        ///<summary>此电脑图标</summary>
-        public static readonly Image Computer = ResourceIcon.GetIcon("imageres.dll", -109).ToBitmap();
-        ///<summary>磁盘图标</summary>
-        public static readonly Image Drive = ResourceIcon.GetIcon("imageres.dll", -30).ToBitmap();
-        ///<summary>文件图标</summary>
-        public static readonly Image File = ResourceIcon.GetIcon("imageres.dll", -19).ToBitmap();
-        ///<summary>文件夹图标</summary>
-        public static readonly Image Folder = ResourceIcon.GetIcon("imageres.dll", -3).ToBitmap();
-        ///<summary>目录图标</summary>
-        public static readonly Image Directory = ResourceIcon.GetIcon("imageres.dll", -162).ToBitmap();
-        ///<summary目录背景图标</summary>
-        public static readonly Image Background = ResourceIcon.GetIcon("imageres.dll", 0).ToBitmap();
-        ///<summary>桌面图标</summary>
-        public static readonly Image Desktop = ResourceIcon.GetIcon("imageres.dll", -183).ToBitmap();
-        ///<summary>所有对象图标</summary>
-        public static readonly Image AllObjects = ResourceIcon.GetIcon("imageres.dll", -117).ToBitmap();
-        ///<summary>锁定图标</summary>
-        public static readonly Image Lock = ResourceIcon.GetIcon("imageres.dll", -59).ToBitmap();
+        public static readonly Image Shield = GetIconImage("imageres.dll", -78);
+        ///<summary>资源管理器</summary>
+        public static readonly Image Explorer = GetIconImage("explorer.exe", 0);
+        ///<summary>命令提示符</summary>
+        public static readonly Image Cmd = GetIconImage("cmd.exe", 0);
+        ///<summary>重启Explorer</summary>
+        public static readonly Image RestartExplorer = GetIconImage("shell32.dll", 238);
+        ///<summary>网络驱动器</summary>
+        public static readonly Image NetworkDrive = GetIconImage("imageres.dll", -33);
+        ///<summary>发送到</summary>
+        public static readonly Image SendTo = GetIconImage("imageres.dll", -185);
+        ///<summary>回收站</summary>
+        public static readonly Image RecycleBin = GetIconImage("imageres.dll", -55);
+        ///<summary>此电脑</summary>
+        public static readonly Image Computer = GetIconImage("imageres.dll", -109);
+        ///<summary>磁盘</summary>
+        public static readonly Image Drive = GetIconImage("imageres.dll", -30);
+        ///<summary>文件</summary>
+        public static readonly Image File = GetIconImage("imageres.dll", -19);
+        ///<summary>文件夹</summary>
+        public static readonly Image Folder = GetIconImage("imageres.dll", -3);
+        ///<summary>目录</summary>
+        public static readonly Image Directory = GetIconImage("imageres.dll", -162);
+        ///<summary目录背景</summary>
+        public static readonly Image Background = GetIconImage("imageres.dll", 0);
+        ///<summary>桌面</summary>
+        public static readonly Image Desktop = GetIconImage("imageres.dll", -183);
+        ///<summary>所有对象</summary>
+        public static readonly Image AllObjects = GetIconImage("imageres.dll", -117);
+        ///<summary>锁定</summary>
+        public static readonly Image Lock = GetIconImage("imageres.dll", -59);
+        ///<summary>快捷方式图标</summary>
+        public static readonly Image LnkFile = GetIconImage("shell32.dll", -16769);
+
+        private static Image GetIconImage(string dllName, int iconIndex)
+        {
+            using(Icon icon = ResourceIcon.GetIcon(dllName, iconIndex)) return icon?.ToBitmap();
+        }
     }
 }

+ 15 - 4
ContextMenuManager/AppString.cs

@@ -56,6 +56,7 @@ namespace ContextMenuManager
             public static string UwpLnk => GetValue("UwpLnk");
             public static string ExeFile => GetValue("ExeFile");
             public static string UnknownType => GetValue("UnknownType");
+            public static string MenuAnalysis => GetValue("MenuAnalysis");
             public static string CustomExtension => GetValue("CustomExtension");
             public static string PerceivedType => GetValue("PerceivedType");
             public static string DirectoryType => GetValue("DirectoryType");
@@ -65,6 +66,7 @@ namespace ContextMenuManager
             public static string GuidBlocked => GetValue("GuidBlocked");
             public static string DragDrop => GetValue("DragDrop");
             public static string PublicReferences => GetValue("PublicReferences");
+            public static string CustomRegPath => GetValue("CustomRegPath");
             public static string IEMenu => GetValue("IEMenu");
             public static string AppSetting => GetValue("AppSetting");
             public static string AboutApp => GetValue("AboutApp");
@@ -95,15 +97,16 @@ namespace ContextMenuManager
             public static string UwpLnk => GetValue("UwpLnk");
             public static string ExeFile => GetValue("ExeFile");
             public static string UnknownType => GetValue("UnknownType");
+            public static string MenuAnalysis => GetValue("MenuAnalysis");
             public static string CustomExtension => GetValue("CustomExtension");
             public static string PerceivedType => GetValue("PerceivedType");
             public static string DirectoryType => GetValue("DirectoryType");
             public static string EnhanceMenu => GetValue("EnhanceMenu");
             public static string ThirdRules => GetValue("ThirdRules");
-            public static string OtherAccounts => GetValue("OtherAccounts");
             public static string GuidBlocked => GetValue("GuidBlocked");
             public static string DragDrop => GetValue("DragDrop");
             public static string PublicReferences => GetValue("PublicReferences");
+            public static string CustomRegPath => GetValue("CustomRegPath");
             public static string IEMenu => GetValue("IEMenu");
         }
 
@@ -149,6 +152,7 @@ namespace ContextMenuManager
             public static string Save => GetValue("Save");
         }
 
+        /// <summary>对话框子窗口</summary>
         public static class Dialog
         {
             private static string GetValue(string key) => GetStringValue("Dialog", key);
@@ -159,8 +163,6 @@ namespace ContextMenuManager
             public static string ItemText => GetValue("ItemText");
             public static string ItemCommand => GetValue("ItemCommand");
             public static string CommandArguments => GetValue("CommandArguments");
-            public static string ItemName => GetValue("ItemName");
-            public static string ItemIcon => GetValue("ItemIcon");
             public static string SingleMenu => GetValue("SingleMenu");
             public static string MultiMenu => GetValue("MultiMenu");
             public static string Public => GetValue("Public");
@@ -168,6 +170,7 @@ namespace ContextMenuManager
             public static string InputGuid => GetValue("InputGuid");
             public static string AddGuidDic => GetValue("AddGuidDic");
             public static string DeleteGuidDic => GetValue("DeleteGuidDic");
+            public static string NoPerceivedType => GetValue("NoPerceivedType");
             public static string TextFile => GetValue("TextFile");
             public static string DocumentFile => GetValue("DocumentFile");
             public static string ImageFile => GetValue("ImageFile");
@@ -179,6 +182,7 @@ namespace ContextMenuManager
             public static string ImageDirectory => GetValue("ImageDirectory");
             public static string VideoDirectory => GetValue("VideoDirectory");
             public static string AudioDirectory => GetValue("AudioDirectory");
+            public static string EditSubItems => GetValue("EditSubItems");
             public static string CheckReference => GetValue("CheckReference");
             public static string CheckCopy => GetValue("CheckCopy");
             public static string SelectExtension => GetValue("SelectExtension");
@@ -188,6 +192,7 @@ namespace ContextMenuManager
             public static string SelectNewItemType => GetValue("SelectNewItemType");
             public static string RegistryFile => GetValue("RegistryFile");
             public static string SelectGroup => GetValue("SelectGroup");
+            public static string SelectObjectType => GetValue("SelectObjectType");
             public static string TranslateTool => GetValue("TranslateTool");
             public static string DefaultText => GetValue("DefaultText");
             public static string OldTranslation => GetValue("OldTranslation");
@@ -218,6 +223,7 @@ namespace ContextMenuManager
             public static string HasBeenAdded => GetValue("HasBeenAdded");
             public static string EditInitialData => GetValue("EditInitialData");
             public static string PromptIsOpenItem => GetValue("PromptIsOpenItem");
+            public static string SelectRegPath => GetValue("SelectRegPath");
             public static string RestartApp => GetValue("RestartApp");
             public static string UpdateApp => GetValue("UpdateApp");
             public static string FileNotExists => GetValue("FileNotExists");
@@ -253,7 +259,9 @@ namespace ContextMenuManager
             public static string CurrentExtension => GetValue("CurrentExtension");
             public static string CurrentPerceivedType => GetValue("CurrentPerceivedType");
             public static string CurrentDirectoryType => GetValue("CurrentDirectoryType");
-            public static string EditSubItems => GetValue("EditSubItems");
+            public static string CurrentFilePath => GetValue("CurrentFilePath");
+            public static string CurrentRegPath => GetValue("CurrentRegPath");
+            public static string SelectRegPath => GetValue("SelectRegPath");
             public static string InvalidItem => GetValue("InvalidItem");
             public static string Separator => GetValue("Separator");
             public static string LockNewMenu => GetValue("LockNewMenu");
@@ -280,6 +288,8 @@ namespace ContextMenuManager
             public static string WinXSortable => GetValue("WinXSortable");
             public static string ShowFilePath => GetValue("ShowFilePath");
             public static string OpenMoreRegedit => GetValue("OpenMoreRegedit");
+            public static string HideDisabledItems => GetValue("HideDisabledItems");
+            public static string SetPerceivedType => GetValue("SetPerceivedType");
         }
 
         /// <summary>提示文本</summary>
@@ -305,6 +315,7 @@ namespace ContextMenuManager
             public static string ConfigPath => GetValue("ConfigPath");
             public static string CommandFiles => GetValue("CommandFiles");
             public static string CreateGroup => GetValue("CreateGroup");
+            public static string DropOrSelectObject => GetValue("DropOrSelectObject");
         }
     }
 }

+ 33 - 38
ContextMenuManager/BluePointLilac.Controls/MyListBox.cs

@@ -102,7 +102,7 @@ namespace BluePointLilac.Controls
 
         public void ClearItems()
         {
-            foreach(Control control in Controls) control.Dispose();
+            foreach(Control control in Controls) BeginInvoke(new Action(control.Dispose));
             this.Controls.Clear();
         }
 
@@ -136,16 +136,18 @@ namespace BluePointLilac.Controls
             this.DoubleBuffered = true;
             this.Height = 50.DpiZoom();
             this.Margin = new Padding(0);
+            this.Font = SystemFonts.IconTitleFont;
             this.ForeColor = Color.FromArgb(80, 80, 80);
             this.BackColor = Color.FromArgb(250, 250, 250);
-            this.Font = SystemFonts.IconTitleFont;
             this.Controls.AddRange(new Control[] { lblSeparator, flpControls, lblText, picImage });
+            this.Resize += (Sender, e) => pnlScrollbar.Height = this.ClientSize.Height;
+            picImage.DoubleClick += (sender, e) => ImageDoubleClick?.Invoke(null, null);
+            lblText.DoubleClick += (sender, e) => TextDoubleClick?.Invoke(null, null);
             flpControls.MouseEnter += (sender, e) => this.OnMouseEnter(null);
-            flpControls.MouseDown += (sender, e) => this.OnMouseEnter(null);
-            flpControls.Left = this.ClientSize.Width;
-            lblText.SetEnabled(false);
+            flpControls.MouseDown += (sender, e) => this.OnMouseDown(null);
             CenterControl(lblText);
             CenterControl(picImage);
+            AddCtr(pnlScrollbar, 0);
         }
 
         public Image Image
@@ -181,10 +183,13 @@ namespace BluePointLilac.Controls
             {
                 hasImage = value;
                 picImage.Visible = value;
-                lblText.Left = value ? 60.DpiZoom() : 20.DpiZoom();
+                lblText.Left = (value ? 60 : 20).DpiZoom();
             }
         }
 
+        public event EventHandler TextDoubleClick;
+        public event EventHandler ImageDoubleClick;
+
         private readonly Label lblText = new Label
         {
             AutoSize = true
@@ -192,57 +197,52 @@ namespace BluePointLilac.Controls
         private readonly PictureBox picImage = new PictureBox
         {
             SizeMode = PictureBoxSizeMode.AutoSize,
-            Left = 20.DpiZoom(),
-            Enabled = false
+            Left = 20.DpiZoom()
         };
         private readonly FlowLayoutPanel flpControls = new FlowLayoutPanel
         {
-            FlowDirection = FlowDirection.RightToLeft,
             AutoSizeMode = AutoSizeMode.GrowAndShrink,
+            FlowDirection = FlowDirection.RightToLeft,
             Anchor = AnchorStyles.Right,
-            AutoSize = true,
-            Top = 0
+            AutoSize = true
         };
         private readonly Label lblSeparator = new Label
         {
             BackColor = Color.FromArgb(220, 220, 220),
             Dock = DockStyle.Bottom,
             Height = 1
-        };
+        };//分割线
+        private readonly Panel pnlScrollbar = new Panel
+        {
+            Width = SystemInformation.VerticalScrollBarWidth,
+            Enabled = false
+        };//预留滚动条宽度
 
         protected override void OnMouseDown(MouseEventArgs e)
         {
             base.OnMouseDown(e); OnMouseEnter(null);
         }
 
-        protected override void OnResize(EventArgs e)
-        {
-            base.OnResize(e); flpControls.Height = this.Height;
-        }
-
         private void CenterControl(Control ctr)
         {
-            void reSize(Control c)
+            void reSize()
             {
-                if(c.Parent == null) return;
-                int top = (c.Parent.Height - c.Height) / 2;
-                if(c.Parent == this) c.Top = top;
-                else if(c.Parent == flpControls)
+                if(ctr.Parent == null) return;
+                int top = (this.ClientSize.Height - ctr.Height) / 2;
+                ctr.Top = top;
+                if(ctr.Parent == flpControls)
                 {
-                    c.Margin = new Padding(0, top, c.Margin.Right, top);
+                    ctr.Margin = new Padding(0, top, ctr.Margin.Right, top);
                 }
             }
-            ctr.Parent.Resize += (sender, e) => reSize(ctr);
-            ctr.Resize += (sender, e) => reSize(ctr);
-            reSize(ctr);
+            ctr.Parent.Resize += (sender, e) => reSize();
+            ctr.Resize += (sender, e) => reSize();
+            reSize();
         }
 
         public void AddCtr(Control ctr)
         {
-            int space = 20.DpiZoom();
-            //为第一个ctr预留垂直滚动条的宽度
-            if(flpControls.Controls.Count == 0) space += SystemInformation.VerticalScrollBarWidth;
-            AddCtr(ctr, space);
+            AddCtr(ctr, 20.DpiZoom());
         }
 
         public void AddCtr(Control ctr, int space)
@@ -259,24 +259,19 @@ namespace BluePointLilac.Controls
             Array.ForEach(ctrs, ctr => AddCtr(ctr));
         }
 
-        public void RemoveCtr(Control ctr)
-        {
-            if(ctr.Parent == flpControls) flpControls.Controls.Remove(ctr);
-        }
-
         public void RemoveCtrAt(int index)
         {
-            if(flpControls.Controls.Count > index) flpControls.Controls.RemoveAt(index);
+            if(flpControls.Controls.Count > index) flpControls.Controls.RemoveAt(index + 1);
         }
 
         public int GetCtrIndex(Control ctr)
         {
-            return flpControls.Controls.GetChildIndex(ctr, true);
+            return flpControls.Controls.GetChildIndex(ctr, true) - 1;
         }
 
         public void SetCtrIndex(Control ctr, int newIndex)
         {
-            flpControls.Controls.SetChildIndex(ctr, newIndex);
+            flpControls.Controls.SetChildIndex(ctr, newIndex + 1);
         }
     }
 }

+ 2 - 1
ContextMenuManager/BluePointLilac.Controls/MyMainForm.cs

@@ -10,10 +10,11 @@ namespace BluePointLilac.Controls
         public MyMainForm()
         {
             this.Text = Application.ProductName;
-            this.MinimumSize = this.Size = new Size(866, 649).DpiZoom();
             this.Icon = Icon.ExtractAssociatedIcon(Application.ExecutablePath);
             this.Controls.AddRange(new Control[] { MainBody, SideBar, StatusBar, ToolBar });
             SideBar.Resize += (sender, e) => this.OnResize(null);
+            this.ClientSize = new Size(850, 610).DpiZoom();
+            this.MinimumSize = this.Size;
             ToolBar.CanMoveForm();
             StatusBar.CanMoveForm();
             this.CenterToScreen();

+ 20 - 3
ContextMenuManager/BluePointLilac.Controls/MyStatusBar.cs

@@ -1,4 +1,5 @@
 using BluePointLilac.Methods;
+using System;
 using System.Drawing;
 using System.Windows.Forms;
 
@@ -49,10 +50,26 @@ namespace BluePointLilac.Controls
         protected override void OnPaint(PaintEventArgs e)
         {
             base.OnPaint(e);
+            string txt = this.Text;
             int left = this.Height / 3;
-            int top = (this.Height - TextRenderer.MeasureText(this.Text, this.Font).Height) / 2;
-            e.Graphics.Clear(this.BackColor);
-            e.Graphics.DrawString(this.Text, this.Font, new SolidBrush(this.ForeColor), left, top);
+            for(int i = Text.Length - 1; i >= 0; i--)
+            {
+                Size size = TextRenderer.MeasureText(txt, Font);
+                if(size.Width < ClientSize.Width - 2 * left)
+                {
+                    int top = (this.Height - size.Height) / 2;
+                    e.Graphics.Clear(BackColor);
+                    e.Graphics.DrawString(txt, Font, new SolidBrush(ForeColor), left, top);
+                    break;
+                }
+                txt = Text.Substring(0, i) + "...";
+            }
+        }
+
+        protected override void OnResize(EventArgs e)
+        {
+            base.OnResize(e);
+            this.Refresh();
         }
     }
 }

+ 17 - 10
ContextMenuManager/BluePointLilac.Controls/MyToolBar.cs

@@ -57,7 +57,9 @@ namespace BluePointLilac.Controls
 
         public void AddButtons(MyToolBarButton[] buttons)
         {
-            Array.ForEach(buttons, button => AddButton(button));
+            int maxWidth = 72.DpiZoom();
+            Array.ForEach(buttons, button => maxWidth = Math.Max(maxWidth, TextRenderer.MeasureText(button.Text, button.Font).Width));
+            Array.ForEach(buttons, button => { button.Width = maxWidth; AddButton(button); });
         }
     }
 
@@ -68,14 +70,12 @@ namespace BluePointLilac.Controls
             this.DoubleBuffered = true;
             this.Size = new Size(72, 72).DpiZoom();
             this.Controls.AddRange(new Control[] { picImage, lblText });
-            picImage.Location = new Point(16, 6).DpiZoom();
+            lblText.Resize += (sender, e) => this.OnResize(null);
+            picImage.Top = 6.DpiZoom();
             lblText.Top = 52.DpiZoom();
-            lblText.Resize += (sender, e) => lblText.Left = (Width - lblText.Width) / 2;
+            lblText.SetEnabled(false);
             this.Image = image;
             this.Text = text;
-            this.CanBeSelected = true;
-            MyToolTip.SetToolTip(this, text);
-            lblText.SetEnabled(false);
         }
 
         readonly PictureBox picImage = new PictureBox
@@ -88,10 +88,10 @@ namespace BluePointLilac.Controls
 
         readonly Label lblText = new Label
         {
-            AutoSize = true,
-            Font = SystemFonts.MenuFont,
             BackColor = Color.Transparent,
-            ForeColor = Color.White
+            Font = SystemFonts.MenuFont,
+            ForeColor = Color.White,
+            AutoSize = true,
         };
 
         public Image Image
@@ -109,11 +109,18 @@ namespace BluePointLilac.Controls
             get => BackColor.A / 255;
             set => BackColor = Color.FromArgb((int)(value * 255), Color.White);
         }
-        public bool CanBeSelected { get; set; }
+        public bool CanBeSelected { get; set; } = true;
 
         protected override void OnMouseDown(MouseEventArgs e)
         {
             if(e.Button == MouseButtons.Left) base.OnMouseDown(e);
         }
+
+        protected override void OnResize(EventArgs e)
+        {
+            base.OnResize(e);
+            lblText.Left = (this.Width - lblText.Width) / 2;
+            picImage.Left = (this.Width - picImage.Width) / 2;
+        }
     }
 }

+ 22 - 0
ContextMenuManager/BluePointLilac.Methods/ComboBoxExtension.cs

@@ -0,0 +1,22 @@
+using System;
+using System.Windows.Forms;
+
+namespace BluePointLilac.Methods
+{
+    public static class ComboBoxExtension
+    {
+        public static void AutosizeDropDownWidth(this ComboBox box)
+        {
+            box.DropDown += (sender, e) =>
+            {
+                int maxWidth = 0;
+                foreach(var item in box.Items)
+                {
+                    maxWidth = Math.Max(maxWidth, TextRenderer.MeasureText(item.ToString(), box.Font).Width);
+                }
+                maxWidth = Math.Max(maxWidth, box.Width);
+                box.DropDownWidth = maxWidth;
+            };
+        }
+    }
+}

+ 0 - 7
ContextMenuManager/BluePointLilac.Methods/ControlExtension.cs

@@ -53,12 +53,5 @@ namespace BluePointLilac.Methods
             if(enabled) { SetWindowLong(ctr.Handle, GWL_STYLE, (~WS_DISABLED) & GetWindowLong(ctr.Handle, GWL_STYLE)); }
             else { SetWindowLong(ctr.Handle, GWL_STYLE, WS_DISABLED | GetWindowLong(ctr.Handle, GWL_STYLE)); }
         }
-
-        public static void SetNoClickEvent(this Control ctr)
-        {
-            Cursor cursor = ctr.Cursor;
-            ctr.MouseDown += (sender, e) => ctr.Cursor = Cursors.No;
-            ctr.MouseUp += (sender, e) => ctr.Cursor = cursor;
-        }
     }
 }

+ 139 - 0
ContextMenuManager/BluePointLilac.Methods/ElevatedFileDroper.cs

@@ -0,0 +1,139 @@
+using System;
+using System.ComponentModel;
+using System.Drawing;
+using System.Runtime.InteropServices;
+using System.Text;
+using System.Windows.Forms;
+
+namespace BluePointLilac.Methods
+{
+    /// 代码用途:管理员UAC进程窗口拖放文件
+    /// 代码来源1:https://zhuanlan.zhihu.com/p/48735364
+    /// 代码来源2:https://github.com/volschin/sdimager/blob/master/ElevatedDragDropManager.cs
+    /// 代码作者:雨少主(知乎)、volschin(Github)、蓝点lilac(转载、修改)
+    /// 调用方法:var droper = new ElevatedFileDroper(control);
+    /// control.DragDrop += (sender, e) => MessageBox.Show(droper.DropFilePaths[0]);
+
+    public sealed class ElevatedFileDroper : IMessageFilter
+    {
+        #region native members
+        [DllImport("user32.dll", SetLastError = true)]
+        [return: MarshalAs(UnmanagedType.Bool)]
+        private static extern bool ChangeWindowMessageFilterEx(IntPtr hWnd, uint message, ChangeFilterAction action, in ChangeFilterStruct pChangeFilterStruct);
+
+        [DllImport("user32.dll", SetLastError = true)]
+        [return: MarshalAs(UnmanagedType.Bool)]
+        private static extern bool ChangeWindowMessageFilter(uint msg, ChangeWindowMessageFilterFlags flags);
+
+        [DllImport("shell32.dll", SetLastError = false)]
+        private static extern void DragAcceptFiles(IntPtr hWnd, bool fAccept);
+
+        [DllImport("shell32.dll", SetLastError = false, CharSet = CharSet.Unicode)]
+        private static extern uint DragQueryFile(IntPtr hWnd, uint iFile, StringBuilder lpszFile, int cch);
+
+        [DllImport("shell32.dll", SetLastError = false)]
+        private static extern bool DragQueryPoint(IntPtr hDrop, out Point lppt);
+
+        [DllImport("shell32.dll", SetLastError = false)]
+        private static extern void DragFinish(IntPtr hDrop);
+
+        [StructLayout(LayoutKind.Sequential)]
+        struct ChangeFilterStruct
+        {
+            public uint CbSize;
+            public ChangeFilterStatu ExtStatus;
+        }
+
+        enum ChangeWindowMessageFilterFlags : uint
+        {
+            MSGFLT_ADD = 1,
+            MSGFLT_REMOVE = 2
+        }
+
+        enum ChangeFilterAction : uint
+        {
+            MSGFLT_RESET,
+            MSGFLT_ALLOW,
+            MSGFLT_DISALLOW
+        }
+
+        enum ChangeFilterStatu : uint
+        {
+            MSGFLTINFO_NONE,
+            MSGFLTINFO_ALREADYALLOWED_FORWND,
+            MSGFLTINFO_ALREADYDISALLOWED_FORWND,
+            MSGFLTINFO_ALLOWED_HIGHER
+        }
+
+        const uint WM_COPYGLOBALDATA = 0x0049;
+        const uint WM_COPYDATA = 0x004A;
+        const uint WM_DROPFILES = 0x0233;
+        #endregion
+
+        public Control ContainerControl { get; private set; }
+        public string[] DropFilePaths { get; private set; }
+        public Point DropPoint { get; private set; }
+
+        public ElevatedFileDroper(Control containerControl)
+        {
+            this.ContainerControl = containerControl ?? throw new ArgumentNullException();
+            if(containerControl.IsDisposed) throw new ObjectDisposedException(containerControl.Name);
+            containerControl.DragDrop += (sender, e) => DropFilePaths = (string[])e.Data.GetData(typeof(string[]));
+            containerControl.DragEnter += (sender, e) => e.Effect = DragDropEffects.All;
+            containerControl.Disposed += (sender, e) => Application.RemoveMessageFilter(this);
+
+            Version ver = Environment.OSVersion.Version;
+            bool isVistaOrHigher = ver >= new Version(6, 0);
+            bool isWin7OrHigher = ver >= new Version(6, 1);
+            var status = new ChangeFilterStruct { CbSize = 8 };
+            if(isVistaOrHigher)
+            {
+                foreach(uint msg in new[] { WM_DROPFILES, WM_COPYGLOBALDATA, WM_COPYDATA })
+                {
+                    bool error = false;
+                    if(isWin7OrHigher)
+                    {
+                        error = !ChangeWindowMessageFilterEx(containerControl.Handle, msg, ChangeFilterAction.MSGFLT_ALLOW, in status);
+                    }
+                    else
+                    {
+                        error = !ChangeWindowMessageFilter(msg, ChangeWindowMessageFilterFlags.MSGFLT_ADD);
+                    }
+                    if(error) throw new Win32Exception(Marshal.GetLastWin32Error());
+                }
+            }
+            DragAcceptFiles(containerControl.Handle, true);
+            Application.AddMessageFilter(this);
+        }
+
+        public bool PreFilterMessage(ref Message m)
+        {
+            if(ContainerControl == null || ContainerControl.IsDisposed) return false;
+            if(ContainerControl.AllowDrop)
+            {
+                DropPoint = ContainerControl.PointToClient(Cursor.Position);
+                ContainerControl.AllowDrop = false;
+                return false;
+            }
+            if(m.Msg == WM_DROPFILES)
+            {
+                IntPtr handle = m.WParam;
+                uint fileCount = DragQueryFile(handle, uint.MaxValue, null, 0);
+                string[] fileNames = new string[fileCount];
+                StringBuilder sb = new StringBuilder(260);
+                int charLength = sb.Capacity;
+                for(uint i = 0; i < fileCount; i++)
+                {
+                    if(DragQueryFile(handle, i, sb, charLength) > 0) fileNames[i] = sb.ToString();
+                }
+                DragQueryPoint(handle, out Point point);
+                DragFinish(handle);
+                DropPoint = point;
+                ContainerControl.AllowDrop = true;
+                ContainerControl.DoDragDrop(fileNames, DragDropEffects.All);
+                return true;
+            }
+            return false;
+        }
+    }
+}

+ 28 - 6
ContextMenuManager/BluePointLilac.Methods/ExternalProgram.cs

@@ -71,14 +71,14 @@ namespace BluePointLilac.Methods
             process.Dispose();
         }
 
-        public static void JumpExplorer(string filePath)
+        public static void JumpExplorer(string filePath, bool moreOpen = false)
         {
             using(Process process = new Process())
             {
                 if(File.Exists(filePath))
                 {
                     process.StartInfo.FileName = "explorer.exe";
-                    process.StartInfo.Arguments = $"/select,{filePath}";
+                    process.StartInfo.Arguments = $"/select, {filePath}";
                     process.Start();
                 }
                 else if(Directory.Exists(filePath))
@@ -103,6 +103,27 @@ namespace BluePointLilac.Methods
             return ShellExecuteEx(ref info);
         }
 
+        public static void ShowOpenWithDialog(string extension)
+        {
+            //Win10 调用 SHOpenWithDialog API 或调用 OpenWith.exe -override "%1"
+            //或调用 rundll32.exe shell32.dll,OpenAs_RunDLL %1 能显示打开方式对话框,但都不能设置默认应用
+            //以下方法只针对未关联打开方式的扩展名显示系统打开方式对话框,对于已关联打开方式的扩展名会报错
+            string tempPath = $"{Path.GetTempPath()}{extension}";
+            tempPath = ObjectPath.GetNewPathWithIndex(tempPath, ObjectPath.PathType.File);
+            File.WriteAllText(tempPath, "");
+            using(Process process = new Process())
+            {
+                process.StartInfo = new ProcessStartInfo
+                {
+                    UseShellExecute = true,
+                    FileName = tempPath,
+                    Verb = "openas"
+                };
+                process.Start();
+            }
+            File.Delete(tempPath);
+        }
+
         public static void RestartExplorer()
         {
             using(Process process = new Process())
@@ -152,16 +173,16 @@ namespace BluePointLilac.Methods
         private const int VK_HOME = 0x24;
         private const int VK_RIGHT = 0x27;
 
-        [DllImport("User32.dll")]
+        [DllImport("user32.dll")]
         private static extern bool ShowWindowAsync(IntPtr hWnd, int cmdShow);
 
-        [DllImport("User32.dll")]
+        [DllImport("user32.dll")]
         private static extern bool SetForegroundWindow(IntPtr hWnd);
 
-        [DllImport("User32.dll")]
+        [DllImport("user32.dll")]
         private static extern bool SetFocus(IntPtr hWnd);
 
-        [DllImport("User32.dll", CharSet = CharSet.Auto)]
+        [DllImport("user32.dll", CharSet = CharSet.Auto)]
         public static extern int GetWindowThreadProcessId(IntPtr hwnd, out int ID);
 
         [DllImport("user32.dll")]
@@ -172,6 +193,7 @@ namespace BluePointLilac.Methods
 
         [DllImport("user32.dll")]
         private static extern int SendMessage(IntPtr hWnd, int uMsg, int wParam, string lParam);
+
         [DllImport("shell32.dll", CharSet = CharSet.Auto)]
         private static extern bool ShellExecuteEx(ref SHELLEXECUTEINFO lpExecInfo);
 

+ 58 - 1
ContextMenuManager/BluePointLilac.Methods/FileExtension.cs

@@ -1,14 +1,71 @@
 using Microsoft.Win32;
+using System;
+using System.Runtime.InteropServices;
+using System.Text;
 
 namespace BluePointLilac.Methods
 {
     public static class FileExtension
     {
+        [Flags]
+        enum AssocF
+        {
+            Init_NoRemapCLSID = 0x1,
+            Init_ByExeName = 0x2,
+            Open_ByExeName = 0x2,
+            Init_DefaultToStar = 0x4,
+            Init_DefaultToFolder = 0x8,
+            NoUserSettings = 0x10,
+            NoTruncate = 0x20,
+            Verify = 0x40,
+            RemapRunDll = 0x80,
+            NoFixUps = 0x100,
+            IgnoreBaseClass = 0x200
+        }
+
+        enum AssocStr
+        {
+            Command = 1,
+            Executable,
+            FriendlyDocName,
+            FriendlyAppName,
+            NoOpen,
+            ShellNewValue,
+            DDECommand,
+            DDEIfExec,
+            DDEApplication,
+            DDETopic
+        }
+
+        [DllImport("shlwapi.dll", SetLastError = true, CharSet = CharSet.Auto)]
+        private static extern uint AssocQueryString(AssocF flags, AssocStr str, string pszAssoc, string pszExtra, [Out] StringBuilder pszOut, ref uint pcchOut);
+
         public const string FileExtsPath = @"HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\FileExts";
 
+        private static string GetExtentionInfo(AssocStr assocStr, string extension)
+        {
+            uint pcchOut = 0;
+            AssocQueryString(AssocF.Verify, assocStr, extension, null, null, ref pcchOut);
+            StringBuilder pszOut = new StringBuilder((int)pcchOut);
+            AssocQueryString(AssocF.Verify, assocStr, extension, null, pszOut, ref pcchOut);
+            return pszOut.ToString();
+        }
+
+        public static string GetExecutablePath(string extension)
+        {
+            return GetExtentionInfo(AssocStr.Executable, extension);
+        }
+
+        public static string GetFriendlyDocName(string extension)
+        {
+            return GetExtentionInfo(AssocStr.FriendlyDocName, extension);
+        }
+
         public static string GetOpenMode(string extension)
         {
-            string mode = Registry.GetValue($@"{FileExtsPath}\{extension}\UserChoice", "ProgId", null)?.ToString();
+            string mode = null;
+            if(string.IsNullOrEmpty(extension)) return mode;
+            mode = Registry.GetValue($@"{FileExtsPath}\{extension}\UserChoice", "ProgId", null)?.ToString();
             if(!string.IsNullOrEmpty(mode)) return mode;
             mode = Registry.GetValue($@"HKEY_CLASSES_ROOT\{extension}", "", null)?.ToString();
             return mode;

+ 1 - 0
ContextMenuManager/BluePointLilac.Methods/ImageExtension.cs

@@ -22,6 +22,7 @@ namespace BluePointLilac.Methods
 
         public static Image ResizeImage(this Image image, int width, int height)
         {
+            //return image.GetThumbnailImage(width, height, null, System.IntPtr.Zero);//质量稍微低一点
             if(image.Width == width && image.Height == height) return image;
             Bitmap destImage = new Bitmap(width, height);
             destImage.SetResolution(image.HorizontalResolution, image.VerticalResolution);

+ 61 - 44
ContextMenuManager/BluePointLilac.Methods/ObjectPath.cs

@@ -11,7 +11,6 @@ namespace BluePointLilac.Methods
         /// <summary>路径类型</summary>
         public enum PathType { File, Directory, Registry }
         private const string RegAppPath = @"HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths";
-        private const string RegLastPath = @"HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Applets\Regedit";
         private const string ShellExecuteCommand = "mshta vbscript:createobject(\"shell.application\").shellexecute(\"";
 
         private static readonly char[] IllegalChars = { '/', '*', '?', '\"', '<', '>', '|' };
@@ -31,75 +30,93 @@ namespace BluePointLilac.Methods
                 //右键菜单仅支持%SystemRoot%\System32和%SystemRoot%两个环境变量,不考虑其他系统环境变量和用户环境变量,和Win+R命令有区别
                 foreach(string dir in new[] { "", @"%SystemRoot%\System32\", @"%SystemRoot%\" })
                 {
+                    if(dir != "" && (name.Contains('\\') || name.Contains(':'))) return false;
                     fullPath = Environment.ExpandEnvironmentVariables($@"{dir}{name}");
                     if(File.Exists(fullPath)) return true;
                 }
 
-                if(!name.Contains("\\"))
-                {
-                    fullPath = Registry.GetValue($@"{RegAppPath}\{name}", "", null)?.ToString();
-                    if(File.Exists(fullPath)) return true;
-                }
+                fullPath = Registry.GetValue($@"{RegAppPath}\{name}", "", null)?.ToString();
+                if(File.Exists(fullPath)) return true;
             }
             fullPath = null;
             return false;
         }
 
+
+        private static readonly Dictionary<string, string> FilePathDic = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
         /// <summary>从包含现有文件路径的命令语句中提取文件路径</summary>
         /// <param name="command">命令语句</param>
         /// <returns>成功提取返回现有文件路径,否则返回值为null</returns>
         public static string ExtractFilePath(string command)
         {
             if(command.IsNullOrWhiteSpace()) return null;
-            command = Environment.ExpandEnvironmentVariables(command).Replace(@"\\", @"\");
-            if(File.Exists(command)) return command;
-
-            if(command.StartsWith(ShellExecuteCommand, StringComparison.OrdinalIgnoreCase))
+            if(FilePathDic.ContainsKey(command)) return FilePathDic[command];
+            else
             {
-                command = command.Remove(0, ShellExecuteCommand.Length);
-                string[] arr = command.Split(new[] { "\",\"" }, StringSplitOptions.None);
-                if(arr.Length > 0)
+                string filePath = null;
+                string partCmd = Environment.ExpandEnvironmentVariables(command).Replace(@"\\", @"\");
+                if(partCmd.StartsWith(ShellExecuteCommand, StringComparison.OrdinalIgnoreCase))
                 {
-                    string filePath = null;
-                    string fileName = arr[0];
-                    if(arr.Length > 1)
+                    partCmd = partCmd.Substring(ShellExecuteCommand.Length);
+                    string[] arr = partCmd.Split(new[] { "\",\"" }, StringSplitOptions.None);
+                    if(arr.Length > 0)
                     {
-                        string arguments = arr[1];
-                        filePath = ExtractFilePath(arguments);
-                        if(filePath != null) return filePath;
+                        string fileName = arr[0];
+                        if(arr.Length > 1)
+                        {
+                            string arguments = arr[1];
+                            filePath = ExtractFilePath(arguments);
+                            if(filePath != null) return filePath;
+                        }
+                        if(GetFullFilePath(fileName, out filePath))
+                        {
+                            FilePathDic.Add(command, filePath);
+                            return filePath;
+                        }
                     }
-                    if(GetFullFilePath(fileName, out filePath)) return filePath;
                 }
-            }
 
-            string[] strs = Array.FindAll(command.Split(IllegalChars), str
-                => IgnoreCommandParts.Any(part => !part.Equals(str.Trim()))).Reverse().ToArray();
-            foreach(string str1 in strs)
-            {
-                string str2 = str1;
-                int index = -1;
-                do
+                string[] strs = Array.FindAll(partCmd.Split(IllegalChars), str
+                    => IgnoreCommandParts.Any(part => !part.Equals(str.Trim()))).Reverse().ToArray();
+
+                foreach(string str1 in strs)
                 {
-                    List<string> paths = new List<string>();
-                    string path1 = str2.Substring(index + 1);
-                    paths.Add(path1);
-                    if(path1.Contains(",")) paths.AddRange(path1.Split(','));
-                    if(index > 0)
-                    {
-                        string path2 = str2.Substring(0, index);
-                        paths.Add(path2);
-                        if(path2.Contains(",")) paths.AddRange(path2.Split(','));
-                    }
-                    foreach(string path in paths)
+                    string str2 = str1;
+                    int index = -1;
+                    do
                     {
-                        if(GetFullFilePath(path, out string fullPath)) return fullPath;
+                        List<string> paths = new List<string>();
+                        string path1 = str2.Substring(index + 1);
+                        paths.Add(path1);
+                        if(index > 0)
+                        {
+                            string path2 = str2.Substring(0, index);
+                            paths.Add(path2);
+                        }
+                        int count = paths.Count;
+                        for(int i = 0; i < count; i++)
+                        {
+                            foreach(char c in new[] { ',', '-' })
+                            {
+                                if(paths[i].Contains(c)) paths.AddRange(paths[i].Split(c));
+                            }
+                        }
+                        foreach(string path in paths)
+                        {
+                            if(GetFullFilePath(path, out filePath))
+                            {
+                                FilePathDic.Add(command, filePath);
+                                return filePath;
+                            }
+                        }
+                        str2 = path1;
+                        index = str2.IndexOf(' ');
                     }
-                    str2 = path1;
-                    index = str2.IndexOf(' ');
+                    while(index != -1);
                 }
-                while(index != -1);
+                FilePathDic.Add(command, null);
+                return null;
             }
-            return null;
         }
 
         /// <summary>移除文件或文件夹名称中的非法字符</summary>

+ 5 - 4
ContextMenuManager/BluePointLilac.Methods/RegTrustedInstaller.cs

@@ -1,6 +1,5 @@
 using Microsoft.Win32;
 using System;
-using System.Diagnostics;
 using System.Runtime.InteropServices;
 using System.Security.AccessControl;
 using System.Security.Principal;
@@ -8,8 +7,7 @@ using System.Security.Principal;
 namespace BluePointLilac.Methods
 {
     /// 获取TrustedInstaller权限注册表项的所有权
-    /// 代码主要为转载,仅做简单改动
-    /// 代码作者:JPBlanc
+    /// 代码作者:JPBlanc(原作者)、蓝点lilac(转载、修改)
     /// 代码原文:https://gist.github.com/JPBlanc/ca0e4f1830e4ca18a526#file-write_a_registry_own_by_trustedinstaller-cs
     public class RegTrustedInstaller
     {
@@ -119,6 +117,9 @@ namespace BluePointLilac.Methods
             [DllImport("kernel32.dll", SetLastError = true)]
             private static extern int GetLastError();
 
+            [DllImport("kernel32.dll", SetLastError = true)]
+            private static extern IntPtr GetCurrentProcess();
+
             public static bool TrySetPrivilege(string sPrivilege, bool enablePrivilege)
             {
                 bool blRc;
@@ -129,7 +130,7 @@ namespace BluePointLilac.Methods
                 IntPtr processToken = IntPtr.Zero;
 
                 //本地进程令牌恢复
-                blRc = OpenProcessToken(Process.GetCurrentProcess().Handle, TokenAccessRights.AllAccess, ref processToken);
+                blRc = OpenProcessToken(GetCurrentProcess(), TokenAccessRights.AllAccess, ref processToken);
                 if(blRc == false) return false;
 
                 //恢复特权的唯一标识符空间

+ 23 - 8
ContextMenuManager/BluePointLilac.Methods/RegistryEx.cs

@@ -8,6 +8,12 @@ namespace BluePointLilac.Methods
 {
     public static class RegistryEx
     {
+        public const string CLASSESROOT = "HKEY_CLASSES_ROOT";
+        public const string CURRENTUSER = "HKEY_CURRENT_USER";
+        public const string LOCALMACHINE = "HKEY_LOCAL_MACHINE";
+        public const string CURRENTCONFIG = "HKEY_CURRENT_CONFIG";
+        public const string USERS = "HKEY_USERS";
+
         public static void CopyTo(this RegistryKey srcKey, RegistryKey dstKey)
         {
             foreach(string name in srcKey.GetValueNames())
@@ -93,28 +99,37 @@ namespace BluePointLilac.Methods
         /// <param name="subRegPath">不包含根项的注册表路径</param>
         public static void GetRootAndSubRegPath(string regPath, out RegistryKey root, out string subRegPath)
         {
+            string rootPath;
             int index = regPath.IndexOf('\\');
-            subRegPath = regPath.Substring(index + 1);
-            string rootPath = regPath.Substring(0, index).ToUpper();
+            if(index > 0)
+            {
+                rootPath = regPath.Substring(0, index).ToUpper();
+                subRegPath = regPath.Substring(index + 1);
+            }
+            else
+            {
+                rootPath = regPath;
+                subRegPath = string.Empty;
+            }
             switch(rootPath)
             {
-                case "HKEY_CLASSES_ROOT":
+                case CLASSESROOT:
                     root = Registry.ClassesRoot;
                     break;
-                case "HKEY_CURRENT_USER":
+                case CURRENTUSER:
                     root = Registry.CurrentUser;
                     break;
-                case "HKEY_LOCAL_MACHINE":
+                case LOCALMACHINE:
                     root = Registry.LocalMachine;
                     break;
-                case "HKEY_USERS":
+                case USERS:
                     root = Registry.Users;
                     break;
-                case "HKEY_CURRENT_CONFIG":
+                case CURRENTCONFIG:
                     root = Registry.CurrentConfig;
                     break;
                 default:
-                    throw new ArgumentNullException("非法的根项!");
+                    throw new ArgumentNullException("The root key resolution failed!");
             }
         }
 

+ 1 - 1
ContextMenuManager/BluePointLilac.Methods/RichTextBoxExtension.cs

@@ -8,7 +8,7 @@ namespace BluePointLilac.Methods
     public static class RichTextBoxExtension
     {
         /// 代码原文:https://archive.codeplex.com/?p=xmlrichtextbox
-        /// 本人仅作简单修改,将原继承类改写为扩展方法
+        /// 本人(蓝点lilac)仅作简单修改,将原继承类改写为扩展方法
         /// <summary>RichTextBox中XML语法高亮</summary>
         /// <param name="xmlStr">要显示的xml文本</param>
         public static void LoadXml(this RichTextBox box, string xmlStr)

+ 307 - 0
ContextMenuManager/BluePointLilac.Methods/ShellLink.cs

@@ -0,0 +1,307 @@
+using System;
+using System.IO;
+using System.Runtime.InteropServices;
+using System.Runtime.InteropServices.ComTypes;
+using System.Text;
+using System.Windows.Forms;
+using ComTypes = System.Runtime.InteropServices.ComTypes;
+
+namespace BluePointLilac.Methods
+{
+    public class ShellLink : IDisposable
+    {
+        [ComImport]
+        [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
+        [Guid("000214F9-0000-0000-C000-000000000046")]
+        interface IShellLinkW
+        {
+            void GetPath([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszFile, int cchMaxPath, ref WIN32_FIND_DATAW pfd, uint fFlags);
+            void GetIDList(out IntPtr ppidl);
+            void SetIDList(IntPtr pidl);
+            void GetDescription([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszName, int cchMaxName);
+            void SetDescription([MarshalAs(UnmanagedType.LPWStr)] string pszName);
+            void GetWorkingDirectory([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszDir, int cchMaxPath);
+            void SetWorkingDirectory([MarshalAs(UnmanagedType.LPWStr)] string pszDir);
+            void GetArguments([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszArgs, int cchMaxPath);
+            void SetArguments([MarshalAs(UnmanagedType.LPWStr)] string pszArgs);
+            void GetHotKey(out ushort pwHotkey);
+            void SetHotKey(ushort wHotKey);
+            void GetShowCmd(out int piShowCmd);
+            void SetShowCmd(int iShowCmd);
+            void GetIconLocation([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszIconPath, int cchIconPath, out int piIcon);
+            void SetIconLocation([MarshalAs(UnmanagedType.LPWStr)] string pszIconPath, int iIcon);
+            void SetRelativePath([MarshalAs(UnmanagedType.LPWStr)] string pszPathRel, uint dwReserved);
+            void Resolve(IntPtr hwnd, uint fFlags);
+            void SetPath([MarshalAs(UnmanagedType.LPWStr)] string pszFile);
+        }
+
+        [ComImport]
+        [ClassInterface(ClassInterfaceType.None)]
+        [Guid("00021401-0000-0000-C000-000000000046")]
+        private class CShellLink { }
+
+        [ComImport]
+        [Guid("45e2b4ae-b1c3-11d0-b92f-00a0c90312e1")]
+        [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
+        interface IShellLinkDataList
+        {
+            void AddDataBlock(IntPtr pDataBlock);
+            void CopyDataBlock(uint dwSig, out IntPtr ppDataBlock);
+            void RemoveDataBlock(uint dwSig);
+            void GetFlags(out ShellLinkDataFlags pdwFlags);
+            void SetFlags(ShellLinkDataFlags dwFlags);
+        }
+
+        [Flags]
+        enum ShellLinkDataFlags : uint
+        {
+            Default = 0x00000000,
+            HasIdList = 0x00000001,
+            HasLinkInfo = 0x00000002,
+            HasName = 0x00000004,
+            HasRelpath = 0x00000008,
+            HasWorkingdir = 0x00000010,
+            HasArgs = 0x00000020,
+            HasIconLocation = 0x00000040,
+            Unicode = 0x00000080,
+            ForceNoLinkInfo = 0x00000100,
+            HasExpSz = 0x00000200,
+            RunInSeparate = 0x00000400,
+            HasLogo3Id = 0x00000800,
+            HasDarwinId = 0x00001000,
+            RunasUser = 0x00002000,
+            HasExpIconSz = 0x00004000,
+            NoPidlAlias = 0x00008000,
+            ForceUncname = 0x00010000,
+            RunWithShimlayer = 0x00020000,
+            ForceNoLinktrack = 0x00040000,
+            EnableTargetMetadata = 0x00080000,
+            DisableLinkPathTracking = 0x00100000,
+            DisableKnownfolderRelativeTracking = 0x00200000,
+            NoKFAlias = 0x00400000,
+            AllowLinkToLink = 0x00800000,
+            UnaliasOnSave = 0x01000000,
+            PreferEnvironmentPath = 0x02000000,
+            KeepLocalIdListForUncTarget = 0x04000000,
+            Valid = 0x07fff7ff,
+            Reserved = 0x80000000
+        }
+
+        [StructLayout(LayoutKind.Sequential, Pack = 4, CharSet = CharSet.Unicode)]
+        struct WIN32_FIND_DATAW
+        {
+            public uint dwFileAttributes;
+            public ComTypes.FILETIME ftCreationTime;
+            public ComTypes.FILETIME ftLastAccessTime;
+            public ComTypes.FILETIME ftLastWriteTime;
+            public uint nFileSizeHigh;
+            public uint nFileSizeLow;
+            public uint dwReserved0;
+            public uint dwReserved1;
+            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = MAX_PATH)]
+            public string cFileName;
+            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 14)]
+            public string cAlternateFileName;
+        }
+
+        public struct ICONLOCATION
+        {
+            public string IconPath;
+            public int IconIndex;
+        }
+
+        private const int MAX_PATH = 260;
+        private const int INFOTIPSIZE = 1024;
+
+        private const uint SLGP_UNCPRIORITY = 2;
+        private const int STGM_READWRITE = 2;
+
+        private const int SW_SHOWMAXIMIZED = 3;
+        private const int SW_SHOWMINIMIZED = 2;
+        private const int SW_SHOWMINNOACTIVE = 7;
+        private const int SW_SHOWNORMAL = 1;
+
+
+        private IShellLinkW shellLinkW = null;
+        private IPersistFile PersistFile => (IPersistFile)shellLinkW;
+        private IShellLinkDataList LinkDataList => (IShellLinkDataList)shellLinkW;
+
+        public string ShortcutPath { get; private set; }
+
+        public string TargetPath
+        {
+            get
+            {
+                StringBuilder targetPath = new StringBuilder(MAX_PATH);
+                WIN32_FIND_DATAW data = new WIN32_FIND_DATAW();
+                shellLinkW.GetPath(targetPath, targetPath.Capacity, ref data, SLGP_UNCPRIORITY);
+                return targetPath.ToString();
+            }
+            set
+            {
+                shellLinkW.SetPath(value);
+            }
+        }
+
+        public string Arguments
+        {
+            get
+            {
+                StringBuilder arguments = new StringBuilder(INFOTIPSIZE);
+                shellLinkW.GetArguments(arguments, arguments.Capacity);
+                return arguments.ToString();
+            }
+            set
+            {
+                shellLinkW.SetArguments(value);
+            }
+        }
+
+        public string WorkingDirectory
+        {
+            get
+            {
+                StringBuilder dirPath = new StringBuilder(MAX_PATH);
+                shellLinkW.GetWorkingDirectory(dirPath, dirPath.Capacity);
+                return dirPath.ToString();
+            }
+            set
+            {
+                shellLinkW.SetWorkingDirectory(value);
+            }
+        }
+
+        public ICONLOCATION IconLocation
+        {
+            get
+            {
+                StringBuilder iconPath = new StringBuilder(MAX_PATH);
+                shellLinkW.GetIconLocation(iconPath, iconPath.Capacity, out int iconIndex);
+                return new ICONLOCATION { IconPath = iconPath.ToString(), IconIndex = iconIndex };
+            }
+            set
+            {
+                shellLinkW.SetIconLocation(value.IconPath, value.IconIndex);
+            }
+        }
+
+        public string IconPath => IconLocation.IconPath;
+
+        public int IconIndex => IconLocation.IconIndex;
+
+        public string Description
+        {
+            get
+            {
+                StringBuilder description = new StringBuilder(INFOTIPSIZE);
+                shellLinkW.GetDescription(description, description.Capacity);
+                return description.ToString();
+            }
+            set
+            {
+                shellLinkW.SetDescription(value);
+            }
+        }
+
+        public Keys HotKey
+        {
+            get
+            {
+                shellLinkW.GetHotKey(out ushort key);
+                int hotKey = ((key & 0xFF00) << 8) | (key & 0xFF);
+                return (Keys)hotKey;
+            }
+            set
+            {
+                if((value & Keys.Modifiers) == 0) throw new ArgumentException("Hotkey must include a modifier key.");
+                ushort key = unchecked((ushort)(((int)(value & Keys.Modifiers) >> 8) | (int)(value & Keys.KeyCode)));
+                shellLinkW.SetHotKey(key);
+            }
+        }
+
+        public FormWindowState WindowStyle
+        {
+            get
+            {
+                shellLinkW.GetShowCmd(out int style);
+                switch(style)
+                {
+                    case SW_SHOWMINIMIZED:
+                    case SW_SHOWMINNOACTIVE:
+                        return FormWindowState.Minimized;
+                    case SW_SHOWMAXIMIZED:
+                        return FormWindowState.Maximized;
+                    case SW_SHOWNORMAL:
+                    default:
+                        return FormWindowState.Normal;
+                }
+            }
+            set
+            {
+                int style;
+                switch(value)
+                {
+                    case FormWindowState.Minimized:
+                        style = SW_SHOWMINIMIZED; break;
+                    case FormWindowState.Maximized:
+                        style = SW_SHOWMAXIMIZED; break;
+                    case FormWindowState.Normal:
+                    default:
+                        style = SW_SHOWNORMAL; break;
+                }
+                shellLinkW.SetShowCmd(style);
+            }
+        }
+
+        public bool RunAsAdministrator
+        {
+            get
+            {
+                LinkDataList.GetFlags(out ShellLinkDataFlags flags);
+                return (flags & ShellLinkDataFlags.RunasUser) == ShellLinkDataFlags.RunasUser;
+            }
+            set
+            {
+                LinkDataList.GetFlags(out ShellLinkDataFlags flags);
+                if(value) flags |= ShellLinkDataFlags.RunasUser;
+                else flags &= ~ShellLinkDataFlags.RunasUser;
+                LinkDataList.SetFlags(flags);
+            }
+        }
+
+        public ShellLink(string lnkPath = null)
+        {
+            try { shellLinkW = (IShellLinkW)new CShellLink(); }
+            catch { throw new COMException("Failed to create ShellLink object."); }
+            Load(lnkPath);
+        }
+
+        ~ShellLink() { Dispose(false); }
+
+        public void Dispose()
+        {
+            Dispose(true);
+            GC.SuppressFinalize(this);
+        }
+
+        protected virtual void Dispose(bool disposing)
+        {
+            if(shellLinkW == null) return;
+            Marshal.FinalReleaseComObject(shellLinkW);
+            shellLinkW = null;
+        }
+
+        public void Save() { Save(this.ShortcutPath); }
+
+        public void Save(string lnkPath)
+        {
+            PersistFile.Save(lnkPath, true);
+        }
+
+        public void Load(string lnkPath)
+        {
+            this.ShortcutPath = lnkPath;
+            if(File.Exists(lnkPath)) PersistFile.Load(lnkPath, STGM_READWRITE);
+        }
+    }
+}

+ 2 - 2
ContextMenuManager/BluePointLilac.Methods/SingleInstance.cs

@@ -44,10 +44,10 @@ namespace BluePointLilac.Methods
             Application.Exit();
         }
 
-        [DllImport("User32.dll")]
+        [DllImport("user32.dll")]
         private static extern bool ShowWindowAsync(IntPtr hWnd, int cmdShow);
 
-        [DllImport("User32.dll")]
+        [DllImport("user32.dll")]
         private static extern bool SetForegroundWindow(IntPtr hWnd);
     }
 }

+ 319 - 0
ContextMenuManager/BluePointLilac.Methods/WinXHasher.cs

@@ -0,0 +1,319 @@
+using System;
+using System.Collections.Generic;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+using System.Runtime.InteropServices.ComTypes;
+using System.Security;
+using System.Text;
+using ComTypes = System.Runtime.InteropServices.ComTypes;
+
+namespace BluePointLilac.Methods
+{
+    /// 代码用途:添加WinX菜单项目
+    /// 参考代码1:https://github.com/riverar/hashlnk/blob/master/hashlnk.cpp (Rafael Rivera)
+    /// 参考代码2:https://github.com/xmoer/HashLnk/blob/main/HashLnk.cs (坑晨)
+    public static class WinXHasher
+    {
+        [DllImport("shlwapi.dll", CharSet = CharSet.Unicode, ExactSpelling = true, SetLastError = true)]
+        private static extern int HashData(
+            [In][MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.U1, SizeParamIndex = 1)] byte[] pbData, int cbData,
+            [Out][MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.U1, SizeParamIndex = 3)] byte[] pbHash, int cbHash);
+
+        [DllImport("shell32.dll", CharSet = CharSet.Unicode, PreserveSig = false)]
+        private static extern uint SHCreateItemFromParsingName([MarshalAs(UnmanagedType.LPWStr)] string pszPath,
+        IBindCtx pbc, [MarshalAs(UnmanagedType.LPStruct)] Guid riid, out IShellItem ppv);
+
+        [DllImport("ole32.dll", PreserveSig = false)]
+        private extern static void PropVariantClear([In, Out] PropVariant pvar);
+
+        [DllImport("propsys.dll", CharSet = CharSet.Unicode, SetLastError = true)]
+        private static extern int PSGetPropertyKeyFromName([In][MarshalAs(UnmanagedType.LPWStr)] string pszCanonicalName, out PropertyKey propkey);
+
+        [ComImport]
+        [Guid("886D8EEB-8CF2-4446-8D02-CDBA1DBDCF99")]
+        [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
+        interface IPropertyStore
+        {
+            [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+            void GetCount([Out] out uint cProps);
+
+            [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+            void GetAt([In] uint iProp, out PropertyKey pkey);
+
+            [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+            void GetValue([In] ref PropertyKey key, out PropVariant pv);
+
+            [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+            void SetValue([In] ref PropertyKey key, [In] ref PropVariant pv);
+
+            [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+            void Commit();
+        }
+
+        [ComImport]
+        [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
+        [Guid("43826d1e-e718-42ee-bc55-a1e261c37bfe")]
+        interface IShellItem
+        {
+            void BindToHandler(IntPtr pbc,
+                [MarshalAs(UnmanagedType.LPStruct)] Guid bhid,
+                [MarshalAs(UnmanagedType.LPStruct)] Guid riid,
+                out IntPtr ppv);
+
+            void GetParent(out IShellItem ppsi);
+
+            void GetDisplayName(SIGDN sigdnName, out IntPtr ppszName);
+
+            void GetAttributes(uint sfgaoMask, out uint psfgaoAttribs);
+
+            void Compare(IShellItem psi, uint hint, out int piOrder);
+        }
+
+        [ComImport]
+        [SuppressUnmanagedCodeSecurity]
+        [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
+        [Guid("7e9fb0d3-919f-4307-ab2e-9b1860310c93")]
+        interface IShellItem2 : IShellItem
+        {
+            [return: MarshalAs(UnmanagedType.Interface)]
+            object BindToHandler(IBindCtx pbc, [In] ref Guid bhid, [In] ref Guid riid);
+
+            IShellItem GetParent();
+
+            [return: MarshalAs(UnmanagedType.LPWStr)]
+            string GetDisplayName(SIGDN sigdnName);
+
+            SFGAO GetAttributes(SFGAO sfgaoMask);
+
+            int Compare(IShellItem psi, SICHINT hint);
+
+            [return: MarshalAs(UnmanagedType.Interface)]
+            IPropertyStore GetPropertyStore(GPS flags, [In] ref Guid riid);
+
+            [return: MarshalAs(UnmanagedType.Interface)]
+            object GetPropertyStoreWithCreateObject(GPS flags, [MarshalAs(UnmanagedType.IUnknown)] object punkCreateObject, [In] ref Guid riid);
+
+            [return: MarshalAs(UnmanagedType.Interface)]
+            object GetPropertyStoreForKeys(IntPtr rgKeys, uint cKeys, GPS flags, [In] ref Guid riid);
+
+            [return: MarshalAs(UnmanagedType.Interface)]
+            object GetPropertyDescriptionList(IntPtr keyType, [In] ref Guid riid);
+
+            void Update(IBindCtx pbc);
+
+            [SecurityCritical]
+            void GetProperty(IntPtr key, [In][Out] PropVariant pv);
+
+            Guid GetCLSID(IntPtr key);
+
+            ComTypes.FILETIME GetFileTime(IntPtr key);
+
+            int GetInt32(IntPtr key);
+
+            [return: MarshalAs(UnmanagedType.LPWStr)]
+            string GetString(PropertyKey key);
+
+            uint GetUInt32(IntPtr key);
+
+            ulong GetUInt64(IntPtr key);
+
+            [return: MarshalAs(UnmanagedType.Bool)]
+            bool GetBool(IntPtr key);
+        }
+
+        [StructLayout(LayoutKind.Sequential, Pack = 4)]
+        struct PropertyKey
+        {
+            public Guid GUID;
+            public int PID;
+        }
+
+        [StructLayout(LayoutKind.Explicit, Pack = 1)]
+        struct PropVariant
+        {
+            [FieldOffset(0)]
+            public VarEnum VarType;
+            [FieldOffset(2)]
+            public ushort wReserved1;
+            [FieldOffset(4)]
+            public ushort wReserved2;
+            [FieldOffset(6)]
+            public ushort wReserved3;
+            [FieldOffset(8)]
+            public byte bVal;
+            [FieldOffset(8)]
+            public sbyte cVal;
+            [FieldOffset(8)]
+            public ushort uiVal;
+            [FieldOffset(8)]
+            public short iVal;
+            [FieldOffset(8)]
+            public uint uintVal;
+            [FieldOffset(8)]
+            public int intVal;
+            [FieldOffset(8)]
+            public ulong ulVal;
+            [FieldOffset(8)]
+            public long lVal;
+            [FieldOffset(8)]
+            public float fltVal;
+            [FieldOffset(8)]
+            public double dblVal;
+            [FieldOffset(8)]
+            public short boolVal;
+            [FieldOffset(8)]
+            public IntPtr pclsidVal;
+            [FieldOffset(8)]
+            public IntPtr pszVal;
+            [FieldOffset(8)]
+            public IntPtr pwszVal;
+            [FieldOffset(8)]
+            public IntPtr punkVal;
+            [FieldOffset(8)]
+            public IntPtr ca;
+            [FieldOffset(8)]
+            public ComTypes.FILETIME filetime;
+
+        }
+
+        enum SIGDN : uint
+        {
+            NORMALDISPLAY = 0,
+            PARENTRELATIVEPARSING = 0x80018001,
+            PARENTRELATIVEFORADDRESSBAR = 0x8001c001,
+            DESKTOPABSOLUTEPARSING = 0x80028000,
+            PARENTRELATIVEEDITING = 0x80031001,
+            DESKTOPABSOLUTEEDITING = 0x8004c000,
+            FILESYSPATH = 0x80058000,
+            URL = 0x80068000
+        }
+
+        [Flags]
+        enum SFGAO : uint
+        {
+            CANCOPY = 1u,
+            CANMOVE = 2u,
+            CANLINK = 4u,
+            STORAGE = 8u,
+            CANRENAME = 16u,
+            CANDELETE = 32u,
+            HASPROPSHEET = 64u,
+            DROPTARGET = 256u,
+            CAPABILITYMASK = 375u,
+            ENCRYPTED = 8192u,
+            ISSLOW = 16384u,
+            GHOSTED = 32768u,
+            LINK = 65536u,
+            SHARE = 131072u,
+            READONLY = 262144u,
+            HIDDEN = 524288u,
+            DISPLAYATTRMASK = 1032192u,
+            FILESYSANCESTOR = 268435456u,
+            FOLDER = 536870912u,
+            FILESYSTEM = 1073741824u,
+            HASSUBFOLDER = 2147483648u,
+            CONTENTSMASK = 2147483648u,
+            VALIDATE = 16777216u,
+            REMOVABLE = 33554432u,
+            COMPRESSED = 67108864u,
+            BROWSABLE = 134217728u,
+            NONENUMERATED = 1048576u,
+            NEWCONTENT = 2097152u,
+            CANMONIKER = 4194304u,
+            HASSTORAGE = 4194304u,
+            STREAM = 4194304u,
+            STORAGEANCESTOR = 8388608u,
+            STORAGECAPMASK = 1891958792u,
+            PKEYSFGAOMASK = 2164539392u
+        }
+
+        [Flags]
+        enum SICHINT : uint
+        {
+            DISPLAY = 0u,
+            ALLFIELDS = 2147483648u,
+            CANONICAL = 268435456u,
+            TEST_FILESYSPATH_IF_NOT_EQUAL = 536870912u
+        }
+
+        [Flags]
+        enum GPS
+        {
+            DEFAULT = 0x00000000,
+            HANDLERPROPERTIESONLY = 0x00000001,
+            READWRITE = 0x00000002,
+            TEMPORARY = 0x00000004,
+            FASTPROPERTIESONLY = 0x00000008,
+            OPENSLOWITEM = 0x00000010,
+            DELAYCREATION = 0x00000020,
+            BESTEFFORT = 0x00000040,
+            NO_OPLOCK = 0x00000080,
+            MASK_VALID = 0x000000FF
+        }
+
+        public static void HashLnk(string lnkPath)
+        {
+            SHCreateItemFromParsingName(lnkPath, null, typeof(IShellItem2).GUID, out IShellItem item);
+            IShellItem2 item2 = (IShellItem2)item;
+            PSGetPropertyKeyFromName("System.Link.TargetParsingPath", out PropertyKey pk);
+            //PKEY_Link_TargetParsingPath
+            //pk.GUID = new Guid("{B9B4B3FC-2B51-4A42-B5D8-324146AFCF25}");
+            //pk.PID = 2;
+            string targetPath;
+            try { targetPath = item2.GetString(pk); }
+            catch { targetPath = null; }
+
+            PSGetPropertyKeyFromName("System.Link.Arguments", out pk);
+            //PKEY_Link_Arguments
+            //pk.GUID = new Guid("{436F2667-14E2-4FEB-B30A-146C53B5B674}");
+            //pk.PID = 100;
+            string arguments;
+            try { arguments = item2.GetString(pk); }
+            catch { arguments = null; }
+
+            string blob = GetGeneralizePath(targetPath) + arguments;
+            blob += "do not prehash links.  this should only be done by the user.";//特殊但必须存在的字符串
+            blob = blob.ToLower();
+            byte[] inBytes = Encoding.Unicode.GetBytes(blob);
+            int byteCount = inBytes.Length;
+            byte[] outBytes = new byte[byteCount];
+            HashData(inBytes, byteCount, outBytes, byteCount);
+            uint hash = BitConverter.ToUInt32(outBytes, 0);
+
+            Guid guid = typeof(IPropertyStore).GUID;
+            IPropertyStore store = item2.GetPropertyStore(GPS.READWRITE, ref guid);
+            PSGetPropertyKeyFromName("System.Winx.Hash", out pk);
+            //PKEY_WINX_HASH
+            //pk.GUID = new Guid("{FB8D2D7B-90D1-4E34-BF60-6EAC09922BBF}");
+            //pk.PID = 2;
+            PropVariant pv = new PropVariant { VarType = VarEnum.VT_UI4, ulVal = hash };
+            store.SetValue(ref pk, ref pv);
+            store.Commit();
+
+            Marshal.ReleaseComObject(store);
+            Marshal.ReleaseComObject(item);
+            PropVariantClear(pv);
+        }
+
+        private static readonly Dictionary<string, string> GeneralizePathDic = new Dictionary<string, string>
+        {
+            { "%ProgramFiles%", "{905e63b6-c1bf-494e-b29c-65b732d3d21a}" },
+            { "%SystemRoot%\\System32", "{1ac14e77-02e7-4e5d-b744-2eb1ae5198b7}" },
+            { "%SystemRoot%", "{f38bf404-1d43-42f2-9305-67de0b28fc23}" }
+        };
+
+        private static string GetGeneralizePath(string filePath)
+        {
+            if(filePath == null) return null;
+            foreach(var kv in GeneralizePathDic)
+            {
+                string dirPath = Environment.ExpandEnvironmentVariables(kv.Key) + "\\";
+                if(filePath.StartsWith(dirPath, StringComparison.OrdinalIgnoreCase))
+                {
+                    filePath = filePath.Replace(dirPath, kv.Value + "\\"); break;
+                }
+            }
+            return filePath;
+        }
+    }
+}

+ 1 - 1
ContextMenuManager/BluePointLilac.Methods/WindowsOsVersion.cs

@@ -44,6 +44,6 @@ namespace BluePointLilac.Methods
         public static readonly bool ISAfterOrEqualVista = ShortVersion >= Vista;
         public static readonly bool ISBeforeOrEqualVista = ShortVersion <= Vista;
 
-        public static readonly bool IsAfterOrEqualWin10_1703 = OsVersion.CompareTo(new Version(10, 0, 15063)) >= 0;
+        public static readonly bool IsAfterOrEqualWin10_1703 = OsVersion > new Version(10, 0, 15063);
     }
 }

+ 0 - 202
ContextMenuManager/BluePointLilac.Methods/WshShortcut.cs

@@ -1,202 +0,0 @@
-using System;
-using System.IO;
-using System.Reflection;
-using System.Runtime.InteropServices;
-using System.Runtime.InteropServices.ComTypes;
-using System.Text;
-
-namespace BluePointLilac.Methods
-{
-    //为兼容.Net Framework 3.5无法使用dynamic和Interop.IWshRuntimeLibrary.dll专门写出此类
-    public sealed class WshShortcut : IDisposable
-    {
-        private static readonly Type ShellType = Type.GetTypeFromCLSID(new Guid("72C24DD5-D70A-438B-8A42-98424B88AFB8"));
-        private static readonly object Shell = Activator.CreateInstance(ShellType);
-        private static readonly BindingFlags InvokeMethodFlag = BindingFlags.Public | BindingFlags.Instance | BindingFlags.InvokeMethod;
-        private static readonly BindingFlags GetPropertyFlag = BindingFlags.Public | BindingFlags.Instance | BindingFlags.GetProperty;
-        private static readonly BindingFlags SetPropertyFlag = BindingFlags.Public | BindingFlags.Instance | BindingFlags.SetProperty;
-
-        private static object CreateShortcut(string lnkPath)
-        {
-            return ShellType.InvokeMember("CreateShortcut", InvokeMethodFlag, null, Shell, new[] { lnkPath });
-        }
-
-        public WshShortcut(string lnkPath)
-        {
-            //只调用CreateShortcut方法时,TargetPath值为null,
-            //其他属性值正常,只有调用一下Save方法才能获取到TargetPath值
-            this.lnkPath = lnkPath;
-            shortcut = CreateShortcut(lnkPath);
-            shortcutType = shortcut.GetType();
-            shellLink = (IShellLinkA)new ShellLink();
-            if(File.Exists(lnkPath))
-            {
-                Save();
-                ((IPersistFile)shellLink).Load(lnkPath, 2);//STGM_READWRITE
-            }
-        }
-
-        private readonly string lnkPath;
-        private readonly object shortcut;
-        private readonly Type shortcutType;
-        private readonly IShellLinkA shellLink;
-
-        public string FullName
-        {
-            get => GetValue("FullName")?.ToString();
-        }
-        public string TargetPath
-        {
-            get => GetValue("TargetPath")?.ToString();
-            set => SetValue("TargetPath", value);
-        }
-        public string Arguments
-        {
-            get => GetValue("Arguments")?.ToString();
-            set => SetValue("Arguments", value);
-        }
-        public string WorkingDirectory
-        {
-            get => GetValue("WorkingDirectory")?.ToString();
-            set => SetValue("WorkingDirectory", value);
-        }
-        public string IconLocation
-        {
-            get => GetValue("IconLocation")?.ToString();
-            set => SetValue("IconLocation", value);
-        }
-        public string Description
-        {
-            get => GetValue("Description")?.ToString();
-            set => SetValue("Description", value);
-        }
-        public string Hotkey
-        {
-            get => GetValue("Hotkey")?.ToString();
-            set => SetValue("Hotkey", value);
-        }
-        public int WindowStyle
-        {
-            get => Convert.ToInt32(GetValue("WindowStyle"));
-            set => SetValue("WindowStyle", value);
-        }
-        public bool RunAsAdministrator
-        {
-            get
-            {
-                ((IShellLinkDataList)shellLink).GetFlags(out ShellLinkDataFlags flags);
-                return (flags & ShellLinkDataFlags.RunasUser) == ShellLinkDataFlags.RunasUser;
-            }
-            set
-            {
-                ((IShellLinkDataList)shellLink).GetFlags(out ShellLinkDataFlags flags);
-                if(value) flags |= ShellLinkDataFlags.RunasUser;
-                else flags &= ~ShellLinkDataFlags.RunasUser;
-                ((IShellLinkDataList)shellLink).SetFlags(flags);
-                ((IPersistFile)shellLink).Save(lnkPath, true);
-            }
-        }
-
-        private object GetValue(string name)
-        {
-            try { return shortcutType.InvokeMember(name, GetPropertyFlag, null, shortcut, null); }
-            catch { return null; }
-        }
-
-        private void SetValue(string name, object value)
-        {
-            shortcutType.InvokeMember(name, SetPropertyFlag, null, shortcut, new[] { value });
-        }
-
-        public void Save()
-        {
-            //存储快捷方式为写入文件行为,如果没有权限会报错
-            shortcutType.InvokeMember("Save", InvokeMethodFlag, null, shortcut, null);
-        }
-
-        public void Dispose()
-        {
-            Marshal.ReleaseComObject(shortcut);
-            Marshal.ReleaseComObject(shellLink);
-        }
-
-        ~WshShortcut() { Dispose(); }
-
-
-        [ComImport]
-        [Guid("00021401-0000-0000-C000-000000000046")]
-        internal class ShellLink { }
-
-        [ComImport]
-        [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
-        [Guid("000214EE-0000-0000-C000-000000000046")]
-        public interface IShellLinkA
-        {
-            void GetPath([Out, MarshalAs(UnmanagedType.LPStr)] StringBuilder pszFile, int cchMaxPath, out IntPtr pfd, int fFlags);
-            void GetIDList(out IntPtr ppidl);
-            void SetIDList(IntPtr pidl);
-            void GetDescription([Out, MarshalAs(UnmanagedType.LPStr)] StringBuilder pszName, int cchMaxName);
-            void SetDescription([MarshalAs(UnmanagedType.LPStr)] string pszName);
-            void GetWorkingDirectory([Out, MarshalAs(UnmanagedType.LPStr)] StringBuilder pszDir, int cchMaxPath);
-            void SetWorkingDirectory([MarshalAs(UnmanagedType.LPStr)] string pszDir);
-            void GetArguments([Out, MarshalAs(UnmanagedType.LPStr)] StringBuilder pszArgs, int cchMaxPath);
-            void SetArguments([MarshalAs(UnmanagedType.LPStr)] string pszArgs);
-            void GetHotkey(out short pwHotkey);
-            void SetHotkey(short wHotkey);
-            void GetShowCmd(out int piShowCmd);
-            void SetShowCmd(int iShowCmd);
-            void GetIconLocation([Out, MarshalAs(UnmanagedType.LPStr)] StringBuilder pszIconPath, int cchIconPath, out int piIcon);
-            void SetIconLocation([MarshalAs(UnmanagedType.LPStr)] string pszIconPath, int iIcon);
-            void SetRelativePath([MarshalAs(UnmanagedType.LPStr)] string pszPathRel, int dwReserved);
-            void Resolve(IntPtr hwnd, int fFlags);
-            void SetPath([MarshalAs(UnmanagedType.LPStr)] string pszFile);
-        }
-
-        [ComImport]
-        [Guid("45e2b4ae-b1c3-11d0-b92f-00a0c90312e1")]
-        [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
-        interface IShellLinkDataList
-        {
-            void AddDataBlock(IntPtr pDataBlock);
-            void CopyDataBlock(uint dwSig, out IntPtr ppDataBlock);
-            void RemoveDataBlock(uint dwSig);
-            void GetFlags(out ShellLinkDataFlags pdwFlags);
-            void SetFlags(ShellLinkDataFlags dwFlags);
-        }
-
-        [Flags] // SHELL_LINK_DATA_FLAGS
-        public enum ShellLinkDataFlags : uint
-        {
-            Default = 0x00000000,
-            HasIdList = 0x00000001,
-            HasLinkInfo = 0x00000002,
-            HasName = 0x00000004,
-            HasRelpath = 0x00000008,
-            HasWorkingdir = 0x00000010,
-            HasArgs = 0x00000020,
-            HasIconLocation = 0x00000040,
-            Unicode = 0x00000080,
-            ForceNoLinkInfo = 0x00000100,
-            HasExpSz = 0x00000200,
-            RunInSeparate = 0x00000400,
-            HasLogo3Id = 0x00000800,
-            HasDarwinId = 0x00001000,
-            RunasUser = 0x00002000,
-            HasExpIconSz = 0x00004000,
-            NoPidlAlias = 0x00008000,
-            ForceUncname = 0x00010000,
-            RunWithShimlayer = 0x00020000,
-            ForceNoLinktrack = 0x00040000,
-            EnableTargetMetadata = 0x00080000,
-            DisableLinkPathTracking = 0x00100000,
-            DisableKnownfolderRelativeTracking = 0x00200000,
-            NoKFAlias = 0x00400000,
-            AllowLinkToLink = 0x00800000,
-            UnaliasOnSave = 0x01000000,
-            PreferEnvironmentPath = 0x02000000,
-            KeepLocalIdListForUncTarget = 0x04000000,
-            Valid = 0x07fff7ff,
-            Reserved = 0x80000000
-        }
-    }
-}

+ 21 - 16
ContextMenuManager/ContextMenuManager.csproj

@@ -8,13 +8,13 @@
     <OutputType>WinExe</OutputType>
     <RootNamespace>ContextMenuManager</RootNamespace>
     <AssemblyName>ContextMenuManager</AssemblyName>
-    <TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
+    <TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
     <FileAlignment>512</FileAlignment>
     <AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
     <Deterministic>true</Deterministic>
     <IsWebBootstrapper>false</IsWebBootstrapper>
     <TargetFrameworkProfile />
-    <PublishUrl>publish\</PublishUrl>
+    <PublishUrl>C:\Users\Lilac\Desktop\</PublishUrl>
     <Install>true</Install>
     <InstallFrom>Disk</InstallFrom>
     <UpdateEnabled>false</UpdateEnabled>
@@ -27,13 +27,14 @@
     <ApplicationRevision>0</ApplicationRevision>
     <ApplicationVersion>1.0.0.%2a</ApplicationVersion>
     <UseApplicationTrust>false</UseApplicationTrust>
+    <PublishWizardCompleted>true</PublishWizardCompleted>
     <BootstrapperEnabled>true</BootstrapperEnabled>
   </PropertyGroup>
   <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
     <PlatformTarget>AnyCPU</PlatformTarget>
     <DebugSymbols>true</DebugSymbols>
     <DebugType>full</DebugType>
-    <Optimize>false</Optimize>
+    <Optimize>true</Optimize>
     <OutputPath>bin\Debug\</OutputPath>
     <DefineConstants>DEBUG;TRACE</DefineConstants>
     <ErrorReport>prompt</ErrorReport>
@@ -41,6 +42,8 @@
     <Prefer32Bit>false</Prefer32Bit>
     <AllowUnsafeBlocks>false</AllowUnsafeBlocks>
     <GenerateSerializationAssemblies>Off</GenerateSerializationAssemblies>
+    <DocumentationFile>
+    </DocumentationFile>
   </PropertyGroup>
   <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
     <PlatformTarget>AnyCPU</PlatformTarget>
@@ -56,7 +59,7 @@
     <ApplicationIcon>Properties\AppIcon.ico</ApplicationIcon>
   </PropertyGroup>
   <PropertyGroup>
-    <TargetZone>LocalIntranet</TargetZone>
+    <TargetZone>Custom</TargetZone>
   </PropertyGroup>
   <PropertyGroup>
     <GenerateManifests>false</GenerateManifests>
@@ -96,6 +99,14 @@
   <PropertyGroup />
   <PropertyGroup />
   <PropertyGroup />
+  <PropertyGroup />
+  <PropertyGroup>
+    <ManifestCertificateThumbprint>BEFE3AE42DB8F7604D715C01388001CABFF0FABF</ManifestCertificateThumbprint>
+  </PropertyGroup>
+  <PropertyGroup>
+    <ManifestKeyFile>ContextMenuManager_TemporaryKey.pfx</ManifestKeyFile>
+  </PropertyGroup>
+  <PropertyGroup />
   <PropertyGroup>
     <ApplicationManifest>Properties\App.manifest</ApplicationManifest>
   </PropertyGroup>
@@ -124,8 +135,10 @@
     <Compile Include="BluePointLilac.Controls\MyToolBar.cs">
       <SubType>Component</SubType>
     </Compile>
+    <Compile Include="BluePointLilac.Methods\ComboBoxExtension.cs" />
     <Compile Include="BluePointLilac.Methods\DesktopIni.cs" />
     <Compile Include="BluePointLilac.Methods\DirectoryEx.cs" />
+    <Compile Include="BluePointLilac.Methods\ElevatedFileDroper.cs" />
     <Compile Include="BluePointLilac.Methods\FileExtension.cs" />
     <Compile Include="BluePointLilac.Methods\GuidEx.cs" />
     <Compile Include="BluePointLilac.Methods\IniReader.cs" />
@@ -137,10 +150,8 @@
     <Compile Include="BluePointLilac.Methods\StringExtension.cs" />
     <Compile Include="BluePointLilac.Methods\TextBoxExtension.cs" />
     <Compile Include="BluePointLilac.Methods\WindowsOsVersion.cs" />
-    <Compile Include="BluePointLilac.Methods\WshShortcut.cs" />
-    <Compile Include="Controls\AddGuidDicDialog.cs">
-      <SubType>Component</SubType>
-    </Compile>
+    <Compile Include="BluePointLilac.Methods\ShellLink.cs" />
+    <Compile Include="BluePointLilac.Methods\WinXHasher.cs" />
     <Compile Include="Controls\FileExtensionDialog.cs">
       <SubType>Component</SubType>
     </Compile>
@@ -348,6 +359,7 @@
     <None Include="Properties\Resources\Texts\AppLanguageDic.ini" />
     <None Include="Properties\Resources\Texts\GuidInfosDic.ini" />
     <Content Include="Properties\Resources\Images\DownLoad.png" />
+    <Content Include="Properties\Resources\Images\Jump.png" />
     <Content Include="Properties\Resources\Images\Translate.png" />
     <Content Include="Properties\Resources\Texts\UwpModeItemsDic.xml" />
     <None Include="Properties\Settings.settings">
@@ -375,8 +387,6 @@
   </ItemGroup>
   <ItemGroup>
     <Content Include="Properties\AppIcon.ico" />
-    <Content Include="Properties\Resources\HashLnk\HashLnk_32.exe" />
-    <Content Include="Properties\Resources\HashLnk\HashLnk_64.exe" />
     <Content Include="Properties\Resources\Images\Custom.png" />
     <Content Include="Properties\Resources\Images\NewFolder.png" />
     <Content Include="Properties\Resources\Images\Refresh.png" />
@@ -413,12 +423,7 @@
   </PropertyGroup>
   <PropertyGroup>
     <PostBuildEvent>mkdir $(TargetDir)\Config\languages
-mkdir $(TargetDir)\Config\Dictionaries\Web
-cd $(ProjectDir)\Properties\Resources\Texts
-xcopy AppLanguageDic.ini $(SolutionDir)\languages\zh-CN.ini /y
-xcopy EnhanceMenusDic.xml $(TargetDir)\Config\Dictionaries\Web /y
-xcopy ThirdRulesDic.xml $(TargetDir)\Config\Dictionaries\Web /y
-xcopy GuidInfosDic.ini $(TargetDir)\Config\Dictionaries\Web /y
+xcopy $(ProjectDir)\Properties\Resources\Texts\AppLanguageDic.ini $(SolutionDir)\languages\zh-CN.ini /y
 xcopy $(SolutionDir)\languages $(TargetDir)\config\languages /y</PostBuildEvent>
   </PropertyGroup>
 </Project>

+ 22 - 16
ContextMenuManager/Controls/AboutApp.cs

@@ -174,6 +174,7 @@ namespace ContextMenuManager.Controls
             MyToolTip.SetToolTip(btnDownLoad, AppString.Tip.OtherLanguages);
             MyToolTip.SetToolTip(btnTranslate, AppString.Dialog.TranslateTool);
             txtTranslators.SetAutoShowScroll(ScrollBars.Vertical);
+            cmbLanguages.AutosizeDropDownWidth();
             this.OnResize(null);
         }
 
@@ -267,6 +268,9 @@ namespace ContextMenuManager.Controls
             mliWinXSortable.AddCtr(chkWinXSortable);
             mliShowFilePath.AddCtr(chkShowFilePath);
             mliOpenMoreRegedit.AddCtr(chkOpenMoreRegedit);
+            mliHideDisabledItems.AddCtr(chkHideDisabledItems);
+            cmbConfigDir.AutosizeDropDownWidth();
+            cmbEngine.AutosizeDropDownWidth();
             MyToolTip.SetToolTip(cmbConfigDir, AppString.Tip.ConfigPath);
             MyToolTip.SetToolTip(btnConfigDir, AppString.Other.OpenConfigDir);
             MyToolTip.SetToolTip(btnBackupDir, AppString.Other.OpenBackupDir);
@@ -324,6 +328,7 @@ namespace ContextMenuManager.Controls
             chkProtect.MouseDown += (sender, e) => AppConfig.ProtectOpenItem = chkProtect.Checked = !chkProtect.Checked;
             chkWinXSortable.MouseDown += (sender, e) => AppConfig.WinXSortable = chkWinXSortable.Checked = !chkWinXSortable.Checked;
             chkOpenMoreRegedit.MouseDown += (sender, e) => AppConfig.OpenMoreRegedit = chkOpenMoreRegedit.Checked = !chkOpenMoreRegedit.Checked;
+            chkHideDisabledItems.MouseDown += (sender, e) => AppConfig.HideDisabledItems = chkHideDisabledItems.Checked = !chkHideDisabledItems.Checked;
             chkShowFilePath.MouseDown += (sender, e) =>
             {
                 chkShowFilePath.Checked = !chkShowFilePath.Checked;
@@ -341,8 +346,7 @@ namespace ContextMenuManager.Controls
 
         readonly MyListItem mliConfigDir = new MyListItem
         {
-            Text = AppString.Other.ConfigPath,
-            HasImage = false
+            Text = AppString.Other.ConfigPath
         };
         readonly ComboBox cmbConfigDir = new ComboBox
         {
@@ -353,16 +357,14 @@ namespace ContextMenuManager.Controls
 
         readonly MyListItem mliBackup = new MyListItem
         {
-            Text = AppString.Other.AutoBackup,
-            HasImage = false
+            Text = AppString.Other.AutoBackup
         };
         readonly MyCheckBox chkBackup = new MyCheckBox();
         readonly PictureButton btnBackupDir = new PictureButton(AppImage.Open);
 
         readonly MyListItem mliUpdate = new MyListItem
         {
-            Text = AppString.Other.CheckUpdate,
-            HasImage = false
+            Text = AppString.Other.CheckUpdate
         };
         readonly Label lblUpdate = new Label
         {
@@ -388,15 +390,13 @@ namespace ContextMenuManager.Controls
 
         readonly MyListItem mliProtect = new MyListItem
         {
-            Text = AppString.Other.ProtectOpenItem,
-            HasImage = false
+            Text = AppString.Other.ProtectOpenItem
         };
         readonly MyCheckBox chkProtect = new MyCheckBox();
 
         readonly MyListItem mliEngine = new MyListItem
         {
-            Text = AppString.Other.WebSearchEngine,
-            HasImage = false
+            Text = AppString.Other.WebSearchEngine
         };
         readonly ComboBox cmbEngine = new ComboBox
         {
@@ -414,18 +414,22 @@ namespace ContextMenuManager.Controls
 
         readonly MyListItem mliShowFilePath = new MyListItem
         {
-            Text = AppString.Other.ShowFilePath,
-            HasImage = false
+            Text = AppString.Other.ShowFilePath
         };
         readonly MyCheckBox chkShowFilePath = new MyCheckBox();
 
         readonly MyListItem mliOpenMoreRegedit = new MyListItem
         {
-            Text = AppString.Other.OpenMoreRegedit,
-            HasImage = false
+            Text = AppString.Other.OpenMoreRegedit
         };
         readonly MyCheckBox chkOpenMoreRegedit = new MyCheckBox();
 
+        readonly MyListItem mliHideDisabledItems = new MyListItem
+        {
+            Text = AppString.Other.HideDisabledItems
+        };
+        readonly MyCheckBox chkHideDisabledItems = new MyCheckBox();
+
         protected override void OnVisibleChanged(EventArgs e)
         {
             base.OnVisibleChanged(e);
@@ -434,14 +438,16 @@ namespace ContextMenuManager.Controls
 
         public void LoadItems()
         {
-            this.AddItems(new[] { mliUpdate, mliConfigDir, mliEngine, mliBackup,
-                mliProtect, mliWinXSortable, mliShowFilePath, mliOpenMoreRegedit });
+            this.AddItems(new[] { mliUpdate, mliConfigDir, mliEngine, mliBackup, mliProtect,
+                mliWinXSortable, mliShowFilePath, mliOpenMoreRegedit, mliHideDisabledItems });
+            foreach(MyListItem item in this.Controls) item.HasImage = false;
             cmbConfigDir.SelectedIndex = AppConfig.SaveToAppDir ? 1 : 0;
             chkBackup.Checked = AppConfig.AutoBackup;
             chkProtect.Checked = AppConfig.ProtectOpenItem;
             chkWinXSortable.Checked = AppConfig.WinXSortable;
             chkShowFilePath.Checked = AppConfig.ShowFilePath;
             chkOpenMoreRegedit.Checked = AppConfig.OpenMoreRegedit;
+            chkHideDisabledItems.Checked = AppConfig.HideDisabledItems;
 
             string url = AppConfig.EngineUrl;
             for(int i = 0; i <= AppConfig.EngineUrls.Length; i++)

+ 0 - 151
ContextMenuManager/Controls/AddGuidDicDialog.cs

@@ -1,151 +0,0 @@
-using BluePointLilac.Controls;
-using BluePointLilac.Methods;
-using System;
-using System.Drawing;
-using System.Windows.Forms;
-
-namespace ContextMenuManager.Controls
-{
-    sealed class AddGuidDicDialog : CommonDialog
-    {
-        public Image ItemIcon { get; set; }
-        public string ItemText { get; set; }
-        public bool IsDelete { get; private set; }
-        public string ItemIconPath { get; set; }
-        public int ItemIconIndex { get; set; }
-        public string ItemIconLocation
-        {
-            get
-            {
-                if(ItemIconPath == null) return null;
-                return $"{ItemIconPath},{ItemIconIndex}";
-            }
-        }
-
-        public override void Reset() { }
-
-        protected override bool RunDialog(IntPtr hwndOwner)
-        {
-            using(AddGuidDicForm frm = new AddGuidDicForm())
-            {
-                frm.ItemText = this.ItemText;
-                frm.ItemIcon = this.ItemIcon;
-                frm.ItemIconPath = this.ItemIconPath;
-                frm.ItemIconIndex = this.ItemIconIndex;
-                bool flag = frm.ShowDialog() == DialogResult.OK;
-                if(flag)
-                {
-                    this.ItemText = frm.ItemText;
-                    this.ItemIcon = frm.ItemIcon;
-                    this.ItemIconPath = frm.ItemIconPath;
-                    this.ItemIconIndex = frm.ItemIconIndex;
-                }
-                this.IsDelete = frm.IsDelete;
-                return flag;
-            }
-        }
-
-        sealed class AddGuidDicForm : Form
-        {
-            public AddGuidDicForm()
-            {
-                this.AcceptButton = btnOk;
-                this.CancelButton = btnCancel;
-                this.Font = SystemFonts.MenuFont;
-                this.Text = AppString.Dialog.AddGuidDic;
-                this.ShowIcon = this.ShowInTaskbar = false;
-                this.MaximizeBox = this.MinimizeBox = false;
-                this.FormBorderStyle = FormBorderStyle.FixedSingle;
-                this.StartPosition = FormStartPosition.CenterParent;
-                InitializeComponents();
-            }
-
-            public string ItemText
-            {
-                get => txtName.Text;
-                set => txtName.Text = value;
-            }
-            public Image ItemIcon
-            {
-                get => picIcon.Image;
-                set => picIcon.Image = value;
-            }
-            public string ItemIconPath { get; set; }
-            public int ItemIconIndex { get; set; }
-            public bool IsDelete { get; private set; }
-
-            readonly TextBox txtName = new TextBox();
-            readonly Label lblName = new Label
-            {
-                Text = AppString.Dialog.ItemName,
-                AutoSize = true
-            };
-            readonly Label lblIcon = new Label
-            {
-                Text = AppString.Dialog.ItemIcon,
-                AutoSize = true
-            };
-            readonly PictureBox picIcon = new PictureBox
-            {
-                Size = SystemInformation.IconSize
-            };
-            readonly Button btnBrowse = new Button
-            {
-                Text = AppString.Dialog.Browse,
-                AutoSize = true
-            };
-            readonly Button btnOk = new Button
-            {
-                Text = AppString.Dialog.Ok,
-                DialogResult = DialogResult.OK,
-                AutoSize = true
-            };
-            readonly Button btnCancel = new Button
-            {
-                Text = AppString.Dialog.Cancel,
-                DialogResult = DialogResult.Cancel,
-                AutoSize = true
-            };
-            readonly Button btnDelete = new Button
-            {
-                Text = AppString.Dialog.DeleteGuidDic,
-                DialogResult = DialogResult.Cancel,
-                AutoSize = true
-            };
-
-            private void InitializeComponents()
-            {
-                this.Controls.AddRange(new Control[] { lblName, txtName, lblIcon, picIcon, btnBrowse, btnDelete, btnOk, btnCancel });
-                int a = 20.DpiZoom();
-                lblName.Left = lblName.Top = lblIcon.Left = btnDelete.Left = txtName.Top = a;
-                txtName.Left = lblName.Right + a;
-                btnOk.Left = btnDelete.Right + a;
-                btnCancel.Left = btnOk.Right + a;
-                txtName.Width = btnCancel.Right - txtName.Left;
-                btnBrowse.Left = btnCancel.Right - btnBrowse.Width;
-                picIcon.Left = btnOk.Left + (btnOk.Width - picIcon.Width) / 2;
-                btnBrowse.Top = txtName.Bottom + a;
-                picIcon.Top = btnBrowse.Top + (btnBrowse.Height - picIcon.Height) / 2;
-                lblIcon.Top = btnBrowse.Top + (btnBrowse.Height - lblIcon.Height) / 2;
-                btnDelete.Top = btnOk.Top = btnCancel.Top = btnBrowse.Bottom + a;
-                this.ClientSize = new Size(btnCancel.Right + a, btnCancel.Bottom + a);
-                MyToolTip.SetToolTip(btnDelete, AppString.Tip.DeleteGuidDic);
-                btnBrowse.Click += (sender, e) => SelectIcon();
-                btnDelete.Click += (sender, e) => this.IsDelete = true;
-            }
-
-            private void SelectIcon()
-            {
-                using(IconDialog dlg = new IconDialog())
-                {
-                    dlg.IconPath = this.ItemIconPath;
-                    dlg.IconIndex = this.ItemIconIndex;
-                    if(dlg.ShowDialog() != DialogResult.OK) return;
-                    ItemIconPath = dlg.IconPath;
-                    ItemIconIndex = dlg.IconIndex;
-                    picIcon.Image = ResourceIcon.GetIcon(ItemIconPath, ItemIconIndex).ToBitmap();
-                }
-            }
-        }
-    }
-}

+ 3 - 1
ContextMenuManager/Controls/EnhanceMenusItem.cs

@@ -34,7 +34,6 @@ namespace ContextMenuManager.Controls
         public EnhanceShellItem()
         {
             ChkVisible = new VisibleCheckBox(this);
-            this.SetNoClickEvent();
         }
 
         private static void WriteAttributesValue(XmlNode valueXN, string regPath)
@@ -98,6 +97,9 @@ namespace ContextMenuManager.Controls
             if(string.IsNullOrEmpty(arguments)) arguments = CreateCommandFile(argXE);
             fileName = Environment.ExpandEnvironmentVariables(fileName);
             arguments = Environment.ExpandEnvironmentVariables(arguments);
+            string prefix = argXE?.GetAttribute("Prefix");
+            string suffix = argXE?.GetAttribute("Suffix");
+            arguments = prefix + arguments + suffix;
             if(seXE != null)
             {
                 string verb = seXE.HasAttribute("Verb") ? seXE.GetAttribute("Verb") : "open";

+ 7 - 3
ContextMenuManager/Controls/EnhanceMenusList.cs

@@ -92,7 +92,11 @@ namespace ContextMenuManager.Controls
                     path = xe.GetAttribute("RegPath");
                     text = ResourceString.GetDirectString(xe.GetAttribute("Text"));
                     if(string.IsNullOrEmpty(path) || string.IsNullOrEmpty(text)) return null;
-                    image = ResourceIcon.GetIcon(xe.GetAttribute("Icon"))?.ToBitmap() ?? AppImage.NotFound;
+                    using(Icon icon = ResourceIcon.GetIcon(xe.GetAttribute("Icon")))
+                    {
+                        if(icon != null) image = icon.ToBitmap();
+                        else image = AppImage.NotFound;
+                    }
                     break;
             }
             GroupPathItem groupItem = new GroupPathItem(path, ObjectPath.PathType.Registry) { Image = image, Text = text };
@@ -143,7 +147,7 @@ namespace ContextMenuManager.Controls
                 {
                     if(!tip.IsNullOrWhiteSpace()) tip += "\n";
                     tip += AppString.Tip.CommandFiles;
-                    if(System.Diagnostics.Debugger.IsAttached) item.ChkVisible.Checked = item.ItemVisible = true;//调试状态
+                    //if(System.Diagnostics.Debugger.IsAttached) item.ChkVisible.Checked = item.ItemVisible = true;//调试状态
                 }
                 MyToolTip.SetToolTip(item.ChkVisible, tip);
                 this.AddItem(item);
@@ -160,7 +164,7 @@ namespace ContextMenuManager.Controls
                 {
                     FoldGroupItem = groupItem,
                     ShellExPath = $@"{groupItem.TargetPath}\ShellEx",
-                    Image = ResourceIcon.GetIcon(itemXE.GetAttribute("Icon"))?.ToBitmap() ?? AppImage.DllDefaultIcon,
+                    Image = ResourceIcon.GetIcon(itemXE.GetAttribute("Icon"))?.ToBitmap() ?? AppImage.SystemFile,
                     Text = ResourceString.GetDirectString(itemXE.GetAttribute("Text")),
                     DefaultKeyName = itemXE.GetAttribute("KeyName"),
                     Guid = guid

+ 11 - 6
ContextMenuManager/Controls/FileExtensionDialog.cs

@@ -1,7 +1,6 @@
 using BluePointLilac.Methods;
 using System;
 using System.Collections.Generic;
-using System.Windows.Forms;
 
 namespace ContextMenuManager.Controls
 {
@@ -9,18 +8,24 @@ namespace ContextMenuManager.Controls
     {
         public string Extension
         {
-            get => Selected;
-            set => Selected = value;
+            get => Selected.Trim();
+            set => Selected = value?.Trim();
         }
 
         public FileExtensionDialog()
         {
+            this.CanEdit = true;
             this.Title = AppString.Dialog.SelectExtension;
-            this.DropDownStyle = ComboBoxStyle.DropDown;
             List<string> items = new List<string>();
-            foreach(string keyName in Microsoft.Win32.Registry.ClassesRoot.GetSubKeyNames())
+            using(var key = RegistryEx.GetRegistryKey(FileExtension.FileExtsPath))
             {
-                if(keyName.StartsWith(".")) items.Add(keyName.Substring(1));
+                if(key != null)
+                {
+                    foreach(string keyName in key.GetSubKeyNames())
+                    {
+                        if(keyName.StartsWith(".")) items.Add(keyName.Substring(1));
+                    }
+                }
             }
             this.Items = items.ToArray();
         }

+ 7 - 2
ContextMenuManager/Controls/GuidBlockedItem.cs

@@ -21,7 +21,7 @@ namespace ContextMenuManager.Controls
             else
             {
                 this.Guid = Guid.Empty;
-                this.Image = AppImage.DllDefaultIcon;
+                this.Image = AppImage.SystemFile;
             }
             this.Text = this.ItemText;
         }
@@ -61,6 +61,7 @@ namespace ContextMenuManager.Controls
         public RegLocationMenuItem TsiRegLocation { get; set; }
 
         readonly ToolStripMenuItem TsiDetails = new ToolStripMenuItem(AppString.Menu.Details);
+        readonly ToolStripMenuItem TsiDelete = new ToolStripMenuItem(AppString.Menu.Delete);
 
         private void InitializeComponents()
         {
@@ -73,11 +74,15 @@ namespace ContextMenuManager.Controls
             TsiHandleGuid = new HandleGuidMenuItem(this, false);
 
             ContextMenuStrip.Items.AddRange(new ToolStripItem[] {TsiHandleGuid,
-                new ToolStripSeparator(), TsiDetails });
+                new ToolStripSeparator(), TsiDetails, new ToolStripSeparator(), TsiDelete });
             TsiDetails.DropDownItems.AddRange(new ToolStripItem[] { TsiSearch,
                 new ToolStripSeparator(), TsiFileProperties, TsiFileLocation, TsiRegLocation});
 
             MyToolTip.SetToolTip(BtnDelete, AppString.Menu.Delete);
+            TsiDelete.Click += (sender, e) =>
+            {
+                if(MessageBoxEx.Show(AppString.MessageBox.ConfirmDelete, MessageBoxButtons.YesNo) == DialogResult.Yes) DeleteMe();
+            };
         }
 
         public void DeleteMe()

+ 10 - 1
ContextMenuManager/Controls/Interfaces/IChkVisibleItem.cs

@@ -13,7 +13,8 @@ namespace ContextMenuManager.Controls.Interfaces
     {
         public VisibleCheckBox(IChkVisibleItem item)
         {
-            ((MyListItem)item).AddCtr(this);
+            MyListItem listItem = (MyListItem)item;
+            listItem.AddCtr(this);
             this.MouseDown += (sender, e) =>
             {
                 if(e.Button == MouseButtons.Left)
@@ -22,6 +23,14 @@ namespace ContextMenuManager.Controls.Interfaces
                     this.Checked = item.ItemVisible;
                 }
             };
+            listItem.ParentChanged += (sender, e) =>
+            {
+                if(listItem.IsDisposed) return;
+                if(listItem.Parent == null) return;
+                if(listItem is IFoldSubItem subItem && subItem.FoldGroupItem != null) return;
+                if(listItem.FindForm() is ShellStoreDialog.ShellStoreForm) return;
+                if(AppConfig.HideDisabledItems) listItem.Visible = item.ItemVisible;
+            };
         }
     }
 }

+ 2 - 0
ContextMenuManager/Controls/Interfaces/IFoldGroupItem.cs

@@ -98,6 +98,8 @@ namespace ContextMenuManager.Controls.Interfaces
                     break;
             }
             MyToolTip.SetToolTip(BtnOpenPath, tip);
+            this.ImageDoubleClick += (sender, e) => this.OnDoubleClick(null);
+            this.TextDoubleClick += (sender, e) => this.OnDoubleClick(null);
         }
 
         public void HideWhenNoSubItem()

+ 6 - 5
ContextMenuManager/Controls/Interfaces/ITsiAdministratorItem.cs

@@ -8,7 +8,7 @@ namespace ContextMenuManager.Controls.Interfaces
     {
         ContextMenuStrip ContextMenuStrip { get; set; }
         RunAsAdministratorItem TsiAdministrator { get; set; }
-        WshShortcut Shortcut { get; }
+        ShellLink ShellLink { get; }
     }
 
     sealed class RunAsAdministratorItem : ToolStripMenuItem
@@ -17,12 +17,12 @@ namespace ContextMenuManager.Controls.Interfaces
         {
             item.ContextMenuStrip.Opening += (sender, e) =>
             {
-                if(item.Shortcut == null)
+                if(item.ShellLink == null)
                 {
                     this.Enabled = false;
                     return;
                 }
-                string filePath = item.Shortcut.TargetPath;
+                string filePath = item.ShellLink.TargetPath;
                 string extension = Path.GetExtension(filePath)?.ToLower();
                 switch(extension)
                 {
@@ -35,11 +35,12 @@ namespace ContextMenuManager.Controls.Interfaces
                         this.Enabled = false;
                         break;
                 }
-                this.Checked = item.Shortcut.RunAsAdministrator;
+                this.Checked = item.ShellLink.RunAsAdministrator;
             };
             this.Click += (sender, e) =>
             {
-                item.Shortcut.RunAsAdministrator = !this.Checked;
+                item.ShellLink.RunAsAdministrator = !this.Checked;
+                item.ShellLink.Save();
             };
         }
     }

+ 1 - 1
ContextMenuManager/Controls/Interfaces/ITsiDeleteItem.cs

@@ -29,7 +29,7 @@ namespace ContextMenuManager.Controls.Interfaces
                      MessageBoxButtons.YesNo) != DialogResult.Yes) return;
                     string date = DateTime.Today.ToString("yyyy-MM-dd");
                     string time = DateTime.Now.ToString("HH.mm.ss");
-                    string filePath = $@"{AppConfig.BackupDir}\{date}\{regItem.Text}-{time}.reg";
+                    string filePath = $@"{AppConfig.BackupDir}\{date}\{regItem.Text} - {time}.reg";
                     Directory.CreateDirectory(Path.GetDirectoryName(filePath));
                     RegistryEx.Export(regItem.RegPath, filePath);
                 }

+ 150 - 4
ContextMenuManager/Controls/Interfaces/ITsiGuidItem.cs

@@ -1,7 +1,7 @@
 using BluePointLilac.Controls;
 using BluePointLilac.Methods;
-using Microsoft.Win32;
 using System;
+using System.Drawing;
 using System.Windows.Forms;
 
 namespace ContextMenuManager.Controls.Interfaces
@@ -29,12 +29,15 @@ namespace ContextMenuManager.Controls.Interfaces
             TsiCopyGuid.Click += (sender, e) => CopyGuid();
             TsiBlockGuid.Click += (sender, e) => BlockGuid();
             TsiAddGuidDic.Click += (sender, e) => AddGuidDic();
-            ((Control)item).ContextMenuStrip.Opening += (sender, e) =>
+            MyListItem listItem = (MyListItem)item;
+            listItem.ImageDoubleClick += (sender, e) => AddGuidDic();
+            listItem.TextDoubleClick += (sender, e) => AddGuidDic();
+            listItem.ContextMenuStrip.Opening += (sender, e) =>
             {
                 TsiBlockGuid.Checked = false;
                 foreach(string path in GuidBlockedList.BlockedPaths)
                 {
-                    if(Registry.GetValue(path, Item.Guid.ToString("B"), null) != null)
+                    if(Microsoft.Win32.Registry.GetValue(path, Item.Guid.ToString("B"), null) != null)
                     {
                         TsiBlockGuid.Checked = true;
                         break;
@@ -66,7 +69,7 @@ namespace ContextMenuManager.Controls.Interfaces
                 }
                 else
                 {
-                    Registry.SetValue(path, Item.Guid.ToString("B"), string.Empty);
+                    Microsoft.Win32.Registry.SetValue(path, Item.Guid.ToString("B"), string.Empty);
                 }
             }
             ExplorerRestarter.Show();
@@ -144,5 +147,148 @@ namespace ContextMenuManager.Controls.Interfaces
                 }
             }
         }
+
+        sealed class AddGuidDicDialog : CommonDialog
+        {
+            public Image ItemIcon { get; set; }
+            public string ItemText { get; set; }
+            public bool IsDelete { get; private set; }
+            public string ItemIconPath { get; set; }
+            public int ItemIconIndex { get; set; }
+            public string ItemIconLocation
+            {
+                get
+                {
+                    if(ItemIconPath == null) return null;
+                    return $"{ItemIconPath},{ItemIconIndex}";
+                }
+            }
+
+            public override void Reset() { }
+
+            protected override bool RunDialog(IntPtr hwndOwner)
+            {
+                using(AddGuidDicForm frm = new AddGuidDicForm())
+                {
+                    frm.ItemText = this.ItemText;
+                    frm.ItemIcon = this.ItemIcon;
+                    frm.ItemIconPath = this.ItemIconPath;
+                    frm.ItemIconIndex = this.ItemIconIndex;
+                    bool flag = frm.ShowDialog() == DialogResult.OK;
+                    if(flag)
+                    {
+                        this.ItemText = frm.ItemText;
+                        this.ItemIcon = frm.ItemIcon;
+                        this.ItemIconPath = frm.ItemIconPath;
+                        this.ItemIconIndex = frm.ItemIconIndex;
+                    }
+                    this.IsDelete = frm.IsDelete;
+                    return flag;
+                }
+            }
+
+            sealed class AddGuidDicForm : Form
+            {
+                public AddGuidDicForm()
+                {
+                    this.AcceptButton = btnOk;
+                    this.CancelButton = btnCancel;
+                    this.Font = SystemFonts.MenuFont;
+                    this.Text = AppString.Dialog.AddGuidDic;
+                    this.ShowIcon = this.ShowInTaskbar = false;
+                    this.MaximizeBox = this.MinimizeBox = false;
+                    this.FormBorderStyle = FormBorderStyle.FixedSingle;
+                    this.StartPosition = FormStartPosition.CenterParent;
+                    InitializeComponents();
+                }
+
+                public string ItemText
+                {
+                    get => txtName.Text;
+                    set => txtName.Text = value;
+                }
+                public Image ItemIcon
+                {
+                    get => picIcon.Image;
+                    set => picIcon.Image = value;
+                }
+                public string ItemIconPath { get; set; }
+                public int ItemIconIndex { get; set; }
+                public bool IsDelete { get; private set; }
+
+                readonly TextBox txtName = new TextBox();
+                readonly Label lblName = new Label
+                {
+                    Text = AppString.Dialog.ItemText,
+                    AutoSize = true
+                };
+                readonly Label lblIcon = new Label
+                {
+                    Text = AppString.Menu.ItemIcon,
+                    AutoSize = true
+                };
+                readonly PictureBox picIcon = new PictureBox
+                {
+                    Size = SystemInformation.IconSize
+                };
+                readonly Button btnBrowse = new Button
+                {
+                    Text = AppString.Dialog.Browse,
+                    AutoSize = true
+                };
+                readonly Button btnOk = new Button
+                {
+                    Text = AppString.Dialog.Ok,
+                    DialogResult = DialogResult.OK,
+                    AutoSize = true
+                };
+                readonly Button btnCancel = new Button
+                {
+                    Text = AppString.Dialog.Cancel,
+                    DialogResult = DialogResult.Cancel,
+                    AutoSize = true
+                };
+                readonly Button btnDelete = new Button
+                {
+                    Text = AppString.Dialog.DeleteGuidDic,
+                    DialogResult = DialogResult.Cancel,
+                    AutoSize = true
+                };
+
+                private void InitializeComponents()
+                {
+                    this.Controls.AddRange(new Control[] { lblName, txtName, lblIcon, picIcon, btnBrowse, btnDelete, btnOk, btnCancel });
+                    int a = 20.DpiZoom();
+                    lblName.Left = lblName.Top = lblIcon.Left = btnDelete.Left = txtName.Top = a;
+                    txtName.Left = lblName.Right + a;
+                    btnOk.Left = btnDelete.Right + a;
+                    btnCancel.Left = btnOk.Right + a;
+                    txtName.Width = btnCancel.Right - txtName.Left;
+                    btnBrowse.Left = btnCancel.Right - btnBrowse.Width;
+                    picIcon.Left = btnOk.Left + (btnOk.Width - picIcon.Width) / 2;
+                    btnBrowse.Top = txtName.Bottom + a;
+                    picIcon.Top = btnBrowse.Top + (btnBrowse.Height - picIcon.Height) / 2;
+                    lblIcon.Top = btnBrowse.Top + (btnBrowse.Height - lblIcon.Height) / 2;
+                    btnDelete.Top = btnOk.Top = btnCancel.Top = btnBrowse.Bottom + a;
+                    this.ClientSize = new Size(btnCancel.Right + a, btnCancel.Bottom + a);
+                    MyToolTip.SetToolTip(btnDelete, AppString.Tip.DeleteGuidDic);
+                    btnBrowse.Click += (sender, e) => SelectIcon();
+                    btnDelete.Click += (sender, e) => this.IsDelete = true;
+                }
+
+                private void SelectIcon()
+                {
+                    using(IconDialog dlg = new IconDialog())
+                    {
+                        dlg.IconPath = this.ItemIconPath;
+                        dlg.IconIndex = this.ItemIconIndex;
+                        if(dlg.ShowDialog() != DialogResult.OK) return;
+                        ItemIconPath = dlg.IconPath;
+                        ItemIconIndex = dlg.IconIndex;
+                        picIcon.Image = ResourceIcon.GetIcon(ItemIconPath, ItemIconIndex).ToBitmap();
+                    }
+                }
+            }
+        }
     }
 }

+ 16 - 18
ContextMenuManager/Controls/Interfaces/ITsiIconItem.cs

@@ -21,28 +21,26 @@ namespace ContextMenuManager.Controls.Interfaces
         {
             this.Click += (sender, e) =>
             {
-                string iconPath = item.IconPath;
-                int iconIndex = item.IconIndex;
-                using(Icon icon = ChangeIcon(ref iconPath, ref iconIndex))
+                using(IconDialog dlg = new IconDialog())
                 {
-                    if(icon == null) return;
-                    item.IconPath = iconPath;
-                    item.IconIndex = iconIndex;
-                    item.IconLocation = $"{iconPath},{iconIndex}";
-                    item.Image = icon.ToBitmap();
+                    dlg.IconPath = item.IconPath;
+                    dlg.IconIndex = item.IconIndex;
+                    if(dlg.ShowDialog() != DialogResult.OK) return;
+                    item.IconPath = dlg.IconPath;
+                    item.IconIndex = dlg.IconIndex;
+                    item.IconLocation = $"{dlg.IconPath},{dlg.IconIndex}";
+                    using(Icon icon = ResourceIcon.GetIcon(dlg.IconPath, dlg.IconIndex))
+                    {
+                        item.Image = icon.ToBitmap();
+                    }
                 }
             };
-        }
-
-        public static Icon ChangeIcon(ref string iconPath, ref int iconIndex)
-        {
-            using(IconDialog dlg = new IconDialog { IconPath = iconPath, IconIndex = iconIndex })
+            MyListItem listItem = (MyListItem)item;
+            listItem.Disposed += (sender, e) => item.ItemIcon?.Dispose();
+            listItem.ImageDoubleClick += (sender, e) =>
             {
-                if(dlg.ShowDialog() != DialogResult.OK) return null;
-                iconPath = dlg.IconPath;
-                iconIndex = dlg.IconIndex;
-            }
-            return ResourceIcon.GetIcon(iconPath, iconIndex);
+                if(this.Enabled) this.OnClick(null);
+            };
         }
     }
 }

+ 6 - 2
ContextMenuManager/Controls/Interfaces/ITsiRegExportItem.cs

@@ -21,9 +21,13 @@ namespace ContextMenuManager.Controls.Interfaces
             {
                 using(SaveFileDialog dlg = new SaveFileDialog())
                 {
-                    string dirPath = $@"{AppConfig.BackupDir}\{DateTime.Today.ToString("yyyy-MM-dd")}";
+                    string date = DateTime.Today.ToString("yyyy-MM-dd");
+                    string time = DateTime.Now.ToString("HH.mm.ss");
+                    string filePath = $@"{AppConfig.BackupDir}\{date}\{item.Text} - {time}.reg";
+                    string dirPath = Path.GetDirectoryName(filePath);
+                    string fileName = Path.GetFileName(filePath);
                     Directory.CreateDirectory(dirPath);
-                    dlg.FileName = item.Text;
+                    dlg.FileName = fileName;
                     dlg.InitialDirectory = dirPath;
                     dlg.Filter = $"{AppString.Dialog.RegistryFile}|*.reg";
                     if(dlg.ShowDialog() == DialogResult.OK)

+ 8 - 8
ContextMenuManager/Controls/Interfaces/ITsiShortcutCommandItem.cs

@@ -8,7 +8,7 @@ namespace ContextMenuManager.Controls.Interfaces
 {
     interface ITsiShortcutCommandItem
     {
-        WshShortcut Shortcut { get; }
+        ShellLink ShellLink { get; }
         ShortcutCommandMenuItem TsiChangeCommand { get; set; }
         ContextMenuStrip ContextMenuStrip { get; set; }
     }
@@ -19,20 +19,20 @@ namespace ContextMenuManager.Controls.Interfaces
         {
             item.ContextMenuStrip.Opening += (sender, e) =>
             {
-                this.Visible = !string.IsNullOrEmpty(item.Shortcut?.TargetPath);
+                this.Visible = !string.IsNullOrEmpty(item.ShellLink?.TargetPath);
             };
         }
 
-        public bool ChangeCommand(WshShortcut shortcut)
+        public bool ChangeCommand(ShellLink shellLink)
         {
             using(CommandDialog dlg = new CommandDialog())
             {
-                dlg.Command = shortcut.TargetPath;
-                dlg.Arguments = shortcut.Arguments;
+                dlg.Command = shellLink.TargetPath;
+                dlg.Arguments = shellLink.Arguments;
                 if(dlg.ShowDialog() != DialogResult.OK) return false;
-                shortcut.TargetPath = dlg.Command;
-                shortcut.Arguments = dlg.Arguments;
-                shortcut.Save();
+                shellLink.TargetPath = dlg.Command;
+                shellLink.Arguments = dlg.Arguments;
+                shellLink.Save();
                 return true;
             }
         }

+ 8 - 1
ContextMenuManager/Controls/Interfaces/ITsiTextItem.cs

@@ -20,9 +20,16 @@ namespace ContextMenuManager.Controls.Interfaces
                 string name = ChangeText(item.Text);
                 if(name != null) item.ItemText = name;
             };
+            if(item is IFoldGroupItem == false)
+            {
+                ((MyListItem)item).TextDoubleClick += (sender, e) =>
+                {
+                    if(this.Enabled) this.OnClick(null);
+                };
+            }
         }
 
-        public static string ChangeText(string text)
+        private string ChangeText(string text)
         {
             using(InputDialog dlg = new InputDialog { Text = text, Title = AppString.Menu.ChangeText })
             {

+ 2 - 2
ContextMenuManager/Controls/NewItem.cs

@@ -1,5 +1,4 @@
 using BluePointLilac.Controls;
-using BluePointLilac.Methods;
 using System;
 
 namespace ContextMenuManager.Controls
@@ -12,10 +11,11 @@ namespace ContextMenuManager.Controls
         {
             this.Text = text;
             this.Image = AppImage.NewItem;
-            this.SetNoClickEvent();
             this.AddCtr(BtnAddNewItem);
             MyToolTip.SetToolTip(BtnAddNewItem, text);
             BtnAddNewItem.MouseDown += (sender, e) => AddNewItem?.Invoke(null, null);
+            this.ImageDoubleClick += (sender, e) => AddNewItem?.Invoke(null, null);
+            this.TextDoubleClick += (sender, e) => AddNewItem?.Invoke(null, null);
 
         }
         public event EventHandler AddNewItem;

+ 3 - 2
ContextMenuManager/Controls/NewLnkFileDialog.cs

@@ -84,7 +84,7 @@ namespace ContextMenuManager.Controls
                 {
                     if(Path.GetExtension(ItemFilePath).ToLower() == ".lnk")
                     {
-                        using(WshShortcut shortcut = new WshShortcut(ItemFilePath))
+                        using(ShellLink shortcut = new ShellLink(ItemFilePath))
                         {
                             if(File.Exists(shortcut.TargetPath))
                             {
@@ -108,11 +108,12 @@ namespace ContextMenuManager.Controls
                         string extension = Path.GetExtension(dlg.FileName).ToLower();
                         if(extension == ".lnk")
                         {
-                            using(WshShortcut shortcut = new WshShortcut(dlg.FileName))
+                            using(ShellLink shortcut = new ShellLink(dlg.FileName))
                             {
                                 if(File.Exists(shortcut.TargetPath))
                                 {
                                     ItemFilePath = shortcut.TargetPath;
+                                    Arguments = shortcut.Arguments;
                                 }
                             }
                         }

+ 1 - 1
ContextMenuManager/Controls/NewOpenWithDialog.cs

@@ -27,7 +27,7 @@ namespace ContextMenuManager.Controls
 
             private string FilePath;
             private string FileName => Path.GetFileName(FilePath);
-            private string AppRegPath => $@"HKEY_CLASSES_ROOT\Applications\{FileName}";
+            private string AppRegPath => $@"{RegistryEx.CLASSESROOT}\Applications\{FileName}";
             private string CommandPath => $@"{AppRegPath}\shell\open\command";
 
             protected override void InitializeComponents()

+ 18 - 5
ContextMenuManager/Controls/NewShellDialog.cs

@@ -107,11 +107,22 @@ namespace ContextMenuManager.Controls
             {
                 using(OpenFileDialog dlg = new OpenFileDialog())
                 {
+                    dlg.DereferenceLinks = false;
                     dlg.Filter = $"{AppString.Dialog.Program}|*.exe;*.bat;*.cmd;*.vbs;*.vbe;*.js;*.jse;*.wsf";
                     if(dlg.ShowDialog() != DialogResult.OK) return;
-                    Arguments = string.Empty;
-                    ItemText = Path.GetFileNameWithoutExtension(dlg.FileName);
-                    string extension = Path.GetExtension(dlg.FileName).ToLower();
+                    string filePath = dlg.FileName;
+                    string arguments = "";
+                    ItemText = Path.GetFileNameWithoutExtension(filePath);
+                    string extension = Path.GetExtension(filePath).ToLower();
+                    if(extension == ".lnk")
+                    {
+                        using(ShellLink shellLink = new ShellLink(filePath))
+                        {
+                            filePath = shellLink.TargetPath;
+                            arguments = shellLink.Arguments;
+                            extension = Path.GetExtension(filePath);
+                        }
+                    }
                     switch(extension)
                     {
                         case ".vbs":
@@ -121,10 +132,12 @@ namespace ContextMenuManager.Controls
                         case ".wsf":
                             chkSE.Checked = true;
                             ItemFilePath = "wscript.exe";
-                            Arguments = dlg.FileName;
+                            Arguments = filePath;
+                            if(!arguments.IsNullOrWhiteSpace()) Arguments += " " + arguments;
                             break;
                         default:
-                            ItemFilePath = dlg.FileName;
+                            Arguments = arguments;
+                            ItemFilePath = filePath;
                             break;
                     }
                     if(Array.FindIndex(DirScenePaths, path

+ 2 - 1
ContextMenuManager/Controls/OpenWithList.cs

@@ -25,7 +25,8 @@ namespace ContextMenuManager.Controls
 
         private void LoadOpenWithItems()
         {
-            using(RegistryKey appKey = Registry.ClassesRoot.OpenSubKey("Applications"))
+            using(RegistryKey root = Registry.ClassesRoot)
+            using(RegistryKey appKey = root.OpenSubKey("Applications"))
             {
                 foreach(string appName in appKey.GetSubKeyNames())
                 {

+ 22 - 4
ContextMenuManager/Controls/RuleItem.cs

@@ -269,8 +269,16 @@ namespace ContextMenuManager.Controls
             NudValue.Minimum = rule.MinValue;
             NudValue.ValueChanged += (sender, e) =>
             {
-                if(NudValue.Value == Rule.DefaultValue) NudValue.ForeColor = Color.Red;
-                else NudValue.ForeColor = Color.Black;
+                if(NudValue.Value == Rule.DefaultValue)
+                {
+                    NudValue.ForeColor = Color.FromArgb(0, 138, 217);
+                    NudValue.Font = new Font(NudValue.Font, FontStyle.Bold);
+                }
+                else
+                {
+                    NudValue.ForeColor = Color.Black;
+                    NudValue.Font = new Font(NudValue.Font, FontStyle.Regular);
+                }
                 this.ItemValue = (int)NudValue.Value;
             };
             NudValue.Value = ItemValue;
@@ -310,6 +318,7 @@ namespace ContextMenuManager.Controls
         {
             Font = new Font(SystemFonts.MenuFont.FontFamily, 12F),
             BorderStyle = BorderStyle.FixedSingle,
+            Cursor = Cursors.Hand,
             AutoSize = true
         };
 
@@ -398,8 +407,16 @@ namespace ContextMenuManager.Controls
             NudValue.Minimum = rule.MinValue;
             NudValue.ValueChanged += (sender, e) =>
             {
-                if(NudValue.Value == Rule.DefaultValue) NudValue.ForeColor = Color.Red;
-                else NudValue.ForeColor = Color.Black;
+                if(NudValue.Value == Rule.DefaultValue)
+                {
+                    NudValue.ForeColor = Color.FromArgb(0, 138, 217);
+                    NudValue.Font = new Font(NudValue.Font, FontStyle.Bold);
+                }
+                else
+                {
+                    NudValue.ForeColor = Color.Black;
+                    NudValue.Font = new Font(NudValue.Font, FontStyle.Regular);
+                }
                 this.ItemValue = (int)NudValue.Value;
             };
             NudValue.Value = ItemValue;
@@ -447,6 +464,7 @@ namespace ContextMenuManager.Controls
         {
             Font = new Font(SystemFonts.MenuFont.FontFamily, 12F),
             BorderStyle = BorderStyle.FixedSingle,
+            Cursor = Cursors.Hand,
             AutoSize = true
         };
 

+ 14 - 8
ContextMenuManager/Controls/SelectDialog.cs

@@ -9,9 +9,9 @@ namespace ContextMenuManager.Controls
     {
         public string Title { get; set; }
         public string Selected { get; set; }
-        public int SelectedIndex { get; private set; }
+        public int SelectedIndex { get; set; }
         public string[] Items { get; set; }
-        public ComboBoxStyle DropDownStyle { get; set; } = ComboBoxStyle.DropDownList;
+        public bool CanEdit { get; set; }
 
         public override void Reset() { }
 
@@ -21,8 +21,9 @@ namespace ContextMenuManager.Controls
             {
                 frm.Text = this.Title;
                 frm.Items = this.Items;
-                frm.Selected = this.Selected;
-                frm.DropDownStyle = this.DropDownStyle;
+                if(this.Selected != null) frm.Selected = this.Selected;
+                else frm.SelectedIndex = this.SelectedIndex;
+                frm.CanEdit = this.CanEdit;
                 bool flag = frm.ShowDialog() == DialogResult.OK;
                 if(flag)
                 {
@@ -68,13 +69,17 @@ namespace ContextMenuManager.Controls
                 }
             }
 
-            public ComboBoxStyle DropDownStyle
+            public bool CanEdit
             {
-                get => cmbItems.DropDownStyle;
-                set => cmbItems.DropDownStyle = value;
+                get => cmbItems.DropDownStyle == ComboBoxStyle.DropDown;
+                set => cmbItems.DropDownStyle = value ? ComboBoxStyle.DropDown : ComboBoxStyle.DropDownList;
             }
 
-            public int SelectedIndex => cmbItems.SelectedIndex;
+            public int SelectedIndex
+            {
+                get => cmbItems.SelectedIndex;
+                set => cmbItems.SelectedIndex = value;
+            }
 
             readonly Button btnOk = new Button
             {
@@ -106,6 +111,7 @@ namespace ContextMenuManager.Controls
                 btnOk.Left = cmbItems.Right + a;
                 btnCancel.Left = btnOk.Right + a;
                 this.ClientSize = new Size(btnCancel.Right + a, btnCancel.Bottom + a);
+                cmbItems.AutosizeDropDownWidth();
             }
         }
     }

+ 17 - 10
ContextMenuManager/Controls/SendToItem.cs

@@ -24,14 +24,14 @@ namespace ContextMenuManager.Controls
             set
             {
                 filePath = value;
-                if(IsShortcut) this.Shortcut = new WshShortcut(value);
+                if(IsShortcut) this.ShellLink = new ShellLink(value);
                 this.Text = this.ItemText;
                 this.Image = this.ItemIcon.ToBitmap();
                 ChkVisible.Checked = this.ItemVisible;
             }
         }
 
-        public WshShortcut Shortcut { get; private set; }
+        public ShellLink ShellLink { get; private set; }
         private string FileExtension => Path.GetExtension(FilePath);
         private bool IsShortcut => FileExtension.ToLower() == ".lnk";
         public string SearchText => $"{AppString.SideBar.SendTo} {Text}";
@@ -41,7 +41,7 @@ namespace ContextMenuManager.Controls
             get
             {
                 string path = null;
-                if(IsShortcut) path = Shortcut.TargetPath;
+                if(IsShortcut) path = ShellLink.TargetPath;
                 else
                 {
                     using(RegistryKey root = Registry.ClassesRoot)
@@ -104,7 +104,7 @@ namespace ContextMenuManager.Controls
                     if(File.Exists(path)) icon = ResourceIcon.GetExtensionIcon(path);
                     else if(Directory.Exists(path)) icon = ResourceIcon.GetFolderIcon(path);
                 }
-                else icon = ResourceIcon.GetExtensionIcon(FileExtension);
+                if(icon == null) icon = ResourceIcon.GetExtensionIcon(FileExtension);
                 return icon;
             }
         }
@@ -116,8 +116,11 @@ namespace ContextMenuManager.Controls
                 string location = null;
                 if(IsShortcut)
                 {
-                    location = Shortcut.IconLocation;
-                    if(location == ",0") location = Shortcut.TargetPath;
+                    ShellLink.ICONLOCATION iconLocation = ShellLink.IconLocation;
+                    string iconPath = iconLocation.IconPath;
+                    int iconIndex = iconLocation.IconIndex;
+                    if(string.IsNullOrEmpty(iconPath)) iconPath = ShellLink.TargetPath;
+                    location = $@"{iconPath},{iconIndex}";
                 }
                 else
                 {
@@ -140,8 +143,12 @@ namespace ContextMenuManager.Controls
             {
                 if(IsShortcut)
                 {
-                    Shortcut.IconLocation = $"{this.IconPath},{this.IconIndex}";
-                    Shortcut.Save();
+                    ShellLink.IconLocation = new ShellLink.ICONLOCATION
+                    {
+                        IconPath = this.IconPath,
+                        IconIndex = this.IconIndex
+                    };
+                    ShellLink.Save();
                 }
                 else
                 {
@@ -201,7 +208,7 @@ namespace ContextMenuManager.Controls
 
             TsiChangeCommand.Click += (sender, e) =>
             {
-                if(TsiChangeCommand.ChangeCommand(Shortcut))
+                if(TsiChangeCommand.ChangeCommand(ShellLink))
                 {
                     Image = ItemIcon.ToBitmap();
                 }
@@ -212,7 +219,7 @@ namespace ContextMenuManager.Controls
         {
             File.Delete(this.FilePath);
             DesktopIni.DeleteLocalizedFileNames(FilePath);
-            this.Shortcut.Dispose();
+            //this.Shortcut.Dispose();
             this.Dispose();
         }
     }

+ 5 - 6
ContextMenuManager/Controls/SendToList.cs

@@ -36,12 +36,12 @@ namespace ContextMenuManager.Controls
                     if(dlg.ShowDialog() != DialogResult.OK) return;
                     string lnkPath = $@"{SendToPath}\{ObjectPath.RemoveIllegalChars(dlg.ItemText)}.lnk";
                     lnkPath = ObjectPath.GetNewPathWithIndex(lnkPath, ObjectPath.PathType.File);
-                    using(WshShortcut shortcut = new WshShortcut(lnkPath))
+                    using(ShellLink shellLink = new ShellLink(lnkPath))
                     {
-                        shortcut.TargetPath = dlg.ItemFilePath;
-                        shortcut.WorkingDirectory = Path.GetDirectoryName(dlg.ItemFilePath);
-                        shortcut.Arguments = dlg.Arguments;
-                        shortcut.Save();
+                        shellLink.TargetPath = dlg.ItemFilePath;
+                        shellLink.WorkingDirectory = Path.GetDirectoryName(dlg.ItemFilePath);
+                        shellLink.Arguments = dlg.Arguments;
+                        shellLink.Save();
                     }
                     DesktopIni.SetLocalizedFileNames(lnkPath, dlg.ItemText);
                     this.InsertItem(new SendToItem(lnkPath), 2);
@@ -60,7 +60,6 @@ namespace ContextMenuManager.Controls
             MyToolTip.SetToolTip(btnPath, AppString.Menu.FileLocation);
             btnPath.MouseDown += (sender, e) => ExternalProgram.JumpExplorer(SendToPath);
             item.AddCtr(btnPath);
-            item.SetNoClickEvent();
             this.InsertItem(item, 1);
         }
     }

+ 9 - 5
ContextMenuManager/Controls/ShellItem.cs

@@ -278,6 +278,14 @@ namespace ContextMenuManager.Controls
                         {
                             Registry.SetValue(RegPath, "HideBasedOnVelocityId", 0x639bc8);
                         }
+                        else
+                        {
+                            if(IsSubItem)
+                            {
+                                MessageBoxEx.Show(AppString.MessageBox.CannotHideSubItem);
+                                return;
+                            }
+                        }
                         if(!IsSubItem)
                         {
                             //当LegaryDisable键值作用于文件夹-"在新窗口中打开"时
@@ -288,10 +296,6 @@ namespace ContextMenuManager.Controls
                             }
                             Registry.SetValue(RegPath, "ProgrammaticAccessOnly", "");
                         }
-                        else
-                        {
-                            MessageBoxEx.Show(AppString.MessageBox.CannotHideSubItem);
-                        }
                         if(ShowAsDisabledIfHidden) DeleteSomeValues();
                     }
                 }
@@ -577,7 +581,7 @@ namespace ContextMenuManager.Controls
             }
             using(ShellSubMenuDialog dlg = new ShellSubMenuDialog())
             {
-                dlg.Text = AppString.Other.EditSubItems.Replace("%s", this.Text);
+                dlg.Text = AppString.Dialog.EditSubItems.Replace("%s", this.Text);
                 dlg.Icon = ResourceIcon.GetIcon(IconPath, IconIndex);
                 dlg.ShowDialog(this.RegPath);
             }

+ 343 - 69
ContextMenuManager/Controls/ShellList.cs

@@ -4,7 +4,9 @@ using ContextMenuManager.Controls.Interfaces;
 using Microsoft.Win32;
 using System;
 using System.Collections.Generic;
+using System.Diagnostics;
 using System.Drawing;
+using System.IO;
 using System.Linq;
 using System.Windows.Forms;
 using System.Xml;
@@ -28,15 +30,18 @@ namespace ContextMenuManager.Controls
         public const string MENUPATH_UWPLNK = @"HKEY_CLASSES_ROOT\Launcher.ImmersiveApplication";//UWP快捷方式
         public const string MENUPATH_UNKNOWN = @"HKEY_CLASSES_ROOT\Unknown";//未知格式
         public const string SYSFILEASSPATH = @"HKEY_CLASSES_ROOT\SystemFileAssociations";//系统扩展名注册表父项路径
+        private const string LASTKEYPATH = @"HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Applets\Regedit";//上次打开的注册表项路径记录
 
         public enum Scenes
         {
             File, Folder, Directory, Background, Desktop, Drive, AllObjects, Computer, RecycleBin, Library,
-            LnkFile, UwpLnk, ExeFile, UnknownType, CustomExtension, PerceivedType, DirectoryType, CommandStore, DragDrop
+            LnkFile, UwpLnk, ExeFile, UnknownType, CustomExtension, PerceivedType, DirectoryType,
+            CommandStore, DragDrop, CustomRegPath, MenuAnalysis
         }
 
         private static readonly string[] DirectoryTypes = { "Document", "Image", "Video", "Audio" };
-        private static readonly string[] PerceivedTypes = { "Text", "Document", "Image", "Video", "Audio", "Compressed", "System" };
+        private static readonly string[] PerceivedTypes = { null, "Text", "Document", "Image", "Video", "Audio", "Compressed", "System" };
+        private static readonly string[] FileObjectTypes = { AppString.SideBar.File, AppString.SideBar.Directory };
         private static readonly string[] DirectoryTypeNames =
         {
             AppString.Dialog.DocumentDirectory, AppString.Dialog.ImageDirectory,
@@ -44,17 +49,17 @@ namespace ContextMenuManager.Controls
         };
         private static readonly string[] PerceivedTypeNames =
         {
-            AppString.Dialog.TextFile, AppString.Dialog.DocumentFile, AppString.Dialog.ImageFile, AppString.Dialog.VideoFile,
-            AppString.Dialog.AudioFile, AppString.Dialog.CompressedFile, AppString.Dialog.SystemFile
+            AppString.Dialog.NoPerceivedType, AppString.Dialog.TextFile, AppString.Dialog.DocumentFile, AppString.Dialog.ImageFile,
+            AppString.Dialog.VideoFile, AppString.Dialog.AudioFile, AppString.Dialog.CompressedFile, AppString.Dialog.SystemFile
         };
 
-        private static string GetDirectoryTypeName()
+        private static string GetDirectoryTypeName(string directoryType)
         {
-            if(CurrentDirectoryType != null)
+            if(directoryType != null)
             {
                 for(int i = 0; i < DirectoryTypes.Length; i++)
                 {
-                    if(CurrentDirectoryType.Equals(DirectoryTypes[i], StringComparison.OrdinalIgnoreCase))
+                    if(directoryType.Equals(DirectoryTypes[i], StringComparison.OrdinalIgnoreCase))
                     {
                         return DirectoryTypeNames[i];
                     }
@@ -63,29 +68,29 @@ namespace ContextMenuManager.Controls
             return null;
         }
 
-        private static string GetPerceivedTypeName()
+        private static string GetPerceivedTypeName(string perceivedType)
         {
-            if(CurrentPerceivedType != null)
+            int index = 0;
+            if(perceivedType != null)
             {
-                for(int i = 0; i < PerceivedTypes.Length; i++)
+                for(int i = 1; i < PerceivedTypes.Length; i++)
                 {
-                    if(CurrentPerceivedType.Equals(PerceivedTypes[i], StringComparison.OrdinalIgnoreCase))
-                    {
-                        return PerceivedTypeNames[i];
-                    }
+                    if(perceivedType.Equals(PerceivedTypes[i], StringComparison.OrdinalIgnoreCase)) index = i;
                 }
             }
-            return null;
+            return PerceivedTypeNames[index];
         }
 
         private static string CurrentExtension = null;
         private static string CurrentDirectoryType = null;
         private static string CurrentPerceivedType = null;
+        public static string CurrentCustomRegPath = null;
+        public static string CurrentFileObjectPath = null;
 
         private static string GetShellPath(string scenePath) => $@"{scenePath}\shell";
-        private static string GetShellExPath(string scenePath) => $@"{scenePath}\shellEx";
+        private static string GetShellExPath(string scenePath) => $@"{scenePath}\ShellEx";
         private static string GetSysAssExtPath(string typeName) => typeName != null ? $@"{SYSFILEASSPATH}\{typeName}" : null;
-        private static string GetOpenModePath(string extension) => extension != null ? $@"HKEY_CLASSES_ROOT\{FileExtension.GetOpenMode(extension)}" : null;
+        private static string GetOpenModePath(string extension) => extension != null ? $@"{RegistryEx.CLASSESROOT}\{FileExtension.GetOpenMode(extension)}" : null;
 
         public Scenes Scene { get; set; }
 
@@ -124,7 +129,7 @@ namespace ContextMenuManager.Controls
                     if(WindowsOsVersion.IsEqualVista) return;
                     scenePath = MENUPATH_LIBRARY; break;
                 case Scenes.LnkFile:
-                    scenePath = GetSysAssExtPath(".lnk"); break;
+                    scenePath = GetOpenModePath(".lnk"); break;
                 case Scenes.UwpLnk:
                     //Win8之前没有Uwp
                     if(WindowsOsVersion.IsBefore8) return;
@@ -134,12 +139,21 @@ namespace ContextMenuManager.Controls
                 case Scenes.UnknownType:
                     scenePath = MENUPATH_UNKNOWN; break;
                 case Scenes.CustomExtension:
-                    scenePath = GetSysAssExtPath(CurrentExtension); break;
+                    bool isLnk = CurrentExtension?.ToLower() == ".lnk";
+                    if(isLnk) scenePath = GetOpenModePath(".lnk");
+                    else scenePath = GetSysAssExtPath(CurrentExtension);
+                    break;
                 case Scenes.PerceivedType:
                     scenePath = GetSysAssExtPath(CurrentPerceivedType); break;
                 case Scenes.DirectoryType:
                     if(CurrentDirectoryType == null) scenePath = null;
                     else scenePath = GetSysAssExtPath($"Directory.{CurrentDirectoryType}"); break;
+                case Scenes.MenuAnalysis:
+                    this.AddItem(new SelectItem(Scene));
+                    this.LoadAnalysisItems();
+                    return;
+                case Scenes.CustomRegPath:
+                    scenePath = CurrentCustomRegPath; break;
                 case Scenes.CommandStore:
                     //Vista系统没有这一项
                     if(WindowsOsVersion.IsEqualVista) return;
@@ -172,17 +186,19 @@ namespace ContextMenuManager.Controls
                     this.LoadItems(MENUPATH_LIBRARY_BACKGROUND);
                     this.LoadItems(MENUPATH_LIBRARY_USER);
                     break;
-                case Scenes.LnkFile:
-                    this.LoadItems(GetOpenModePath(".lnk"));
-                    break;
                 case Scenes.ExeFile:
                     this.LoadItems(GetOpenModePath(".exe"));
                     break;
                 case Scenes.CustomExtension:
                 case Scenes.PerceivedType:
                 case Scenes.DirectoryType:
+                case Scenes.CustomRegPath:
                     this.InsertItem(new SelectItem(Scene), 0);
-                    if(Scene == Scenes.CustomExtension) this.LoadItems(GetOpenModePath(CurrentExtension));
+                    if(Scene == Scenes.CustomExtension)
+                    {
+                        this.LoadItems(GetOpenModePath(CurrentExtension));
+                        if(CurrentExtension != null) this.InsertItem(new PerceivedTypeItem(), 1);
+                    }
                     break;
             }
         }
@@ -201,10 +217,10 @@ namespace ContextMenuManager.Controls
             {
                 if(shellKey == null) return;
                 RegTrustedInstaller.TakeRegTreeOwnerShip(shellKey.Name);
-                Array.ForEach(shellKey.GetSubKeyNames(), keyName =>
+                foreach(string keyName in shellKey.GetSubKeyNames())
                 {
                     this.AddItem(new ShellItem($@"{shellPath}\{keyName}"));
-                });
+                }
             }
         }
 
@@ -280,7 +296,6 @@ namespace ContextMenuManager.Controls
                     {
                         dlg.Items = new[] { "Shell", "ShellEx" };
                         dlg.Title = AppString.Dialog.SelectNewItemType;
-                        dlg.Selected = dlg.Items[0];
                         if(dlg.ShowDialog() != DialogResult.OK) return;
                         isShell = dlg.SelectedIndex == 0;
                     }
@@ -328,7 +343,6 @@ namespace ContextMenuManager.Controls
                             dlg2.Title = AppString.Dialog.SelectGroup;
                             dlg2.Items = new[] { AppString.SideBar.Folder, AppString.SideBar.Directory,
                                         AppString.SideBar.Drive, AppString.SideBar.AllObjects };
-                            dlg2.Selected = dlg2.Items[0];
                             if(dlg2.ShowDialog() != DialogResult.OK) return;
                             switch(dlg2.SelectedIndex)
                             {
@@ -387,7 +401,6 @@ namespace ContextMenuManager.Controls
             }
         }
 
-        ///<summary>“其他规则”-“公共引用”</summary>
         private void LoadStoreItems()
         {
             using(var shellKey = RegistryEx.GetRegistryKey(ShellItem.CommandStorePath))
@@ -424,7 +437,72 @@ namespace ContextMenuManager.Controls
             }
         }
 
-        sealed class SelectItem : MyListItem
+        private void LoadAnalysisItems()
+        {
+            if(CurrentFileObjectPath == null) return;
+
+            void AddFileItems(string filePath)
+            {
+                string extension = Path.GetExtension(filePath);
+                if(extension == string.Empty) extension = ".";
+                string perceivedType = Registry.GetValue($@"{RegistryEx.CLASSESROOT}\{extension}", "PerceivedType", null)?.ToString();
+                string perceivedTypeName = GetPerceivedTypeName(perceivedType);
+                string openMode = FileExtension.GetOpenMode(extension);
+                JumpItem.Extension = extension;
+                JumpItem.PerceivedType = perceivedType;
+                this.AddItem(new JumpItem(Scenes.File));
+                this.AddItem(new JumpItem(Scenes.AllObjects));
+                this.AddItem(new JumpItem(Scenes.CustomExtension));
+                if(openMode == null) this.AddItem(new JumpItem(Scenes.UnknownType));
+                if(perceivedType != null) this.AddItem(new JumpItem(Scenes.PerceivedType));
+            }
+
+            void AddDirItems(string dirPath)
+            {
+                if(!dirPath.EndsWith(":\\"))
+                {
+                    this.AddItem(new JumpItem(Scenes.Folder));
+                    this.AddItem(new JumpItem(Scenes.Directory));
+                    this.AddItem(new JumpItem(Scenes.AllObjects));
+                    this.AddItem(new JumpItem(Scenes.DirectoryType));
+                }
+                else
+                {
+                    this.AddItem(new JumpItem(Scenes.Drive));
+                }
+            }
+
+            if(File.Exists(CurrentFileObjectPath))
+            {
+                string extension = Path.GetExtension(CurrentFileObjectPath).ToLower();
+                if(extension == ".lnk")
+                {
+                    this.AddItem(new JumpItem(Scenes.LnkFile));
+                    using(ShellLink shellLink = new ShellLink(CurrentFileObjectPath))
+                    {
+                        string targetPath = shellLink.TargetPath;
+                        if(File.Exists(targetPath))
+                        {
+                            AddFileItems(targetPath);
+                        }
+                        else if(Directory.Exists(targetPath))
+                        {
+                            AddDirItems(targetPath);
+                        }
+                    }
+                }
+                else
+                {
+                    AddFileItems(CurrentFileObjectPath);
+                }
+            }
+            else if(Directory.Exists(CurrentFileObjectPath))
+            {
+                AddDirItems(CurrentFileObjectPath);
+            }
+        }
+
+        public sealed class SelectItem : MyListItem
         {
             static string selected;
             public static string Selected
@@ -441,55 +519,60 @@ namespace ContextMenuManager.Controls
 
             readonly PictureButton BtnSelect = new PictureButton(AppImage.Select);
 
+            public Scenes Scene { get; private set; }
+
             public SelectItem(Scenes scene)
             {
-                this.SetNoClickEvent();
-                this.Image = AppImage.Custom;
-                this.Text = this.GetText(scene);
+                this.Scene = scene;
                 this.AddCtr(BtnSelect);
-                BtnSelect.MouseDown += (sender, e) => Select(scene);
+                this.SetTextAndTip();
+                this.Image = AppImage.Custom;
+                BtnSelect.MouseDown += (sender, e) => ShowSelectDialog();
+                this.ImageDoubleClick += (sender, e) => ShowSelectDialog();
+                this.TextDoubleClick += (sender, e) => ShowSelectDialog();
             }
 
-            private string GetText(Scenes scene)
+            private void SetTextAndTip()
             {
-                switch(scene)
+                string tip = "";
+                string text = "";
+                switch(Scene)
                 {
                     case Scenes.CustomExtension:
-                        if(CurrentExtension == null)
-                        {
-                            return AppString.Dialog.SelectExtension;
-                        }
-                        else
-                        {
-                            return AppString.Other.CurrentExtension.Replace("%s", CurrentExtension);
-                        }
+                        tip = AppString.Dialog.SelectExtension;
+                        if(CurrentExtension == null) text = tip;
+                        else text = AppString.Other.CurrentExtension.Replace("%s", CurrentExtension);
+                        break;
                     case Scenes.PerceivedType:
-                        if(CurrentPerceivedType == null)
-                        {
-                            return AppString.Dialog.SelectPerceivedType;
-                        }
-                        else
-                        {
-                            return AppString.Other.CurrentPerceivedType.Replace("%s", GetPerceivedTypeName());
-                        }
+                        tip = AppString.Dialog.SelectPerceivedType;
+                        if(CurrentPerceivedType == null) text = tip;
+                        else text = AppString.Other.CurrentPerceivedType.Replace("%s", GetPerceivedTypeName(CurrentPerceivedType));
+                        break;
                     case Scenes.DirectoryType:
-                        if(CurrentDirectoryType == null)
-                        {
-                            return AppString.Dialog.SelectDirectoryType;
-                        }
-                        else
-                        {
-                            return AppString.Other.CurrentDirectoryType.Replace("%s", GetDirectoryTypeName());
-                        }
-                    default:
-                        return null;
+                        tip = AppString.Dialog.SelectDirectoryType;
+                        if(CurrentDirectoryType == null) text = tip;
+                        else text = AppString.Other.CurrentDirectoryType.Replace("%s", GetDirectoryTypeName(CurrentDirectoryType));
+                        break;
+                    case Scenes.CustomRegPath:
+                        tip = AppString.Other.SelectRegPath;
+                        if(CurrentCustomRegPath == null) text = tip;
+                        else text = AppString.Other.CurrentRegPath + "\n" + CurrentCustomRegPath;
+                        break;
+                    case Scenes.MenuAnalysis:
+                        tip = AppString.Tip.DropOrSelectObject;
+                        if(CurrentFileObjectPath == null) text = tip;
+                        else text = AppString.Other.CurrentFilePath + "\n" + CurrentFileObjectPath;
+                        break;
+
                 }
+                MyToolTip.SetToolTip(BtnSelect, tip);
+                this.Text = text;
             }
 
-            private void Select(Scenes scene)
+            private void ShowSelectDialog()
             {
-                SelectDialog dlg;
-                switch(scene)
+                SelectDialog dlg = null;
+                switch(Scene)
                 {
                     case Scenes.CustomExtension:
                         dlg = new FileExtensionDialog
@@ -502,7 +585,7 @@ namespace ContextMenuManager.Controls
                         {
                             Items = PerceivedTypeNames,
                             Title = AppString.Dialog.SelectPerceivedType,
-                            Selected = GetPerceivedTypeName() ?? PerceivedTypeNames[0]
+                            Selected = GetPerceivedTypeName(CurrentPerceivedType)
                         };
                         break;
                     case Scenes.DirectoryType:
@@ -510,13 +593,44 @@ namespace ContextMenuManager.Controls
                         {
                             Items = DirectoryTypeNames,
                             Title = AppString.Dialog.SelectDirectoryType,
-                            Selected = GetDirectoryTypeName() ?? DirectoryTypeNames[0]
+                            Selected = GetDirectoryTypeName(CurrentDirectoryType)
+                        };
+                        break;
+                    case Scenes.MenuAnalysis:
+                        dlg = new SelectDialog
+                        {
+                            Items = FileObjectTypes,
+                            Title = AppString.Dialog.SelectObjectType,
                         };
                         break;
-                    default: return;
+                    case Scenes.CustomRegPath:
+                        if(MessageBoxEx.Show(AppString.MessageBox.SelectRegPath,
+                            MessageBoxButtons.YesNo, MessageBoxIcon.Question) != DialogResult.Yes) return;
+                        Form frm = this.FindForm();
+                        frm.Opacity = 0;
+                        using(Process process = Process.Start("regedit.exe", "-m"))
+                        {
+                            process.WaitForExit();
+                        }
+                        string path = Registry.GetValue(LASTKEYPATH, "LastKey", "").ToString();
+                        int index = path.IndexOf('\\');
+                        if(index == -1) return;
+                        path = path.Substring(index + 1);
+                        Selected = CurrentCustomRegPath = path;
+                        frm.Activate();
+                        frm.Opacity = 1;
+                        break;
                 }
-                if(dlg.ShowDialog() != DialogResult.OK) return;
-                switch(scene)
+                switch(Scene)
+                {
+                    case Scenes.CustomExtension:
+                    case Scenes.PerceivedType:
+                    case Scenes.DirectoryType:
+                    case Scenes.MenuAnalysis:
+                        if(dlg.ShowDialog() != DialogResult.OK) return;
+                        break;
+                }
+                switch(Scene)
                 {
                     case Scenes.CustomExtension:
                         Selected = CurrentExtension = dlg.Selected;
@@ -527,6 +641,166 @@ namespace ContextMenuManager.Controls
                     case Scenes.DirectoryType:
                         Selected = CurrentDirectoryType = DirectoryTypes[dlg.SelectedIndex];
                         break;
+                    case Scenes.MenuAnalysis:
+                        if(dlg.SelectedIndex == 0)
+                        {
+                            using(var dialog = new System.Windows.Forms.OpenFileDialog())
+                            {
+                                dialog.DereferenceLinks = false;
+                                if(dialog.ShowDialog() != DialogResult.OK) return;
+                                Selected = CurrentFileObjectPath = dialog.FileName;
+                            }
+                        }
+                        else
+                        {
+                            using(var dialog = new FolderBrowserDialog())
+                            {
+                                if(dialog.ShowDialog() != DialogResult.OK) return;
+                                Selected = CurrentFileObjectPath = dialog.SelectedPath;
+                            }
+                        }
+                        break;
+                }
+            }
+        }
+
+        sealed class JumpItem : MyListItem
+        {
+            public JumpItem(Scenes scene)
+            {
+                this.AddCtr(btnJump);
+                string text = "";
+                Image image = null;
+                int index1 = 0;
+                int index2 = 0;
+                switch(scene)
+                {
+                    case Scenes.File:
+                        text = $"[ {AppString.ToolBar.Home} ]  ▶  [ {AppString.SideBar.File} ]";
+                        image = AppImage.File;
+                        break;
+                    case Scenes.Folder:
+                        text = $"[ {AppString.ToolBar.Home} ]  ▶  [ {AppString.SideBar.Folder} ]";
+                        image = AppImage.Folder;
+                        index2 = 1;
+                        break;
+                    case Scenes.Directory:
+                        text = $"[ {AppString.ToolBar.Home} ]  ▶  [ {AppString.SideBar.Directory} ]";
+                        image = AppImage.Directory;
+                        index2 = 2;
+                        break;
+                    case Scenes.Drive:
+                        text = $"[ {AppString.ToolBar.Home} ]  ▶  [ {AppString.SideBar.Drive} ]";
+                        image = AppImage.Drive;
+                        index2 = 5;
+                        break;
+                    case Scenes.AllObjects:
+                        text = $"[ {AppString.ToolBar.Home} ]  ▶  [ {AppString.SideBar.AllObjects} ]";
+                        image = AppImage.AllObjects;
+                        index2 = 6;
+                        break;
+                    case Scenes.LnkFile:
+                        text = $"[ {AppString.ToolBar.Type} ]  ▶  [ {AppString.SideBar.LnkFile} ]";
+                        image = AppImage.LnkFile;
+                        index1 = 1;
+                        break;
+                    case Scenes.UnknownType:
+                        text = $"[ {AppString.ToolBar.Type} ]  ▶  [ {AppString.SideBar.UnknownType} ]";
+                        image = AppImage.NotFound;
+                        index1 = 1;
+                        index2 = 8;
+                        break;
+                    case Scenes.CustomExtension:
+                        text = $"[ {AppString.ToolBar.Type} ]  ▶  [ {AppString.SideBar.CustomExtension} ]  ▶  [ {Extension} ]";
+                        using(Icon icon = ResourceIcon.GetExtensionIcon(Extension))
+                        {
+                            image = icon.ToBitmap();
+                        }
+                        index1 = 1;
+                        index2 = 4;
+                        break;
+                    case Scenes.PerceivedType:
+                        text = $"[ {AppString.ToolBar.Type} ]  ▶  [ {AppString.SideBar.PerceivedType} ]  ▶  [ {GetPerceivedTypeName(PerceivedType)} ]";
+                        image = AppImage.File;
+                        index1 = 1;
+                        index2 = 5;
+                        break;
+                    case Scenes.DirectoryType:
+                        text = $"[ {AppString.ToolBar.Type} ]  ▶  [ {AppString.SideBar.DirectoryType} ]";
+                        image = AppImage.Directory;
+                        index1 = 1;
+                        index2 = 6;
+                        break;
+                }
+                this.Text = text;
+                this.Image = image;
+                void SwitchTab()
+                {
+                    switch(scene)
+                    {
+                        case Scenes.CustomExtension:
+                            CurrentExtension = Extension; break;
+                        case Scenes.PerceivedType:
+                            CurrentPerceivedType = PerceivedType; break;
+                    }
+                    ((MainForm)this.FindForm()).SwitchTab(index1, index2);
+                };
+                btnJump.MouseDown += (sender, e) => SwitchTab();
+                this.ImageDoubleClick += (sender, e) => SwitchTab();
+                this.TextDoubleClick += (sender, e) => SwitchTab();
+            }
+
+            readonly PictureButton btnJump = new PictureButton(AppImage.Jump);
+
+            public static string Extension = null;
+            public static string PerceivedType = null;
+        }
+
+        sealed class PerceivedTypeItem : MyListItem, ITsiRegPathItem
+        {
+            public PerceivedTypeItem()
+            {
+                this.AddCtr(btnSelect);
+                this.ContextMenuStrip = new ContextMenuStrip();
+                TsiRegLocation = new RegLocationMenuItem(this);
+                this.ContextMenuStrip.Items.Add(TsiRegLocation);
+                this.Text = $@"{Tip} {GetPerceivedTypeName(PerceivedType)}";
+                using(Icon icon = ResourceIcon.GetExtensionIcon(CurrentExtension))
+                {
+                    this.Image = icon.ToBitmap();
+                }
+                MyToolTip.SetToolTip(btnSelect, Tip);
+                btnSelect.MouseDown += (sender, e) => ShowSelectDialog();
+                this.TextDoubleClick += (sender, e) => ShowSelectDialog();
+                this.ImageDoubleClick += (sender, e) => ShowSelectDialog();
+            }
+
+            public string ValueName => "PerceivedType";
+            public string RegPath => $@"{RegistryEx.CLASSESROOT}\{CurrentExtension}";
+            private string Tip => AppString.Other.SetPerceivedType.Replace("%s", CurrentExtension);
+            public string PerceivedType
+            {
+                get => Registry.GetValue(RegPath, ValueName, null)?.ToString();
+                set
+                {
+                    if(value == null) RegistryEx.DeleteValue(RegPath, ValueName);
+                    else Registry.SetValue(RegPath, ValueName, value, RegistryValueKind.String);
+                }
+            }
+
+            readonly PictureButton btnSelect = new PictureButton(AppImage.Select);
+            public RegLocationMenuItem TsiRegLocation { get; set; }
+
+            private void ShowSelectDialog()
+            {
+                using(SelectDialog dlg = new SelectDialog())
+                {
+                    dlg.Items = PerceivedTypeNames;
+                    dlg.Title = AppString.Dialog.SelectPerceivedType;
+                    dlg.Selected = GetPerceivedTypeName(PerceivedType);
+                    if(dlg.ShowDialog() != DialogResult.OK) return;
+                    this.Text = $@"{Tip} {dlg.Selected}";
+                    PerceivedType = PerceivedTypes[dlg.SelectedIndex];
                 }
             }
         }

+ 11 - 17
ContextMenuManager/Controls/ShellNewItem.cs

@@ -4,6 +4,7 @@ using ContextMenuManager.Controls.Interfaces;
 using Microsoft.Win32;
 using System;
 using System.Drawing;
+using System.IO;
 using System.Linq;
 using System.Windows.Forms;
 
@@ -30,7 +31,7 @@ namespace ContextMenuManager.Controls
             this.Owner = list;
             InitializeComponents();
             this.RegPath = regPath;
-            SetSortabled(ShellNewLockItem.IsLocked);
+            SetSortabled(ShellNewList.ShellNewLockItem.IsLocked);
         }
 
         private string regPath;
@@ -51,12 +52,10 @@ namespace ContextMenuManager.Controls
         public string Extension => RegPath.Split('\\')[1];
         private string SnKeyName => RegistryEx.GetKeyName(RegPath);
         private string BackupPath => $@"{RegistryEx.GetParentPath(RegPath)}\{(ItemVisible ? SnParts[1] : SnParts[0])}";
-
-        private const string HKCR = "HKEY_CLASSES_ROOT";
         private string OpenMode => FileExtension.GetOpenMode(Extension);//关联打开方式
-        private string OpenModePath => $@"{HKCR}\{OpenMode}";//关联打开方式注册表路径
-        private string DefaultOpenMode => Registry.GetValue($@"{HKCR}\{Extension}", "", null)?.ToString();//默认关联打开方式
-        private string DefaultOpenModePath => $@"{HKCR}\{DefaultOpenMode}";//默认关联打开方式注册表路径
+        private string OpenModePath => $@"{RegistryEx.CLASSESROOT}\{OpenMode}";//关联打开方式注册表路径
+        private string DefaultOpenMode => Registry.GetValue($@"{RegistryEx.CLASSESROOT}\{Extension}", "", null)?.ToString();//默认关联打开方式
+        private string DefaultOpenModePath => $@"{RegistryEx.CLASSESROOT}\{DefaultOpenMode}";//默认关联打开方式注册表路径
         private string ConfigPath => $@"{RegPath}\Config";
 
         public bool CanSort => !UnableSortExtensions.Contains(Extension, StringComparer.OrdinalIgnoreCase);//能够排序的
@@ -68,15 +67,11 @@ namespace ContextMenuManager.Controls
         {
             get
             {
-                string filePath = null;
-                using(RegistryKey key = RegistryEx.GetRegistryKey(OpenModePath))
+                string filePath = FileExtension.GetExecutablePath(Extension);
+                if(File.Exists(filePath)) return filePath;
+                using(RegistryKey key = RegistryEx.GetRegistryKey($@"{OpenModePath}\CLSID"))
                 {
-                    if(key == null) return filePath;
-                    string value = key.OpenSubKey(@"shell\open\command")?.GetValue("")?.ToString();
-                    filePath = ObjectPath.ExtractFilePath(value);
-                    if(filePath != null) return filePath;
-
-                    value = key.OpenSubKey("CLSID")?.GetValue("")?.ToString();
+                    string value = key?.GetValue("")?.ToString();
                     if(GuidEx.TryParse(value, out Guid guid))
                     {
                         filePath = GuidInfo.GetFilePath(guid);
@@ -107,7 +102,6 @@ namespace ContextMenuManager.Controls
                 name = Registry.GetValue(DefaultOpenModePath, "FriendlyTypeName", null)?.ToString();
                 name = ResourceString.GetDirectString(name);
                 if(!string.IsNullOrEmpty(name)) return name;
-
                 name = Registry.GetValue(DefaultOpenModePath, "", null)?.ToString();
                 if(!string.IsNullOrEmpty(name)) return name;
                 return null;
@@ -287,7 +281,7 @@ namespace ContextMenuManager.Controls
             ShellNewList list = (ShellNewList)this.Parent;
             int index = list.GetItemIndex(list.Separator);
             list.SetItemIndex(this, index);
-            if(ShellNewLockItem.IsLocked) list.SaveSorting();
+            if(ShellNewList.ShellNewLockItem.IsLocked) list.SaveSorting();
         }
 
         public void DeleteMe()
@@ -295,7 +289,7 @@ namespace ContextMenuManager.Controls
             RegistryEx.DeleteKeyTree(this.RegPath);
             RegistryEx.DeleteKeyTree(this.BackupPath);
             this.Dispose();
-            if(ShellNewLockItem.IsLocked) Owner.SaveSorting();
+            if(ShellNewList.ShellNewLockItem.IsLocked) Owner.SaveSorting();
         }
     }
 }

+ 71 - 65
ContextMenuManager/Controls/ShellNewList.cs

@@ -140,10 +140,12 @@ namespace ContextMenuManager.Controls
                 {
                     if(dlg.ShowDialog() != DialogResult.OK) return;
                     string extension = dlg.Extension;
+                    if(extension == ".") return;
                     string openMode = FileExtension.GetOpenMode(extension);
                     if(string.IsNullOrEmpty(openMode))
                     {
                         MessageBoxEx.Show(AppString.MessageBox.NoOpenModeExtension);
+                        ExternalProgram.ShowOpenWithDialog(extension);
                         return;
                     }
                     foreach(Control ctr in this.Controls)
@@ -158,7 +160,8 @@ namespace ContextMenuManager.Controls
                         }
                     }
 
-                    using(RegistryKey exKey = Registry.ClassesRoot.OpenSubKey(extension, true))
+                    using(RegistryKey root = Registry.ClassesRoot)
+                    using(RegistryKey exKey = root.OpenSubKey(extension, true))
                     using(RegistryKey snKey = exKey.CreateSubKey("ShellNew", true))
                     {
                         string defaultOpenMode = exKey.GetValue("")?.ToString();
@@ -173,111 +176,114 @@ namespace ContextMenuManager.Controls
                         item.Focus();
                         if(item.ItemText.IsNullOrWhiteSpace())
                         {
-                            item.ItemText = $"{extension.Substring(1)} file";
+                            item.ItemText = FileExtension.GetFriendlyDocName(extension);
                         }
                         if(ShellNewLockItem.IsLocked) this.SaveSorting();
                     }
                 }
             };
         }
-    }
 
-    sealed class ShellNewLockItem : MyListItem, IChkVisibleItem, IBtnShowMenuItem, ITsiWebSearchItem
-    {
-        public ShellNewLockItem(ShellNewList list)
+        public sealed class ShellNewLockItem : MyListItem, IChkVisibleItem, IBtnShowMenuItem, ITsiWebSearchItem, ITsiRegPathItem
         {
-            this.Owner = list;
-            this.Image = AppImage.Lock;
-            this.Text = AppString.Other.LockNewMenu;
-            this.SetNoClickEvent();
-            BtnShowMenu = new MenuButton(this);
-            ChkVisible = new VisibleCheckBox(this) { Checked = IsLocked };
-            MyToolTip.SetToolTip(ChkVisible, AppString.Tip.LockNewMenu);
-            TsiSearch = new WebSearchMenuItem(this);
-            this.ContextMenuStrip = new ContextMenuStrip();
-            this.ContextMenuStrip.Items.Add(TsiSearch);
-        }
+            public ShellNewLockItem(ShellNewList list)
+            {
+                this.Owner = list;
+                this.Image = AppImage.Lock;
+                this.Text = AppString.Other.LockNewMenu;
+                BtnShowMenu = new MenuButton(this);
+                ChkVisible = new VisibleCheckBox(this) { Checked = IsLocked };
+                MyToolTip.SetToolTip(ChkVisible, AppString.Tip.LockNewMenu);
+                TsiSearch = new WebSearchMenuItem(this);
+                TsiRegLocation = new RegLocationMenuItem(this);
+                this.ContextMenuStrip.Items.AddRange(new ToolStripItem[]
+                    { TsiSearch, new ToolStripSeparator(), TsiRegLocation });
+            }
 
-        public MenuButton BtnShowMenu { get; set; }
-        public WebSearchMenuItem TsiSearch { get; set; }
-        public VisibleCheckBox ChkVisible { get; set; }
-        public ShellNewList Owner { get; private set; }
+            public MenuButton BtnShowMenu { get; set; }
+            public WebSearchMenuItem TsiSearch { get; set; }
+            public RegLocationMenuItem TsiRegLocation { get; set; }
+            public VisibleCheckBox ChkVisible { get; set; }
+            public ShellNewList Owner { get; private set; }
 
-        public bool ItemVisible
-        {
-            get => IsLocked;
-            set
+            public bool ItemVisible
             {
-                if(value) Owner.SaveSorting();
-                else UnLock();
-                foreach(Control ctr in Owner.Controls)
+                get => IsLocked;
+                set
                 {
-                    if(ctr is ShellNewItem item)
+                    if(value) Owner.SaveSorting();
+                    else UnLock();
+                    foreach(Control ctr in Owner.Controls)
                     {
-                        item.SetSortabled(value);
+                        if(ctr is ShellNewItem item)
+                        {
+                            item.SetSortabled(value);
+                        }
                     }
                 }
             }
-        }
 
-        public string SearchText => Text;
+            public string SearchText => Text;
+            public string RegPath => ShellNewPath;
+            public string ValueName => "Classes";
 
-        public static bool IsLocked
-        {
-            get
+            public static bool IsLocked
             {
-                using(RegistryKey key = RegistryEx.GetRegistryKey(ShellNewList.ShellNewPath))
+                get
                 {
-                    RegistrySecurity rs = key.GetAccessControl();
-                    foreach(RegistryAccessRule rar in rs.GetAccessRules(true, true, typeof(NTAccount)))
+                    using(RegistryKey key = RegistryEx.GetRegistryKey(ShellNewPath))
                     {
-                        if(rar.AccessControlType.ToString().Equals("Deny", StringComparison.OrdinalIgnoreCase))
+                        RegistrySecurity rs = key.GetAccessControl();
+                        foreach(RegistryAccessRule rar in rs.GetAccessRules(true, true, typeof(NTAccount)))
                         {
-                            if(rar.IdentityReference.ToString().Equals("Everyone", StringComparison.OrdinalIgnoreCase)) return true;
+                            if(rar.AccessControlType.ToString().Equals("Deny", StringComparison.OrdinalIgnoreCase))
+                            {
+                                if(rar.IdentityReference.ToString().Equals("Everyone", StringComparison.OrdinalIgnoreCase)) return true;
+                            }
                         }
                     }
+                    return false;
                 }
-                return false;
             }
-        }
 
-        public static void Lock()
-        {
-            using(RegistryKey key = RegistryEx.GetRegistryKey(ShellNewList.ShellNewPath, RegistryKeyPermissionCheck.ReadWriteSubTree, RegistryRights.ChangePermissions))
+            public static void Lock()
             {
-                RegistrySecurity rs = new RegistrySecurity();
-                RegistryAccessRule rar = new RegistryAccessRule("Everyone", RegistryRights.Delete | RegistryRights.WriteKey, AccessControlType.Deny);
-                rs.AddAccessRule(rar);
-                key.SetAccessControl(rs);
+                using(RegistryKey key = RegistryEx.GetRegistryKey(ShellNewPath, RegistryKeyPermissionCheck.ReadWriteSubTree, RegistryRights.ChangePermissions))
+                {
+                    RegistrySecurity rs = new RegistrySecurity();
+                    RegistryAccessRule rar = new RegistryAccessRule("Everyone", RegistryRights.Delete | RegistryRights.WriteKey, AccessControlType.Deny);
+                    rs.AddAccessRule(rar);
+                    key.SetAccessControl(rs);
+                }
             }
-        }
 
-        public static void UnLock()
-        {
-            using(RegistryKey key = RegistryEx.GetRegistryKey(ShellNewList.ShellNewPath, RegistryKeyPermissionCheck.ReadWriteSubTree, RegistryRights.ChangePermissions))
+            public static void UnLock()
             {
-                RegistrySecurity rs = key.GetAccessControl();
-                foreach(RegistryAccessRule rar in rs.GetAccessRules(true, true, typeof(NTAccount)))
+                using(RegistryKey key = RegistryEx.GetRegistryKey(ShellNewPath, RegistryKeyPermissionCheck.ReadWriteSubTree, RegistryRights.ChangePermissions))
                 {
-                    if(rar.AccessControlType.ToString().Equals("Deny", StringComparison.OrdinalIgnoreCase))
+                    RegistrySecurity rs = key.GetAccessControl();
+                    foreach(RegistryAccessRule rar in rs.GetAccessRules(true, true, typeof(NTAccount)))
                     {
-                        if(rar.IdentityReference.ToString().Equals("Everyone", StringComparison.OrdinalIgnoreCase))
+                        if(rar.AccessControlType.ToString().Equals("Deny", StringComparison.OrdinalIgnoreCase))
                         {
-                            rs.RemoveAccessRule(rar);
+                            if(rar.IdentityReference.ToString().Equals("Everyone", StringComparison.OrdinalIgnoreCase))
+                            {
+                                rs.RemoveAccessRule(rar);
+                            }
                         }
                     }
+                    key.SetAccessControl(rs);
                 }
-                key.SetAccessControl(rs);
             }
         }
-    }
 
-    sealed class ShellNewSeparator : MyListItem
-    {
-        public ShellNewSeparator()
+        public sealed class ShellNewSeparator : MyListItem
         {
-            this.Text = AppString.Other.Separator;
-            this.HasImage = false;
+            public ShellNewSeparator()
+            {
+                this.Text = AppString.Other.Separator;
+                this.HasImage = false;
+            }
         }
     }
 }

+ 1 - 2
ContextMenuManager/Controls/ShellStoreDialog.cs

@@ -26,7 +26,7 @@ namespace ContextMenuManager.Controls
             }
         }
 
-        sealed class ShellStoreForm : Form
+        public sealed class ShellStoreForm : Form
         {
             public string ShellPath { get; private set; }
             public List<string> IgnoredKeyNames { get; private set; }
@@ -122,7 +122,6 @@ namespace ContextMenuManager.Controls
             {
                 this.AddCtr(chkSelected, 40.DpiZoom());
                 this.ContextMenuStrip = null;
-                this.SetNoClickEvent();
                 ChkVisible.Visible = BtnShowMenu.Visible = BtnSubItems.Visible = false;
             }
             RegTrustedInstaller.TakeRegTreeOwnerShip(regPath);

+ 2 - 3
ContextMenuManager/Controls/ShellSubMenuDialog.cs

@@ -39,6 +39,7 @@ namespace ContextMenuManager.Controls
                 this.ShowInTaskbar = this.MaximizeBox = this.MinimizeBox = false;
                 this.MinimumSize = this.Size = new Size(646, 369).DpiZoom();
                 this.Controls.AddRange(new Control[] { MlbSubItems, StatusBar });
+                StatusBar.CanMoveForm();
                 this.OnResize(null);
             }
 
@@ -335,7 +336,6 @@ namespace ContextMenuManager.Controls
                         BtnMoveDown.MouseDown += (sender, e) => Owner.MoveItem(this, false);
                         MyToolTip.SetToolTip(this, AppString.Tip.InvalidItem);
                         MyToolTip.SetToolTip(BtnDelete, AppString.Menu.Delete);
-                        this.SetNoClickEvent();
                     }
 
                     public DeleteButton BtnDelete { get; set; }
@@ -380,7 +380,7 @@ namespace ContextMenuManager.Controls
                     string sckValue = GetValue(parentPath, "ExtendedSubCommandsKey", null)?.ToString();
                     if(!sckValue.IsNullOrWhiteSpace())
                     {
-                        this.ShellPath = $@"HKEY_CLASSES_ROOT\{sckValue}\shell";
+                        this.ShellPath = $@"{RegistryEx.CLASSESROOT}\{sckValue}";
                     }
                     else
                     {
@@ -564,7 +564,6 @@ namespace ContextMenuManager.Controls
                     BtnMoveDown = new MoveButton(this, false);
                     BtnMoveUp = new MoveButton(this, true);
                     MyToolTip.SetToolTip(BtnDelete, AppString.Menu.Delete);
-                    this.SetNoClickEvent();
                 }
 
                 public DeleteButton BtnDelete { get; set; }

+ 0 - 1
ContextMenuManager/Controls/ThirdRulesList.cs

@@ -156,7 +156,6 @@ namespace ContextMenuManager.Controls
                             }
                         }
                         this.AddItem(ruleItem);
-                        ruleItem.HasImage = false;
                         ruleItem.FoldGroupItem = groupItem;
                     }
                     groupItem.IsFold = true;

+ 2 - 0
ContextMenuManager/Controls/TranslateDialog.cs

@@ -131,6 +131,8 @@ namespace ContextMenuManager.Controls
                 txtNew.SetAutoShowScroll(ScrollBars.Vertical);
                 txtDefault.CanSelectAllWhenReadOnly();
                 txtOld.CanSelectAllWhenReadOnly();
+                cmbSections.AutosizeDropDownWidth();
+                cmbKeys.AutosizeDropDownWidth();
 
                 int a = 20.DpiZoom();
 

+ 14 - 15
ContextMenuManager/Controls/WinXItem.cs

@@ -24,7 +24,7 @@ namespace ContextMenuManager.Controls
             set
             {
                 filePath = value;
-                this.Shortcut = new WshShortcut(value);
+                this.ShellLink = new ShellLink(value);
                 this.Text = this.ItemText;
                 this.Image = this.ItemIcon.ToBitmap();
                 ChkVisible.Checked = this.ItemVisible;
@@ -35,15 +35,15 @@ namespace ContextMenuManager.Controls
         {
             get
             {
-                string name = Shortcut.Description?.Trim();
+                string name = ShellLink.Description?.Trim();
                 if(name.IsNullOrWhiteSpace()) name = DesktopIni.GetLocalizedFileNames(FilePath, true);
                 if(name == string.Empty) name = Path.GetFileNameWithoutExtension(FilePath);
                 return name;
             }
             set
             {
-                Shortcut.Description = value;
-                Shortcut.Save();
+                ShellLink.Description = value;
+                ShellLink.Save();
                 this.Text = ResourceString.GetDirectString(value);
                 ExplorerRestarter.Show();
             }
@@ -66,7 +66,11 @@ namespace ContextMenuManager.Controls
         {
             get
             {
-                Icon icon = ResourceIcon.GetIcon(Shortcut.IconLocation);
+                ShellLink.ICONLOCATION iconLocation = ShellLink.IconLocation;
+                string iconPath = iconLocation.IconPath;
+                int iconIndex = iconLocation.IconIndex;
+                if(string.IsNullOrEmpty(iconPath)) iconPath = FilePath;
+                Icon icon = ResourceIcon.GetIcon(iconPath, iconIndex);
                 if(icon == null)
                 {
                     string path = ItemFilePath;
@@ -81,13 +85,13 @@ namespace ContextMenuManager.Controls
         {
             get
             {
-                string path = Shortcut.TargetPath;
+                string path = ShellLink.TargetPath;
                 if(!File.Exists(path) && !Directory.Exists(path)) path = FilePath;
                 return path;
             }
         }
 
-        public WshShortcut Shortcut { get; private set; }
+        public ShellLink ShellLink { get; private set; }
         public string SearchText => $"{AppString.SideBar.WinX} {Text}";
         private string FileName => Path.GetFileName(FilePath);
 
@@ -132,17 +136,12 @@ namespace ContextMenuManager.Controls
             TsiChangeGroup.Click += (sender, e) => ChangeGroup();
             BtnMoveDown.MouseDown += (sender, e) => MoveItem(false);
             BtnMoveUp.MouseDown += (sender, e) => MoveItem(true);
-            TsiAdministrator.Click += (sender, e) =>
-            {
-                WinXList.HashLnk(this.FilePath);
-                ExplorerRestarter.Show();
-            };
             TsiChangeCommand.Click += (sender, e) =>
             {
-                if(TsiChangeCommand.ChangeCommand(Shortcut))
+                if(TsiChangeCommand.ChangeCommand(ShellLink))
                 {
                     Image = ItemIcon.ToBitmap();
-                    WinXList.HashLnk(this.FilePath);
+                    WinXHasher.HashLnk(FilePath);
                 }
             };
         }
@@ -221,7 +220,7 @@ namespace ContextMenuManager.Controls
             File.Delete(FilePath);
             DesktopIni.DeleteLocalizedFileNames(FilePath);
             ExplorerRestarter.Show();
-            this.Shortcut.Dispose();
+            this.ShellLink.Dispose();
             this.Dispose();
         }
     }

+ 7 - 42
ContextMenuManager/Controls/WinXList.cs

@@ -2,7 +2,6 @@
 using BluePointLilac.Methods;
 using System;
 using System.Collections.Generic;
-using System.Diagnostics;
 using System.IO;
 using System.Text;
 using System.Windows.Forms;
@@ -76,7 +75,6 @@ namespace ContextMenuManager.Controls
                     {
                         dlg2.Title = AppString.Dialog.SelectGroup;
                         dlg2.Items = GetGroupNames();
-                        dlg2.Selected = dlg2.Items[0];
                         if(dlg2.ShowDialog() != DialogResult.OK) return;
                         string dirPath = $@"{WinXPath}\{dlg2.Selected}";
                         string extension = Path.GetExtension(dlg1.ItemFilePath).ToLower();
@@ -85,26 +83,24 @@ namespace ContextMenuManager.Controls
                         string index = (count + 1).ToString().PadLeft(2, '0');
                         string lnkName = $"{index} - {fileName}.lnk";
                         string lnkPath = $@"{dirPath}\{lnkName}";
-                        WshShortcut shortcut;
+                        ShellLink shellLink;
                         if(extension == ".lnk")
                         {
                             File.Copy(dlg1.ItemFilePath, lnkPath);
-                            shortcut = new WshShortcut(lnkPath);
+                            shellLink = new ShellLink(lnkPath);
                         }
                         else
                         {
-                            shortcut = new WshShortcut(lnkPath)
+                            shellLink = new ShellLink(lnkPath)
                             {
                                 TargetPath = dlg1.ItemFilePath,
                                 Arguments = dlg1.Arguments,
-                                WorkingDirectory = Path.GetDirectoryName(dlg1.ItemFilePath)
                             };
+                            shellLink.WorkingDirectory = Path.GetDirectoryName(shellLink.TargetPath);
                         }
-                        shortcut.Description = dlg1.ItemText;
-                        shortcut.Save();
-                        shortcut.Dispose();
+                        shellLink.Description = dlg1.ItemText;
+                        shellLink.Save();
                         DesktopIni.SetLocalizedFileNames(lnkPath, dlg1.ItemText);
-                        HashLnk(lnkPath);
                         foreach(MyListItem ctr in this.Controls)
                         {
                             if(ctr is WinXGroupItem groupItem && groupItem.Text == dlg2.Selected)
@@ -115,6 +111,7 @@ namespace ContextMenuManager.Controls
                                 break;
                             }
                         }
+                        WinXHasher.HashLnk(lnkPath);
                         ExplorerRestarter.Show();
                     }
                 }
@@ -132,38 +129,6 @@ namespace ContextMenuManager.Controls
             this.InsertItem(new WinXGroupItem(dirPath), 1);
         }
 
-        public static void HashLnk(string lnkPath)
-        {
-            using(FileStream fs = new FileStream(AppConfig.HashLnkExePath, FileMode.OpenOrCreate))
-            {
-                byte[] buffer;
-                //Any CPU编译条件下,64bit操作系统IntPtr.Size = 8
-                if(IntPtr.Size == 8 && !lnkPath.StartsWith(Environment.ExpandEnvironmentVariables("%ProgramFiles(x86)%")))
-                {
-                    buffer = Properties.Resources.HashLnk_64;
-                }
-                else
-                {
-                    buffer = Properties.Resources.HashLnk_32;
-                }
-                fs.Write(buffer, 0, buffer.Length);
-            }
-
-            using(Process process = new Process())
-            {
-                process.StartInfo = new ProcessStartInfo
-                {
-                    FileName = AppConfig.HashLnkExePath,
-                    Arguments = $"\"{lnkPath}\"",
-                    UseShellExecute = false,
-                    CreateNoWindow = true,
-                    WindowStyle = ProcessWindowStyle.Hidden
-                };
-                process.Start();
-                process.WaitForExit();
-            }
-        }
-
         public static string[] GetGroupNames()
         {
             List<string> items = new List<string>();

+ 3 - 3
ContextMenuManager/GuidInfo.cs

@@ -138,9 +138,9 @@ namespace ContextMenuManager
             IconLocation location = GetIconLocation(guid);
             string iconPath = location.IconPath;
             int iconIndex = location.IconIndex;
-            if(iconPath == null && iconIndex == 0) image = AppImage.DllDefaultIcon;
-            else if(Path.GetFileName(iconPath).ToLower() == "shell32.dll" && iconIndex == 0) image = AppImage.DllDefaultIcon;
-            else image = ResourceIcon.GetIcon(iconPath, iconIndex)?.ToBitmap() ?? AppImage.DllDefaultIcon;
+            if(iconPath == null && iconIndex == 0) image = AppImage.SystemFile;
+            else if(Path.GetFileName(iconPath).ToLower() == "shell32.dll" && iconIndex == 0) image = AppImage.SystemFile;
+            else image = ResourceIcon.GetIcon(iconPath, iconIndex)?.ToBitmap() ?? AppImage.SystemFile;
             ItemImageDic.Add(guid, image);
             return image;
         }

+ 45 - 27
ContextMenuManager/MainForm.cs

@@ -1,4 +1,5 @@
 using BluePointLilac.Controls;
+using BluePointLilac.Methods;
 using ContextMenuManager.Controls;
 using ContextMenuManager.Controls.Interfaces;
 using System;
@@ -13,20 +14,26 @@ namespace ContextMenuManager
     {
         public MainForm()
         {
-            SetSideBarWidth();
+            this.SetSideBarWidth();
             this.Text = AppString.General.AppName;
             this.ForeColor = Color.FromArgb(80, 80, 80);
             this.Controls.Add(new ExplorerRestarter());
             appSettingBox.Owner = shellList.Owner = shellNewList.Owner = sendToList.Owner = openWithList.Owner
                 = winXList.Owner = guidBlockedList.Owner = enhanceMenusList.Owner = thirdRuleList.Owner = iEList.Owner = MainBody;
             donateBox.Parent = aboutMeBox.Parent = dictionariesBox.Parent = languagesBox.Parent = MainBody;
-            SideBar.SelectIndexChanged += (sender, e) => SwitchItem();
+            ToolBar.SelectedButtonChanged += (sender, e) => SwitchTab(ToolBar.SelectedIndex);
             SideBar.HoverIndexChanged += (sender, e) => ShowItemInfo();
-            ToolBar.SelectedButtonChanged += (sender, e) => SwitchTab();
+            SideBar.SelectIndexChanged += (sender, e) => SwitchItem();
             ToolBarButtons[3].MouseDown += (sender, e) => SwitchItem();
             ToolBar.AddButtons(ToolBarButtons);
             ToolBar.SelectedIndex = 0;
             if(AppConfig.ShowFilePath) ShowFilePath();
+            var droper = new ElevatedFileDroper(this);
+            this.DragDrop += (sender, e) =>
+            {
+                ShellList.CurrentFileObjectPath = droper.DropFilePaths[0];
+                SwitchTab(1, 9);
+            };
         }
 
         readonly MyToolBarButton[] ToolBarButtons = new MyToolBarButton[] {
@@ -100,7 +107,8 @@ namespace ContextMenuManager
             AppString.SideBar.PerceivedType,
             AppString.SideBar.DirectoryType,
             null,
-            AppString.SideBar.UnknownType
+            AppString.SideBar.UnknownType,
+            AppString.SideBar.MenuAnalysis
         };
         static readonly string[] TypeItemInfos = {
             AppString.StatusBar.LnkFile,
@@ -111,7 +119,8 @@ namespace ContextMenuManager
             AppString.StatusBar.PerceivedType,
             AppString.StatusBar.DirectoryType,
             null,
-            AppString.StatusBar.UnknownType
+            AppString.StatusBar.UnknownType,
+            AppString.StatusBar.MenuAnalysis
         };
 
         static readonly string[] OtherRuleItems = {
@@ -120,8 +129,9 @@ namespace ContextMenuManager
             null,
             AppString.SideBar.DragDrop,
             AppString.SideBar.PublicReferences,
-            AppString.SideBar.GuidBlocked,
+            AppString.SideBar.CustomRegPath,
             null,
+            AppString.SideBar.GuidBlocked,
             AppString.SideBar.IEMenu
         };
         static readonly string[] OtherRuleItemInfos = {
@@ -130,8 +140,9 @@ namespace ContextMenuManager
             null,
             AppString.StatusBar.DragDrop,
             AppString.StatusBar.PublicReferences,
-            AppString.StatusBar.GuidBlocked,
+            AppString.StatusBar.CustomRegPath,
             null,
+            AppString.StatusBar.GuidBlocked,
             AppString.StatusBar.IEMenu
         };
 
@@ -167,25 +178,14 @@ namespace ContextMenuManager
             ShellList.Scenes.PerceivedType,
             ShellList.Scenes.DirectoryType,
             null,
-            ShellList.Scenes.UnknownType
+            ShellList.Scenes.UnknownType,
+            ShellList.Scenes.MenuAnalysis
         };
 
-        private void HideAllParts()
+        public void SwitchTab(int toolbarIndex, int sidebarIndex = 0)
         {
-            foreach(Control ctr in MainBody.Controls)
-            {
-                ctr.Visible = false;
-                if(ctr.GetType().BaseType == typeof(MyList))
-                {
-                    if(ctr == appSettingBox) continue;
-                    ((MyList)ctr).ClearItems();
-                }
-            }
-        }
-
-        private void SwitchTab()
-        {
-            switch(ToolBar.SelectedIndex)
+            ToolBar.SelectedIndex = toolbarIndex;
+            switch(toolbarIndex)
             {
                 case 0:
                     SideBar.ItemNames = GeneralItems; break;
@@ -196,12 +196,16 @@ namespace ContextMenuManager
                 case 4:
                     SideBar.ItemNames = AboutItems; break;
             }
-            SideBar.SelectIndex = 0;
+            SideBar.SelectIndex = sidebarIndex;
         }
 
         private void SwitchItem()
         {
-            HideAllParts();
+            foreach(Control ctr in MainBody.Controls)
+            {
+                ctr.Visible = false;
+                if(ctr is MyList list && list != appSettingBox) list.ClearItems();
+            }
             if(SideBar.SelectIndex == -1) return;
             switch(ToolBar.SelectedIndex)
             {
@@ -250,7 +254,19 @@ namespace ContextMenuManager
                     {
                         StatusBar.Text = guidItem.Value; return;
                     }
-                    StatusBar.Text = item.Text;
+                    else if(item is ShellList.SelectItem selectItem)
+                    {
+                        switch(shellList.Scene)
+                        {
+                            case ShellList.Scenes.CustomRegPath:
+                                StatusBar.Text = ShellList.CurrentCustomRegPath ?? item.Text; return;
+                            case ShellList.Scenes.MenuAnalysis:
+                                StatusBar.Text = ShellList.CurrentFileObjectPath ?? item.Text; return;
+                        }
+                    }
+                    string regPath = item.GetType().GetProperty("RegPath")?.GetValue(item, null)?.ToString();
+                    if(regPath != null) StatusBar.Text = regPath;
+                    else StatusBar.Text = item.Text;
                 };
             }
         }
@@ -298,8 +314,10 @@ namespace ContextMenuManager
                 case 4:
                     shellList.Scene = ShellList.Scenes.CommandStore; shellList.LoadItems(); shellList.Visible = true; break;
                 case 5:
-                    guidBlockedList.LoadItems(); guidBlockedList.Visible = true; break;
+                    shellList.Scene = ShellList.Scenes.CustomRegPath; shellList.LoadItems(); shellList.Visible = true; break;
                 case 7:
+                    guidBlockedList.LoadItems(); guidBlockedList.Visible = true; break;
+                case 8:
                     iEList.LoadItems(); iEList.Visible = true; break;
             }
         }

+ 5 - 5
ContextMenuManager/Properties/App.manifest

@@ -1,20 +1,20 @@
 <?xml version="1.0" encoding="utf-8"?>
 <assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1">
-  <assemblyIdentity version="1.0.0.0" name="MyApplication.app"/>
+  <assemblyIdentity version="1.0.0.0" name="MyApplication.app" />
   <trustInfo xmlns="urn:schemas-microsoft-com:asm.v2">
     <security>
       <requestedPrivileges xmlns="urn:schemas-microsoft-com:asm.v3">
-        <requestedExecutionLevel level="highestAvailable" uiAccess="false"/>
+        <requestedExecutionLevel level="requireAdministrator" uiAccess="false" />
       </requestedPrivileges>
       <applicationRequestMinimum>
-        <defaultAssemblyRequest permissionSetReference="Custom"/>
-        <PermissionSet class="System.Security.PermissionSet" version="1" Unrestricted="true" ID="Custom" SameSite="site"/>
+        <defaultAssemblyRequest permissionSetReference="Custom" />
+        <PermissionSet class="System.Security.PermissionSet" version="1" ID="Custom" SameSite="site" />
       </applicationRequestMinimum>
     </security>
   </trustInfo>
   <compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
     <application>
-      <supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}"/>
+      <supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}" />
     </application>
   </compatibility>
   <application xmlns="urn:schemas-microsoft-com:asm.v3">

+ 2 - 2
ContextMenuManager/Properties/AssemblyInfo.cs

@@ -11,5 +11,5 @@ using System.Runtime.InteropServices;
 [assembly: AssemblyCulture("")]
 [assembly: ComVisible(false)]
 [assembly: Guid("35190ec1-2515-488d-a2e9-825d6ff67aa2")]
-[assembly: AssemblyVersion("3.1.2.0")]
-[assembly: AssemblyFileVersion("3.1.2.0")]
+[assembly: AssemblyVersion("3.2.0.0")]
+[assembly: AssemblyFileVersion("3.2.0.0")]

+ 12 - 22
ContextMenuManager/Properties/Resources.Designer.cs

@@ -175,7 +175,7 @@ namespace ContextMenuManager.Properties {
         }
         
         /// <summary>
-        ///   查找类似 &lt;?xml version=&apos;1.0&apos; encoding=&apos;utf-8&apos; ?&gt;
+        ///   查找类似 &lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;
         ///&lt;!--此文件为常用右键菜单字典,
         ///Tip属性为鼠标悬浮在开关上时的提示信息,从每个Item节点开始, 子元素Value表示该项的注册表键值,目前仅支持REG_SZ、REG_DWORD、REG_EXPAND_SZ的键值类型,
         ///子元素SubKey的所有子元素是该项的子项,项名即为元素名; 每一Item项和SubKey的所有子元素的属性Default为该注册表项默认值,不放在Value\REG_SZ元素里面是为了防止与可能存在的键名为Default的键产生冲突
@@ -185,7 +185,7 @@ namespace ContextMenuManager.Properties {
         ///    &lt;Shell&gt;
         ///      &lt;Item KeyName=&apos;CopyContent&apos; Tip=&apos;不需打开文件直接复制文件文本内容&amp;#x000A;非UTF-16 LE(或带BOM)编码会乱码&apos;&gt;
         ///        &lt;Value&gt;
-        ///          &lt;REG [字符串的其余部分被截断]&quot;; 的本地化字符串。
+        ///          &lt;REG_ [字符串的其余部分被截断]&quot;; 的本地化字符串。
         /// </summary>
         internal static string EnhanceMenusDic {
             get {
@@ -223,31 +223,21 @@ namespace ContextMenuManager.Properties {
         }
         
         /// <summary>
-        ///   查找 System.Byte[] 类型的本地化资源。
-        /// </summary>
-        internal static byte[] HashLnk_32 {
-            get {
-                object obj = ResourceManager.GetObject("HashLnk_32", resourceCulture);
-                return ((byte[])(obj));
-            }
-        }
-        
-        /// <summary>
-        ///   查找 System.Byte[] 类型的本地化资源。
+        ///   查找 System.Drawing.Bitmap 类型的本地化资源。
         /// </summary>
-        internal static byte[] HashLnk_64 {
+        internal static System.Drawing.Bitmap Home {
             get {
-                object obj = ResourceManager.GetObject("HashLnk_64", resourceCulture);
-                return ((byte[])(obj));
+                object obj = ResourceManager.GetObject("Home", resourceCulture);
+                return ((System.Drawing.Bitmap)(obj));
             }
         }
         
         /// <summary>
         ///   查找 System.Drawing.Bitmap 类型的本地化资源。
         /// </summary>
-        internal static System.Drawing.Bitmap Home {
+        internal static System.Drawing.Bitmap Jump {
             get {
-                object obj = ResourceManager.GetObject("Home", resourceCulture);
+                object obj = ResourceManager.GetObject("Jump", resourceCulture);
                 return ((System.Drawing.Bitmap)(obj));
             }
         }
@@ -343,13 +333,13 @@ namespace ContextMenuManager.Properties {
         }
         
         /// <summary>
-        ///   查找类似 &lt;?xml version=&apos;1.0&apos; encoding=&apos;utf-8&apos; ?&gt;
+        ///   查找类似 &lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;
         ///&lt;!--每个程序为一个Group,Text为Group项显示文本,Guid用于判断用户是否安装此程序并决定是否显示该Group,不设置Guid则为常驻菜单,RegPath为程序相关注册表主路径;
         ///其相关菜单项目设置作为一个Item子元素,Item的Text为该Item项显示文本,Tip属性为鼠标悬浮在开关上时的提示信息,需要重启资源管理器生效则添加属性RestartExplorer;
         ///Item的子元素Rule为相关注册表内容,RegPath省略则默认为Group主路径,以\开头则为Group主路径的子项路径;
         ///ValueName为相关键名,On为启用键值,Off为禁用键值;不设置On或Off属性时,其值为null,对应注册表键值不存在;
         ///每个Item可能受多个注册表Rule影响,按照顺序进行键值判定;判定规则:当有多条规则时,前面的规则注册表键值匹配On则为On,匹配Off则为Off,并终止判断,都不匹配时继续往下判断,若所有规则都不匹配则为On
-        ///ValueKind为键值类型,默认键值类型ValueKind为REG_D [字符串的其余部分被截断]&quot;; 的本地化字符串。
+        ///ValueKind为键值类型,默认键值类型ValueKind为REG_DW [字符串的其余部分被截断]&quot;; 的本地化字符串。
         /// </summary>
         internal static string ThirdRulesDic {
             get {
@@ -408,7 +398,7 @@ namespace ContextMenuManager.Properties {
         }
         
         /// <summary>
-        ///   查找类似 &lt;?xml version=&apos;1.0&apos; encoding=&apos;utf-8&apos; ?&gt;
+        ///   查找类似 &lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot;?&gt;
         ///&lt;!-- 微软在Win10右键菜单中新增的UWP模块, 非Shell、ShellEx类型,
         ///但是可通过GUID锁定屏蔽来禁用右键菜单项目,
         ///GUID查找位置:HKEY_CLASSES_ROOT\PackagedCom\Package\[包名]\Class\[GUID],
@@ -424,7 +414,7 @@ namespace ContextMenuManager.Properties {
         ///	&lt;/Directory&gt;
         ///	&lt;Background&gt;
         ///		&lt;Item Guid=&apos;9f156763-7844-4dc4-b2b1-901f640f5155&apos;/&gt;
-        ///	&lt;/Back [字符串的其余部分被截断]&quot;; 的本地化字符串。
+        ///	&lt;/Backg [字符串的其余部分被截断]&quot;; 的本地化字符串。
         /// </summary>
         internal static string UwpModeItemsDic {
             get {

+ 6 - 9
ContextMenuManager/Properties/Resources.resx

@@ -112,12 +112,12 @@
     <value>2.0</value>
   </resheader>
   <resheader name="reader">
-    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
   </resheader>
   <resheader name="writer">
-    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
   </resheader>
-  <assembly alias="System.Windows.Forms" name="System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
+  <assembly alias="System.Windows.Forms" name="System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
   <data name="About" type="System.Resources.ResXFileRef, System.Windows.Forms">
     <value>resources\images\about.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
   </data>
@@ -151,15 +151,12 @@
   <data name="GuidInfosDic" type="System.Resources.ResXFileRef, System.Windows.Forms">
     <value>resources\texts\guidinfosdic.ini;System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089;utf-8</value>
   </data>
-  <data name="HashLnk_32" type="System.Resources.ResXFileRef, System.Windows.Forms">
-    <value>resources\hashlnk\hashlnk_32.exe;System.Byte[], mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
-  </data>
-  <data name="HashLnk_64" type="System.Resources.ResXFileRef, System.Windows.Forms">
-    <value>resources\hashlnk\hashlnk_64.exe;System.Byte[], mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
-  </data>
   <data name="Home" type="System.Resources.ResXFileRef, System.Windows.Forms">
     <value>resources\images\home.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
   </data>
+  <data name="Jump" type="System.Resources.ResXFileRef, System.Windows.Forms">
+    <value>resources\images\jump.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
+  </data>
   <data name="MicrosoftStore" type="System.Resources.ResXFileRef, System.Windows.Forms">
     <value>resources\images\microsoftstore.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
   </data>

BIN
ContextMenuManager/Properties/Resources/HashLnk/HashLnk_32.exe


BIN
ContextMenuManager/Properties/Resources/HashLnk/HashLnk_64.exe


BIN
ContextMenuManager/Properties/Resources/Images/Jump.png


Fișier diff suprimat deoarece este prea mare
+ 18 - 8
ContextMenuManager/Properties/Resources/Texts/AppLanguageDic.ini


+ 59 - 16
ContextMenuManager/Properties/Resources/Texts/EnhanceMenusDic.xml

@@ -60,7 +60,7 @@ Tip属性为鼠标悬浮在开关上时的提示信息,从每个Item节点开
       <Item KeyName='Windows.NewFolder'>
         <OSVersion Compare=">=">6.1</OSVersion>
         <Value>
-          <REG_SZ MUIVerb='@shell32.dll,-31236' Icon='shell32.dll,-319' Position='top' CommandStateSync='' 
+          <REG_SZ MUIVerb='@shell32.dll,-31236' Icon='shell32.dll,-319' Position='top' CommandStateSync=''
                   CommandStateHandler='{3756e7f5-e514-4776-a32b-eb24bc1efe7a}' CanonicalName='{E44616AD-6DF1-4B94-85A4-E465AE8A19DB}'/>
           <REG_DWORD ImpliedSelectionModel='4' InvokeCommandOnSelection='0'/>
         </Value>
@@ -105,8 +105,8 @@ Tip属性为鼠标悬浮在开关上时的提示信息,从每个Item节点开
               <CreateFile
                 FileName='ShowHiddenFiles.vbs'
                 Content='
+                Dim wsh
                 On Error Resume Next
-                Dim wsh, path, value
                 Set wsh = CreateObject("WScript.Shell")
                 path = "HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced\Hidden"
                 value = 1
@@ -130,8 +130,8 @@ Tip属性为鼠标悬浮在开关上时的提示信息,从每个Item节点开
               <CreateFile
                 FileName='ShowFileExtensions.vbs'
                 Content='
+                Dim wsh
                 On Error Resume Next
-                Dim wsh, path, value
                 Set wsh = CreateObject("WScript.Shell")
                 path = "HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced\HideFileExt"
                 value = 1
@@ -154,8 +154,8 @@ Tip属性为鼠标悬浮在开关上时的提示信息,从每个Item节点开
               <CreateFile
                 FileName='ShowSuperHidden.vbs'
                 Content='
+                Dim wsh
                 On Error Resume Next
-                Dim wsh, path, value
                 Set wsh = CreateObject("WScript.Shell")
                 path = "HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced\ShowSuperHidden"
                 value = 1
@@ -445,7 +445,7 @@ Tip属性为鼠标悬浮在开关上时的提示信息,从每个Item节点开
                       <CreateFile
                         FileName='HyperVMode.vbs'
                         Content='
-                        Dim sap, wsh, msg
+                        Dim sap, wsh
                         Set sap = CreateObject("Shell.Application")
                         sap.ShellExecute "bcdedit", "/set hypervisorlaunchtype auto", "" ,"runas", 0
                         msg = "你当前切换的模式为 Hyper-V," &amp; VbCrlf
@@ -474,7 +474,7 @@ Tip属性为鼠标悬浮在开关上时的提示信息,从每个Item节点开
                       <CreateFile
                         FileName='VirtualBoxMode.vbs'
                         Content='
-                        Dim sap, wsh, msg
+                        Dim sap, wsh
                         Set sap = CreateObject("Shell.Application")
                         sap.ShellExecute "bcdedit", "/set hypervisorlaunchtype off", "", "runas", 0
                         msg = "你当前切换的模式为 VirtualBox," &amp; VbCrlf
@@ -507,8 +507,8 @@ Tip属性为鼠标悬浮在开关上时的提示信息,从每个Item节点开
               <CreateFile
                 FileName='WallPaperLocation.vbs'
                 Content='
+                Dim wsh
                 On Error Resume Next
-                Dim wsh, path
                 Set wsh = CreateObject("WScript.Shell")
                 path = wsh.RegRead("HKCU\Control Panel\Desktop\WallPaper")
                 wsh.Run("explorer /select, " &amp; path)
@@ -558,7 +558,7 @@ Tip属性为鼠标悬浮在开关上时的提示信息,从每个Item节点开
       <!--磁盘清理-->
       <Item KeyName='Windows.CleanUp'>
         <Value>
-          <REG_SZ MUIVerb='@shell32.dll,-22026' Icon='cleanmgr.exe,-104' CommandStateSync='' 
+          <REG_SZ MUIVerb='@shell32.dll,-22026' Icon='cleanmgr.exe,-104' CommandStateSync=''
                   ExplorerCommandHandler='{9cca66bb-9c78-4e59-a76f-a5e9990b8aa0}'/>
           <REG_DWORD ImpliedSelectionModel='0x1'/>
         </Value>
@@ -574,8 +574,8 @@ Tip属性为鼠标悬浮在开关上时的提示信息,从每个Item节点开
               <CreateFile
                 FileName='ShowDriveLetters.vbs'
                 Content='
+                Dim wsh
                 On Error Resume Next
-                Dim wsh, path, value
                 Set wsh = CreateObject("WScript.Shell")
                 path = "HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\ShowDriveLettersFirst"
                 value = 2
@@ -599,8 +599,8 @@ Tip属性为鼠标悬浮在开关上时的提示信息,从每个Item节点开
               <CreateFile
                 FileName='ShowVolumeStrips.vbs'
                 Content='
+                Dim wsh
                 On Error Resume Next
-                Dim wsh, path, value
                 Set wsh = CreateObject("WScript.Shell")
                 path = "HKLM\SOFTWARE\Classes\Drive\TileInfo"
                 value = "prop:*System.PercentFull;System.Computer.DecoratedFreeSpace;System.Volume.FileSystem"
@@ -623,7 +623,7 @@ Tip属性为鼠标悬浮在开关上时的提示信息,从每个Item节点开
       <Item KeyName='Windows.PermanentDelete' Tip='不能用于删除lnk快捷方式文件,&#x000A;或通过快捷方式删除其目标对象'>
         <OSVersion Compare=">=">6.2</OSVersion>
         <Value>
-          <REG_SZ MUIVerb='@shell32.dll,-37394' Icon='shell32.dll,-240' Position='bottom' CommandStateSync='' 
+          <REG_SZ MUIVerb='@shell32.dll,-37394' Icon='shell32.dll,-240' Position='bottom' CommandStateSync=''
                   ExplorerCommandHandler='{E9571AB2-AD92-4ec6-8924-4E5AD33790F5}'/>
         </Value>
       </Item>
@@ -639,8 +639,8 @@ Tip属性为鼠标悬浮在开关上时的提示信息,从每个Item节点开
       <Item KeyName='Windows.CopyAsPath' Tip='系统原生菜单项需按住Shift显示,&#x000A;此项可以直接显示, 路径带双引号'>
         <OSVersion Compare=">=">6.2</OSVersion>
         <Value>
-          <REG_SZ MUIVerb='@shell32.dll,-30329' Icon='imageres.dll,-5302' CommandStateHandler='{3B1599F9-E00A-4BBF-AD3E-B3F99FA87779}' 
-                  CanonicalName='{707C7BC6-685A-4A4D-A275-3966A5A3EFAA}' CommandStateSync='' VerbHandler='{f3d06e7c-1e45-4a26-847e-f9fcdee59be0}' 
+          <REG_SZ MUIVerb='@shell32.dll,-30329' Icon='imageres.dll,-5302' CommandStateHandler='{3B1599F9-E00A-4BBF-AD3E-B3F99FA87779}'
+                  CanonicalName='{707C7BC6-685A-4A4D-A275-3966A5A3EFAA}' CommandStateSync='' VerbHandler='{f3d06e7c-1e45-4a26-847e-f9fcdee59be0}'
                   VerbName='copyaspath' Description='@shell32.dll,-30336'/>
           <REG_DWORD InvokeCommandOnSelection='1'/>
         </Value>
@@ -648,7 +648,7 @@ Tip属性为鼠标悬浮在开关上时的提示信息,从每个Item节点开
       <!--幻灯片放映-->
       <Item KeyName='Windows.SlideShow'>
         <Value>
-          <REG_SZ MUIVerb='@shell32.dll,-31287' Icon='imageres.dll,-5347' CommandStateHandler='{880ac964-2e34-4425-8cf2-86ada2c3a019}' 
+          <REG_SZ MUIVerb='@shell32.dll,-31287' Icon='imageres.dll,-5347' CommandStateHandler='{880ac964-2e34-4425-8cf2-86ada2c3a019}'
                   CanonicalName='{73BCE053-3BBC-4AD7-9FE7-7A7C212C98E6}' CommandStateSync='' Description='@shell32.dll,-31288' VerbToInvoke='slideshow'/>
           <REG_DWORD MediaTypeFlags='5'/>
         </Value>
@@ -695,6 +695,49 @@ Tip属性为鼠标悬浮在开关上时的提示信息,从每个Item节点开
           </Shell>
         </SubKey>
       </Item>
+      <Item KeyName='CreateDesktopShortcut'>
+        <Value>
+          <REG_SZ MUIVerb='创建桌面快捷方式' Icon='imageres.dll,-110'/>
+        </Value>
+        <SubKey>
+          <Command>
+            <FileName>Wscript.exe</FileName>
+            <Arguments Suffix=' "%1"'>
+              <CreateFile
+                FileName='CreateDesktopShortcut.vbs'
+                Content='
+                Dim wsh, fso, shortcut
+                Set paths = WScript.Arguments
+                Set wsh = CreateObject("WScript.Shell")
+                Set fso = CreateObject("Scripting.FileSystemObject")
+                desktop = wsh.SpecialFolders("Desktop")
+                For i = 0 To paths.Count - 1
+	              path = paths(i)
+	              index1 = InstrRev(path, "\")
+	              dir = Mid(path, 1, index1 - 1)
+	              name = Mid(path, index1 + 1)
+	              index2 = InstrRev(name, ".")
+	              If index2 > 0 Then name = Mid(name, 1, index2 - 1)
+	              lnkPath = ""
+	              j = 1
+	              Do
+	                  lnkPath = desktop &amp; "\" &amp; name
+	                  If j > 1 Then lnkPath = lnkPath &amp; " (" &amp; j &amp; ")"
+	                  lnkPath = lnkPath &amp; ".lnk"
+	                  j = j + 1
+	              Loop While fso.FileExists(lnkPath)
+	              Set shortcut = wsh.CreateShortcut(lnkPath)  
+	              shortcut.TargetPath = path 
+	              shortcut.WorkingDirectory = dir
+	              shortcut.Save
+                Next
+                Set shortcut = Nothing
+                Set wsh = Nothing
+                Set fso = Nothing'/>
+            </Arguments>
+          </Command>
+        </SubKey>
+      </Item>
     </Shell>
     <ShellEx>
       <!--复制到文件夹-->
@@ -771,8 +814,8 @@ Tip属性为鼠标悬浮在开关上时的提示信息,从每个Item节点开
               <CreateFile
                 FileName='BatteryReport.vbs'
                 Content='
+                Dim wsh, fso
                 On Error Resume Next
-                Dim wsh, fso, path
                 Set wsh = CreateObject("WScript.Shell")
                 Set fso = CreateObject("Scripting.FileSystemObject")
                 path = fso.GetSpecialFolder(2) &amp; "\BatteryReport.html"
@@ -801,8 +844,8 @@ Tip属性为鼠标悬浮在开关上时的提示信息,从每个Item节点开
               <CreateFile
                 FileName='EditSignInInfo.vbs'
                 Content='
+                Dim wsh
                 On Error Resume Next
-                Dim wsh, path, value
                 Set wsh = CreateObject("WScript.Shell")
                 path = "HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System\LegalnoticeCaption"
                 value = wsh.RegRead(path)

+ 78 - 59
ContextMenuManager/Properties/Resources/Texts/GuidInfosDic.ini

@@ -53,11 +53,11 @@ Text=向左、向右旋转
 [ff609cc7-d34d-4049-a1aa-2293517ffcc6]
 Icon=imageres.dll,-5346
 ;固定到任务栏(&K)
-[90AA3A4E-1CBA-4233-B8BB-535773D48449]
+[90aa3a4e-1cba-4233-b8bb-535773d48449]
 Text=@*,-5386
 Icon=imageres.dll,-5354
 ;打开方式(&H)
-[09799AFB-AD67-11d1-ABCD-00C04FC30936]
+[09799afb-ad67-11d1-abcd-00c04fc30936]
 Text=@*,-5376
 Icon=imageres.dll,-5340
 ;复制为路径(&A)
@@ -68,14 +68,14 @@ Icon=imageres.dll,-5302
 Text=包含到库中(&I)
 Icon=imageres.dll,-1001
 ;固定到"开始"屏幕(&P)
-[470C0EBD-5D73-4d58-9CED-E91E22E23282]
+[470c0ebd-5d73-4d58-9ced-e91e22e23282]
 [email protected],-51201
 Icon=imageres.dll,-5376
 [a2a9545d-a0c2-42b4-9708-a0b2badd77c8]
 Text=附到「开始」菜单(&U)
 Icon=imageres.dll,-80
 ;发送到(&N)
-[7BA4C740-9E81-11CF-99D3-00AA004AE837]
+[7ba4c740-9e81-11cf-99d3-00aa004ae837]
 Text=@*,-30312
 Icon=imageres.dll,-185
 ;下一个桌面背景(&N)
@@ -83,12 +83,12 @@ Icon=imageres.dll,-185
 Text=@*,-416
 Icon=imageres.dll,-5346
 ;新建(&W)
-[D969A300-E7FF-11d0-A93B-00A0C90F2719]
+[d969a300-e7ff-11d0-a93b-00a0c90f2719]
 Text=@*,-95851
 Icon=imageres.dll,-5307
 [6b9228da-9c15-419e-856c-19e768a13bdc]
 Text=Windows 小工具
-[A470F8CF-A1E8-4f65-8335-227475AA5C46]
+[a470f8cf-a1e8-4f65-8335-227475aa5c46]
 Text=加密(&Y)
 Icon=imageres.dll,-59
 ;共享
@@ -96,17 +96,17 @@ Icon=imageres.dll,-59
 Text=@*,-107
 Icon=ntshrui.dll,-123
 ;工作文件夹
-[E61BF828-5E63-4287-BEF1-60B1A4FDE0E3]
+[e61bf828-5e63-4287-bef1-60b1a4fde0e3]
 [email protected],-1
 Icon=WorkFolders.exe
 ;授予访问权限(&G)
 [f81e9010-6ea4-11ce-a7ff-00aa003ca9f6]
 Text=@*,-103
 ;始终脱机可用(&F)
-[474C98EE-CF3D-41f5-80E3-4AAB0AB04301]
+[474c98ee-cf3d-41f5-80e3-4aab0ab04301]
 Text=@*,-38
 ;增强的存储设备
-[2854F705-3548-414C-A113-93E27C808C85]
+[2854f705-3548-414c-a113-93e27c808c85]
 Text=@*,-101
 ;刻录到光盘(&T)
 [fbeb8a05-beee-4442-804e-409d6c4515e9]
@@ -115,13 +115,13 @@ Icon=imageres.dll,-30
 [59099400-57ff-11ce-bd94-0020af85b590]
 Text=复制磁盘(&Y)...
 ;便携设备菜单
-[D6791A63-E7E2-4fee-BF52-5DED8E86E9B8]
+[d6791a63-e7e2-4fee-bf52-5ded8e86e9b8]
 Text=@*,-511
 [0af96ede-aebf-41ed-a1c8-cf7a685505b6]
 Text=不在导航窗格中显示
 Icon=imageres.dll,-5359
 ;还原以前的版本(&V)
-[596AB062-B4D2-4215-9F74-E9109B0A8153]
+[596ab062-b4d2-4215-9f74-e9109b0a8153]
 Text=@*,-1037
 ;公文包
 [85bbd920-42a0-1069-a2e4-08002b30309d]
@@ -146,6 +146,8 @@ Icon=imageres.dll,-5303
 [3080f90e-d7ad-11d9-bd98-0000947b0257]
 [email protected],-12715
 Icon=imageres.dll
+[5635493f-7d77-4372-a839-8ad89f5b3726]
+Text=卸载(&U)
 
 ;----------------显卡------------------
 [a929c4ce-fd36-4270-b4f5-34ecac5bd63c]
@@ -154,45 +156,45 @@ Icon=nvcpl.dll
 [e97dec16-a50d-49bb-ae24-cf682282e08d]
 Text=更改 OpenGL 渲染 GPU...
 Icon=nvcpl.dll
-[3D1975AF-48C6-4f8e-A182-BE0E08FA86A9]
+[3d1975af-48c6-4f8e-a182-be0e08fa86a9]
 Text=NVIDIA 控制面板
 Icon=nvcpl.dll
-[9B5F5829-A529-4B12-814A-E81BCB8D93FC]
+[9b5f5829-a529-4b12-814a-e81bcb8d93fc]
 Text=英特尔® 显卡设置
-Icon=.\igfxEM.exe
+Icon=.\igfxTray.exe
 [3ab1675a-ccff-11d2-8b20-00a0c93cb1f4]
 Text=Intel 显卡
-[5E2121EE-0300-11D4-8D3B-444553540000]
+[5e2121ee-0300-11d4-8d3b-444553540000]
 Text=AMD 显卡
 Icon=.\RadeonSettings.exe
 
 ;----------------压缩------------------
-[5B69A6B4-393B-459C-8EBB-214237A9E7AC]
+[5b69a6b4-393b-459c-8ebb-214237a9e7ac]
 Text=Bandizip
 Icon=.\Bandizip.exe
-[9179176E-B763-3200-8500-BB1B90B3D5DE]
+[9179176e-b763-3200-8500-bb1b90b3d5de]
 Text=360zip
 Icon=.\360zip.exe
-[B41DB860-64E4-11D2-9906-E49FADC173CA]
+[b41db860-64e4-11d2-9906-e49fadc173ca]
 Text=WinRAR 64bit
-[B41DB860-8EE4-11D2-9906-E49FADC173CA]
+[b41db860-8ee4-11d2-9906-e49fadc173ca]
 Text=WinRAR 32bit
-[23170F69-40C1-278A-1000-000100020000]
+[23170f69-40c1-278a-1000-000100020000]
 Text=7-zip
 Icon=.\7zG.exe
-[B1832224-9F22-4965-A6E8-E6A6E3C4FDF7]
+[b1832224-9f22-4965-a6e8-e6a6e3c4fdf7]
 Text=52好压
 Icon=.\kzip_main.exe
-[5FED836A-C96C-4d88-A91E-F63F07726585]
+[5fed836a-c96c-4d88-a91e-f63f07726585]
 Text=2345好压
 Icon=.\HaoZip.exe
-[6ADF19E3-77A3-4395-ADB4-9FD7D351EB3E]
+[6adf19e3-77a3-4395-adb4-9fd7d351eb3e]
 Text=快压
-[903D855A-D671-4A8E-A592-9168755917DB]
+[903d855a-d671-4a8e-a592-9168755917db]
 Text=快压
-[6ADF19E3-77A3-4395-ADB4-9FD7D351EB3E]
+[6adf19e3-77a3-4395-adb4-9fd7d351eb3e]
 Text=快压
-[903D855A-D671-4A8E-A592-9168755917DB]
+[903d855a-d671-4a8e-a592-9168755917db]
 Text=快压
 [e0d79304-84be-11ce-9641-444553540000]
 Text=WinZip
@@ -238,50 +240,50 @@ Icon=.\WinArchiver.exe
 [1532b32d-3a75-4a4d-9b38-5a6000ea7045]
 Text=FreeArc
 Icon=..\FreeArc.exe
-[AD392E40-428C-459F-961E-9B147782D099]
+[ad392e40-428c-459f-961e-9b147782d099]
 Text=UltraISO
 Icon=.\UltraISO.exe
 [be86f80b-eb1a-45b4-b4b6-4b12d302b6bc]
 Text=AntZip
 
 ;----------------杀软------------------
-[09A47860-11B0-4DA5-AFA5-26D86198A780]
+[09a47860-11b0-4da5-afa5-26d86198a780]
 Text=Microsoft Defender
 Icon=.\EppManifest.dll
-[18A3E590-F219-4105-9079-93DAFA51B9D6]
+[18a3e590-f219-4105-9079-93dafa51b9d6]
 Text=使用火绒安全进行杀毒
-[9F012318-CAA5-402C-9BF6-28EB36F61496]
+[9f012318-caa5-402c-9bf6-28eb36f61496]
 Text=使用火绒安全粉碎文件
-[63332668-8CE1-445D-A5EE-25929176714E]
+[63332668-8ce1-445d-a5ee-25929176714e]
 Text=扫描病毒(电脑管家)
-[754DF2CE-51E8-4895-B53C-6381418B84AE]
+[754df2ce-51e8-4895-b53c-6381418b84ae]
 Text=文件粉碎(电脑管家)
-[CBDECEF7-7A29-4cbf-A009-2673D82C7BF9]
+[cbdecef7-7a29-4cbf-a009-2673d82c7bf9]
 Text=强力卸载(电脑管家)
 Icon=.\QQPCSoftMgr.exe
-[C5617F6A-39BB-436D-91CF-61C1B45DD688]
+[c5617f6a-39bb-436d-91cf-61c1b45dd688]
 Text=深度加速(管家小火箭)
 [b7667919-3765-4815-a66d-98a09be662d6]
 Text=清理垃圾(电脑管家)
-[086F171D-5ED1-4ED2-B736-CFF3AD6A128E]
+[086f171d-5ed1-4ed2-b736-cff3ad6a128e]
 Text=使用 360杀毒 扫描
 Icon=.\msdev.exe
-[7C0F6D57-E799-4C8A-A319-8E2B4D724CF0]
+[7c0f6d57-e799-4c8a-a319-8e2b4d724cf0]
 Text=360安全卫士
 Icon=..\360Safe.exe
-[5E19C0CE-C02C-46c2-98C3-A2E12EDE0E17]
+[5e19c0ce-c02c-46c2-98c3-a2e12ede0e17]
 Text=360强力卸载 && 桌面助手
 Icon=.\SoftMgr.exe
-[C4F75DB1-B9F4-425A-9F5B-778911BCF176]
+[c4f75db1-b9f4-425a-9f5b-778911bcf176]
 Text=2345扫描病毒 && 强力删除
 Icon=.\2345MPCSafe.exe
-[6B3BA4A8-EC7E-4714-9ECF-EB33995B3384]
+[6b3ba4a8-ec7e-4714-9ecf-eb33995b3384]
 Text=使用2345软件管家卸载软件
 Icon=..\..\2345SoftMgr.exe
-[DDEA5705-1BB0-4C03-AC1E-8FF9716A0D51]
+[ddea5705-1bb0-4c03-ac1e-8ff9716a0d51]
 Text=金山毒霸(64位)
 Icon=.\kismain.exe
-[D21D88E8-4123-48BA-B0B1-3FDBE4AE5FA4]
+[d21d88e8-4123-48ba-b0b1-3fdbe4ae5fa4]
 Text=金山毒霸(32位)
 Icon=.\kismain.exe
 [367f6ae2-6809-4bed-b09b-228893fb33dd]
@@ -289,7 +291,7 @@ Text=金山毒霸
 Icon=.\kismain.exe
 [758c684b-4d10-4bc1-90da-6bebf0b4e0b4]
 Text=使用联想电脑管家进行扫描
-[C49499AC-DC25-478B-B903-E005012B3DD1]
+[c49499ac-dc25-478b-b903-e005012b3dd1]
 Text=使用智量扫描
 Icon=.\WiseVector.exe
 [cca9efd3-29ed-430a-ba6d-e6bbff0a60c2]
@@ -318,14 +320,16 @@ Text=使用瑞星杀毒
 [0bb81440-5f42-4480-a5f7-770a6f439fc8]
 Text=IObit Malware Fighter
 Icon=*,3
+[b089fe88-fb52-11d3-bdf1-0050da34150d]
+Text=ESET Endpoint Antivirus
 
 ;----------------传输------------------
-[53D2405C-48AB-4C8A-8F59-CE0610F13BBC]
+[53d2405c-48ab-4c8a-8f59-ce0610f13bbc]
 Text=通过QQ发送到
 [cb3d0f55-bc2c-4c1a-85ed-23ed75b5106b]
 Text=OneDrive
 Icon=..\..\OneDrive.exe
-[6D85624F-305A-491d-8848-C1927AA0D790]
+[6d85624f-305a-491d-8848-c1927aa0d790]
 Text=上传到百度网盘
 Icon=.\BaiduNetdisk.exe
 [2008caf4-a5c1-4037-99a8-699e4d01456d]
@@ -340,12 +344,12 @@ Icon=..\115chrome.exe
 [171b6b53-17b1-40b7-afb2-a415b2b40401]
 Text=上传到腾讯微云
 Icon=..\..\..\..\..\..\..\WeiyunApp.exe
-[5D652B62-B702-496A-92BC-92C308251FEA]
+[5d652b62-b702-496a-92bc-92c308251fea]
 Text=坚果云
 Icon=*,3
-[67F4D210-BFC2-4ADD-9A2A-C9B9E1F42C4F]
+[67f4d210-bfc2-4add-9a2a-c9b9e1f42c4f]
 Text=上传到 “WPS云文档”
-[AA147FFB-0B1F-4BB1-9B1E-8D062B35C145]
+[aa147ffb-0b1f-4bb1-9b1e-8d062b35c145]
 Text=自动同步文件夹到 “WPS云文档”
 [970a26b5-2b84-4b60-8067-1440c229672d]
 Text=钉盘
@@ -358,7 +362,7 @@ Text=Dropbox
 [30351349-7b7d-4fcc-81b4-1e394ca267eb]
 Text=TortoiseSVN
 Icon=.\TortoiseIDiff.exe
-[10A0FDD2-B0C0-4CD4-A7AE-E594CE3B91C8]
+[10a0fdd2-b0c0-4cd4-a7ae-e594ce3b91c8]
 Text=TortoiseGit
 Icon=.\TortoiseGitProc.exe
 [2a535b11-6cfc-4e85-a75f-0e397b1584cf]
@@ -379,6 +383,9 @@ Text=广讯通发送文件
 Icon=.\GXT.exe
 [41b3b91f-d6b3-3430-bb86-a143f85353ca]
 Text=Huawei Share
+[1bca9901-05c3-4d01-8ad4-78da2eac9b3f]
+Text=使用小米互传发送
+Icon=.\FixServiceTool.exe
 
 ;----------------PDF------------------
 [9c5397bb-07be-4e38-98ba-395f94045091]
@@ -392,13 +399,13 @@ Text=Adobe Acrobat
 Icon=..\Acrobat\Acrobat.exe
 [d25b2cab-8a9a-4517-a9b2-cb5f68a5a802]
 Text=转换为Adobe PDF(&B)
-[1ECDA7BF-4DFA-41D8-9380-1A27B26CFC41]
+[1ecda7bf-4dfa-41d8-9380-1a27b26cfc41]
 Text=使用WPS PDF编辑
 Icon=..\..\wpspdf.exe
-[E3ED4700-22D4-41B6-8144-E3F5F1AC5153]
+[e3ed4700-22d4-41b6-8144-e3f5f1ac5153]
 Text=使用WPS PDF编辑
 Icon=..\..\wpspdf.exe
-[AF1D7D2F-6AE8-4BAA-ABFA-738201F4871C]
+[af1d7d2f-6ae8-4baa-abfa-738201f4871c]
 Text=WPS Office PDF
 Icon=.\wpspdf.exe
 [b4e15cd0-f916-4c8e-830a-15e3e9d01a1b]
@@ -436,7 +443,7 @@ Text=使用“Windows Media Player”播放(&P)
 Text=使用 Media Player 播放(&P)
 [e598560b-28d5-46aa-a14a-8a3bea34b576]
 Text=幻灯片放映
-[9B6D38F3-8EF4-48A5-AD30-FFFFFFFFFFFF]
+[9b6d38f3-8ef4-48a5-ad30-ffffffffffff]
 Text=Honeyview
 Icon=.\Honeyview.exe
 [c2396f1e-4ba2-4b7d-857a-f764761c012b]
@@ -456,18 +463,24 @@ Text=图片工厂(&F)
 Text=调整图片大小(PowerToys)
 [5c6a637c-9780-4d0f-a379-4732edcce7c3]
 Text=网易云音乐
-[1F77B17B-F531-44DB-ACA4-76ABB5010A28]
+[1f77b17b-f531-44db-aca4-76abb5010a28]
 Text=AIMP
 Icon=..\AIMP.exe
 [8e7861bb-3a13-40a1-af25-633458757201]
 Text=QQ影音
 [7a1884a3-f647-49be-b93c-8ffaf4a1f1bf]
 Text=使用PP视频播放
+[8f556da3-987d-47b0-aa88-eb8d52fe1b99]
+Text=迅雷影音
+Icon=..\..\Program\APlayer.exe
+[4d2fba8d-621b-4447-af6d-5794f479c4a5]
+Text=爱奇艺看图
+Icon=..\QyImg.exe
 
 ;----------------美化------------------
-[CF444751-60FC-48B8-AC0F-363063EB2A9E]
+[cf444751-60fc-48b8-ac0f-363063eb2a9e]
 Text=开启桌面整理(电脑管家)
-[B3A2F1A4-10A2-410C-9C19-622B621C61D0]
+[b3a2f1a4-10a2-410c-9c19-622b621c61d0]
 Text=换壁纸(小鸟壁纸)
 [3b7162fb-4389-40c8-83a5-da10d491ec66]
 Text=映射此文件夹到桌面(小智桌面)
@@ -475,6 +488,9 @@ Icon=.\XZDesktop.exe
 [96babf4f-7c38-4885-b407-3800f461669b]
 Text=打开火萤视频桌面
 Icon=..\..\HYVideoDesktop.exe
+[c3c76829-1d8b-49a2-afb4-196c443f1b0b]
+Text=人工桌面
+Icon=.\N0vaDesktop.exe
 [a2a9545d-a0c2-42b4-9708-a0b2badd77c9]
 Text=附到「开始」菜单(&U)(StartIsBack)
 Icon=.\StartIsBackCfg.exe
@@ -500,7 +516,7 @@ Icon=.\ChromaTune.exe
 Text=右键菜单背景图片插件(第三方)
 
 ;--------------文件处理----------------
-[B298D29A-A6ED-11DE-BA8C-A68E55D89593]
+[b298d29a-a6ed-11de-ba8c-a68e55d89593]
 Text=Notepad++
 [36d94110-787c-4828-9c1b-0dafebc36069]
 Text=EditPlus
@@ -514,7 +530,7 @@ Icon=..\vim.exe
 [ed90173a-3b4c-4e7e-b9cf-79714425d4b5]
 Text=PSPad Editor
 Icon=.\PSPad.exe
-[A3777921-CFD3-4A6B-89BF-08E6B95716E8]
+[a3777921-cfd3-4a6b-89bf-08e6b95716e8]
 Text=格式工厂(&F)
 Icon=.\FormatFactory.exe
 [af9b72b5-f4e4-44b0-a3d9-b55b748efe90]
@@ -544,7 +560,7 @@ Text=File Governor
 Icon=.\FileGovernor.exe
 [1650dc30-2343-498a-b49a-37b90918f611]
 Text=CleanMyPC
-[6CB83A5A-AA68-4895-9F54-175E789AE149]
+[6cb83a5a-aa68-4895-9f54-175e789ae149]
 Text=Balabolka
 Icon=.\balabolka.exe
 [0440049f-d1dc-4e46-b27b-98393d79486b]
@@ -595,13 +611,16 @@ Icon=.\DirListerPro.exe
 [8e57c449-7891-49bb-80e5-ddac375f8ac8]
 Text=使用微表格打开
 Icon=.\microexcel.exe
+[0d8b46ea-7d35-4921-b88c-7e2b1e2d80f0]
+Text=WPS Office
+Icon=..\..\wpsoffice.exe
 
 ;-------------UWP新模块----------------
 [776dbc8d-7347-478c-8d71-791e12ef49d8]
 UwpName=Microsoft.SkypeApp
 Text=@*,-101
 Icon=.\Skype.exe
-[9F156763-7844-4DC4-B2B1-901F640F5155]
+[9f156763-7844-4dc4-b2b1-901f640f5155]
 UwpName=Microsoft.WindowsTerminal
 Text=Open in Windows Terminal
 Icon=.\WindowsTerminal.exe

+ 3 - 3
ContextMenuManager/Updater.cs

@@ -19,9 +19,9 @@ namespace ContextMenuManager
         {
             Version appVersion = new Version(Application.ProductVersion);
             //如果上次检测更新时间为一个月以前就进行更新操作
-            bool flag1 = AppConfig.LastCheckUpdateTime.AddMonths(1).CompareTo(DateTime.Today) < 0;
+            bool flag1 = AppConfig.LastCheckUpdateTime.AddMonths(1) < DateTime.Today;
             //如果配置文件中的版本号与程序版本号不同也进行更新操作
-            bool flag2 = appVersion.CompareTo(AppConfig.Version) != 0;
+            bool flag2 = appVersion != AppConfig.Version;
             if(flag1 || flag2)
             {
                 CheckUpdate();
@@ -52,7 +52,7 @@ namespace ContextMenuManager
                 version1 = new Version(Application.ProductVersion);
             }
             Version version2 = new Version(Application.ProductVersion);
-            if(version1.CompareTo(version2) > 0)
+            if(version1 > version2)
             {
                 string info = reader.GetValue("Update", "Info").Replace("\\n", Environment.NewLine);
                 if(MessageBoxEx.Show($"{AppString.MessageBox.UpdateApp}{version1}{Environment.NewLine}{info}",

+ 12 - 3
Donate.md

@@ -8,9 +8,9 @@
 
 ## 捐赠名单
 
-> 此名单不定期更新(上次更新:**2021-03-16**)
+> 此名单不定期更新(上次更新:**2021-04-11**)
 
-> 累计金额:**366.64** 元,累计人次:**62** 人次
+> 累计金额:**408.3** 元,累计人次:**71** 人次
 
 |日期|用户ID|平台|金额|备注
 |:--:|:--:|:--:|:--:|:--:
@@ -75,4 +75,13 @@
 |2020-03-13|k*h|微信|6.66|右键管理强迫症福音
 |2020-03-13|*🍊|微信|10|软件好用,十分感谢!
 |2020-03-16|**骏|支付宝|0.1|
-|2020-03-16|**华|支付宝|5|
+|2020-03-16|**华|支付宝|5|
+|2020-03-19|**阳|支付宝|1|感谢帮我移除了天翼云盘右键菜单
+|2020-03-23|*👀|微信|6.66|
+|2020-03-25|**楠|支付宝|1|
+|2020-03-29|花*.|微信|3|挺好用哒哒
+|2020-03-30|*珊|微信|10|
+|2020-04-02|**霖|支付宝|10|
+|2020-04-03|**科|支付宝|6|
+|2020-04-08|**帅|支付宝|2|
+|2020-04-08|*财|微信|2|菜单管理工具太棒了

+ 1 - 2
README-en.md

@@ -21,8 +21,7 @@
 
 ## Third-party resources
 * Main program icon from [EasyIcon][EasyIcon]<br>![][AppIcon]
-* [Button icons][AppImage] from [Alibaba Iconfont][IconFont]
-* WinX HashLnk author: [Rafael Rivera][HashLnk]
+* [Button icons][AppImage] from [Alibaba Iconfont][IconFont]![](AppImage.png)
 
 ## Updates
 * Program and dictionary updates can be installed within the program, overwritting the original files.

+ 1 - 2
README.md

@@ -19,8 +19,7 @@
 
 ## 资源引用
 * 程序主图标来自 [EasyIcon][EasyIcon]<br>![][AppIcon]
-* [程序按钮图标][AppImage] 主要来自于 [阿里巴巴矢量图标资源库][IconFont]
-* WinX HashLnk 作者: [Rafael Rivera][HashLnk]
+* [程序按钮图标][AppImage] 主要来自于 [阿里巴巴矢量图标资源库][IconFont]<br>![](AppImage.png)
 
 ## 下载更新
 * 程序有检查更新功能,除了更新程序本身还会更新程序字典,下载完成后直接覆盖原文件即可

+ 3 - 3
Update.ini

@@ -1,4 +1,4 @@
 [Update]
-Version=3.1.2.0
-Url=https://github.com/BluePointLilac/ContextMenuManager/releases/download/3.1.2.0/ContextMenuManager.zip
-Info=【更新描述】\n(1).优化部分代码,修复部分Bug。
+Version=3.2.0.0
+Url=https://github.com/BluePointLilac/ContextMenuManager/releases/download/3.2.0.0/ContextMenuManager.zip
+Info=【更新描述】\n(1).优化部分代码,修复部分Bug;\n(2).添加拖拽文件分析菜单功能;\n(3).添加分析自定义注册表路径菜单功能;\n(4).添加隐藏已禁用菜单项目功能。\n(5).添加了翻译程序功能。\n(6).减小了程序文件大小

Fișier diff suprimat deoarece este prea mare
+ 3 - 41
languages/en-US.ini


+ 3 - 13
languages/ja-JP.ini

@@ -34,8 +34,8 @@ WinX = Win+X
 LnkFile = lnkファイル
 UwpLnk = uwp lnk
 ExeFile = アプリケーション
-UnknownType = 不明な形式
 CustomExtension = カスタムフォーマット
+UnknownType = 不明な形式
 
 GuidBlocked = GUIDロック
 ThirdRules = 第三者のルール
@@ -64,15 +64,8 @@ WinX = Win10、Win8「スタート」ボタンの右クリックメニュー
 LnkFile = すべてのショートカットの右クリックメニュー
 UwpLnk = すべてのWin10、Win8 UWPアプリの右クリックメニュー
 ExeFile = すべてのアプリケーションの右クリックメニュー
-TextFile = テキスト形式(.txt、.iniなど)ファイルの右クリックメニュー
-ImageFile = イメージ形式(.jpg、.pngなど)ファイルの右クリックメニュー
-VideoFile = ビデオ形式(.avi、.wmvなど)ファイルの右クリックメニュー
-AudioFile = オーディオ形式(.mp3、.wavなど)ファイルの右クリックメニュー
-ImageDirectory = イメージファイルディレクトリの右クリックメニュー
-VideoDirectory = ビデオファイルディレクトリの右クリックメニュー
-AudioDirectory = オーディオファイルディレクトリの右クリックメニュー
+CustomExtension = 指定のファイル形式の右クリックメニュー
 UnknownType = すべての不明な形式のファイルの右クリックメニュー
-CustomType = 指定のファイル形式の右クリックメニュー
 
 GuidBlocked = GUIDに依存する頑固なShellExプロジェクトに適しています(一部のGUIDは無効)
 ThirdRules = プログラムディレクトリに含まれる第三者プログラムの内部メニュー設定ルール
@@ -110,9 +103,6 @@ Ok = 確認
 Cancel = キャンセル
 Browse = ブラウズ
 Program = プログラム
-NewShellItem = 新しい「Shell」タイプの右クリックメニュー項目を作成
-NewSendToItem = 新しい「送る」サブメニューを作成
-NewOpenWithItem = 新しい「開く」メニュー項目を作成
 ItemText = アイテムテキスト
 ItemCommand = 菜アイテムコマンド
 SingleMenu = シングルメニュー
@@ -125,6 +115,7 @@ AudioFile = オーディオファイル
 ImageDirectory = イメージディレクトリ
 VideoDirectory = ビデオディレクトリ
 AudioDirectory = オーディオディレクトリ
+EditSubItems = 「%s」のサブメニュー項目を編集
 CheckReference = 引用を追加したいメニュー項目をチェックしてください
 CheckCommon = 追加したい一般的なメニュー項目を確認してください
 SelectExtension = ファイル拡張子を選択してください
@@ -183,7 +174,6 @@ UseStoreOpenWith = Microsoft Storeでアプリを探す
 NewItem = 新しいメニュー項目を作成
 AddGuidBlockedItem = GUIDロックアイテムを追加
 CurrentExtension = 現在選択しているファイル形式は
-EditSubItems = 「%s」のサブメニュー項目を編集
 InvalidItem = 無効なメニュー項目:
 Separator = >>>>>> プロジェクトの分割線 <<<<<<
 DictionaryDescription = 辞書説明

Fișier diff suprimat deoarece este prea mare
+ 11 - 5
languages/zh-CN.ini


Unele fișiere nu au fost afișate deoarece prea multe fișiere au fost modificate în acest diff