├── Resource
└── menu.png
├── MenuFunctions
├── MenuFunctions
│ ├── key.snk
│ ├── packages.config
│ ├── Properties
│ │ ├── AssemblyInfo.cs
│ │ ├── Resources.Designer.cs
│ │ └── Resources.resx
│ ├── MenuFunctions.csproj
│ └── ExplorerHelper.cs
├── 实现运行效果
│ ├── packages.config
│ ├── App.config
│ ├── Properties
│ │ └── AssemblyInfo.cs
│ ├── 实现运行效果.csproj
│ ├── ExplorerHelper.cs
│ └── Program.cs
├── 按键测试2
│ ├── packages.config
│ ├── App.config
│ ├── Properties
│ │ └── AssemblyInfo.cs
│ ├── 按键测试2.csproj
│ └── Program.cs
├── MenuFunctions_Panel
│ ├── packages.config
│ ├── App.config
│ ├── Properties
│ │ ├── Settings.settings
│ │ ├── Settings.Designer.cs
│ │ ├── AssemblyInfo.cs
│ │ ├── Resources.Designer.cs
│ │ └── Resources.resx
│ ├── App.xaml.cs
│ ├── App.xaml
│ ├── 项目说明.txt
│ ├── README.md
│ ├── 快速入门.md
│ ├── 示例配置.json
│ ├── MenuFunctions_Panel.csproj
│ ├── Models
│ │ └── MenuItemConfig.cs
│ ├── MainWindow.xaml.cs
│ ├── ViewModels
│ │ └── MainViewModel.cs
│ └── MainWindow.xaml
├── 按键测试
│ ├── App.config
│ ├── Properties
│ │ └── AssemblyInfo.cs
│ ├── 按键测试.csproj
│ └── Program.cs
├── 测试
│ ├── App.config
│ ├── Properties
│ │ └── AssemblyInfo.cs
│ ├── Program.cs
│ ├── 测试.csproj
│ ├── ExplorerHelper.cs
│ └── RunProgram.cs
├── 测试复选框
│ ├── App.config
│ ├── Properties
│ │ └── AssemblyInfo.cs
│ ├── 测试复选框.csproj
│ └── Program.cs
├── 测试输入控件
│ ├── App.config
│ ├── Properties
│ │ └── AssemblyInfo.cs
│ ├── 测试输入控件.csproj
│ └── Program.cs
├── 卸载计算机全部sharpshelldll.ps1
└── MenuFunctions.sln
├── .gitignore
└── README.md
/Resource/menu.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/onlyclxy/MenuFunctions/main/Resource/menu.png
--------------------------------------------------------------------------------
/MenuFunctions/MenuFunctions/key.snk:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/onlyclxy/MenuFunctions/main/MenuFunctions/MenuFunctions/key.snk
--------------------------------------------------------------------------------
/MenuFunctions/实现运行效果/packages.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/MenuFunctions/按键测试2/packages.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/MenuFunctions/MenuFunctions_Panel/packages.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/MenuFunctions/按键测试/App.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/MenuFunctions/测试/App.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/MenuFunctions/实现运行效果/App.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/MenuFunctions/按键测试2/App.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/MenuFunctions/测试复选框/App.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/MenuFunctions/测试输入控件/App.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/MenuFunctions/MenuFunctions_Panel/App.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/MenuFunctions/MenuFunctions/packages.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/MenuFunctions/MenuFunctions_Panel/Properties/Settings.settings:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # 忽略所有 .exe 文件
2 | *.exe
3 | *.rar
4 | *.zip
5 | *.7z
6 | *.dll
7 | git.txt
8 |
9 |
10 | # 忽略 Visual Studio 临时文件和用户特定文件
11 | *.user
12 | *.suo
13 | .vs/
14 |
15 | # 忽略 NuGet Packages
16 | packages/
17 |
18 | # 忽略 bin 目录
19 | bin/
20 | obj/
21 | Debug/
22 | Release/
23 | MenuFunctions_StableVersion/
24 |
25 |
26 | # 更多忽略规则...
27 |
--------------------------------------------------------------------------------
/MenuFunctions/MenuFunctions_Panel/App.xaml.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Configuration;
4 | using System.Data;
5 | using System.Linq;
6 | using System.Threading.Tasks;
7 | using System.Windows;
8 |
9 | namespace MenuFunctions_Panel
10 | {
11 | ///
12 | /// App.xaml 的交互逻辑
13 | ///
14 | public partial class App : Application
15 | {
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/MenuFunctions/MenuFunctions_Panel/App.xaml:
--------------------------------------------------------------------------------
1 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/MenuFunctions/测试复选框/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 | using System.Runtime.InteropServices;
4 |
5 | // 有关程序集的一般信息由以下
6 | // 控制。更改这些特性值可修改
7 | // 与程序集关联的信息。
8 | [assembly: AssemblyTitle("测试复选框")]
9 | [assembly: AssemblyDescription("")]
10 | [assembly: AssemblyConfiguration("")]
11 | [assembly: AssemblyCompany("")]
12 | [assembly: AssemblyProduct("测试复选框")]
13 | [assembly: AssemblyCopyright("Copyright © 2024")]
14 | [assembly: AssemblyTrademark("")]
15 | [assembly: AssemblyCulture("")]
16 |
17 | // 将 ComVisible 设置为 false 会使此程序集中的类型
18 | //对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型
19 | //请将此类型的 ComVisible 特性设置为 true。
20 | [assembly: ComVisible(false)]
21 |
22 | // 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID
23 | [assembly: Guid("436a0c07-a5a9-49a0-82ef-13fd9817ce6a")]
24 |
25 | // 程序集的版本信息由下列四个值组成:
26 | //
27 | // 主版本
28 | // 次版本
29 | // 生成号
30 | // 修订号
31 | //
32 | //可以指定所有这些值,也可以使用“生成号”和“修订号”的默认值
33 | //通过使用 "*",如下所示:
34 | // [assembly: AssemblyVersion("1.0.*")]
35 | [assembly: AssemblyVersion("1.0.0.0")]
36 | [assembly: AssemblyFileVersion("1.0.0.0")]
37 |
--------------------------------------------------------------------------------
/MenuFunctions/测试/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 | using System.Runtime.InteropServices;
4 |
5 | // 有关程序集的一般信息由以下
6 | // 控制。更改这些特性值可修改
7 | // 与程序集关联的信息。
8 | [assembly: AssemblyTitle("测试")]
9 | [assembly: AssemblyDescription("")]
10 | [assembly: AssemblyConfiguration("")]
11 | [assembly: AssemblyCompany("h3d.com")]
12 | [assembly: AssemblyProduct("测试")]
13 | [assembly: AssemblyCopyright("Copyright © h3d.com 2023")]
14 | [assembly: AssemblyTrademark("")]
15 | [assembly: AssemblyCulture("")]
16 |
17 | // 将 ComVisible 设置为 false 会使此程序集中的类型
18 | //对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型
19 | //请将此类型的 ComVisible 特性设置为 true。
20 | [assembly: ComVisible(false)]
21 |
22 | // 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID
23 | [assembly: Guid("4e0da51c-ece6-40d6-a199-c2beb44e8b15")]
24 |
25 | // 程序集的版本信息由下列四个值组成:
26 | //
27 | // 主版本
28 | // 次版本
29 | // 生成号
30 | // 修订号
31 | //
32 | //可以指定所有这些值,也可以使用“生成号”和“修订号”的默认值
33 | //通过使用 "*",如下所示:
34 | // [assembly: AssemblyVersion("1.0.*")]
35 | [assembly: AssemblyVersion("1.0.0.0")]
36 | [assembly: AssemblyFileVersion("1.0.0.0")]
37 |
--------------------------------------------------------------------------------
/MenuFunctions/测试输入控件/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 | using System.Runtime.InteropServices;
4 |
5 | // 有关程序集的一般信息由以下
6 | // 控制。更改这些特性值可修改
7 | // 与程序集关联的信息。
8 | [assembly: AssemblyTitle("测试输入控件")]
9 | [assembly: AssemblyDescription("")]
10 | [assembly: AssemblyConfiguration("")]
11 | [assembly: AssemblyCompany("")]
12 | [assembly: AssemblyProduct("测试输入控件")]
13 | [assembly: AssemblyCopyright("Copyright © 2024")]
14 | [assembly: AssemblyTrademark("")]
15 | [assembly: AssemblyCulture("")]
16 |
17 | // 将 ComVisible 设置为 false 会使此程序集中的类型
18 | //对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型
19 | //请将此类型的 ComVisible 特性设置为 true。
20 | [assembly: ComVisible(false)]
21 |
22 | // 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID
23 | [assembly: Guid("91648df0-52ef-499c-b21e-fc312be51449")]
24 |
25 | // 程序集的版本信息由下列四个值组成:
26 | //
27 | // 主版本
28 | // 次版本
29 | // 生成号
30 | // 修订号
31 | //
32 | //可以指定所有这些值,也可以使用“生成号”和“修订号”的默认值
33 | //通过使用 "*",如下所示:
34 | // [assembly: AssemblyVersion("1.0.*")]
35 | [assembly: AssemblyVersion("1.0.0.0")]
36 | [assembly: AssemblyFileVersion("1.0.0.0")]
37 |
--------------------------------------------------------------------------------
/MenuFunctions/按键测试/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 | using System.Runtime.InteropServices;
4 |
5 | // 有关程序集的一般信息由以下
6 | // 控制。更改这些特性值可修改
7 | // 与程序集关联的信息。
8 | [assembly: AssemblyTitle("按键测试")]
9 | [assembly: AssemblyDescription("")]
10 | [assembly: AssemblyConfiguration("")]
11 | [assembly: AssemblyCompany("h3d.com")]
12 | [assembly: AssemblyProduct("按键测试")]
13 | [assembly: AssemblyCopyright("Copyright © h3d.com 2023")]
14 | [assembly: AssemblyTrademark("")]
15 | [assembly: AssemblyCulture("")]
16 |
17 | // 将 ComVisible 设置为 false 会使此程序集中的类型
18 | //对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型
19 | //请将此类型的 ComVisible 特性设置为 true。
20 | [assembly: ComVisible(false)]
21 |
22 | // 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID
23 | [assembly: Guid("ab5c5856-cd60-4994-b75f-01542d99f05d")]
24 |
25 | // 程序集的版本信息由下列四个值组成:
26 | //
27 | // 主版本
28 | // 次版本
29 | // 生成号
30 | // 修订号
31 | //
32 | //可以指定所有这些值,也可以使用“生成号”和“修订号”的默认值
33 | //通过使用 "*",如下所示:
34 | // [assembly: AssemblyVersion("1.0.*")]
35 | [assembly: AssemblyVersion("1.0.0.0")]
36 | [assembly: AssemblyFileVersion("1.0.0.0")]
37 |
--------------------------------------------------------------------------------
/MenuFunctions/实现运行效果/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 | using System.Runtime.InteropServices;
4 |
5 | // 有关程序集的一般信息由以下
6 | // 控制。更改这些特性值可修改
7 | // 与程序集关联的信息。
8 | [assembly: AssemblyTitle("实现运行效果")]
9 | [assembly: AssemblyDescription("")]
10 | [assembly: AssemblyConfiguration("")]
11 | [assembly: AssemblyCompany("h3d.com")]
12 | [assembly: AssemblyProduct("实现运行效果")]
13 | [assembly: AssemblyCopyright("Copyright © h3d.com 2023")]
14 | [assembly: AssemblyTrademark("")]
15 | [assembly: AssemblyCulture("")]
16 |
17 | // 将 ComVisible 设置为 false 会使此程序集中的类型
18 | //对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型
19 | //请将此类型的 ComVisible 特性设置为 true。
20 | [assembly: ComVisible(false)]
21 |
22 | // 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID
23 | [assembly: Guid("81868e36-4bff-43ef-9010-e436789b19ee")]
24 |
25 | // 程序集的版本信息由下列四个值组成:
26 | //
27 | // 主版本
28 | // 次版本
29 | // 生成号
30 | // 修订号
31 | //
32 | //可以指定所有这些值,也可以使用“生成号”和“修订号”的默认值
33 | //通过使用 "*",如下所示:
34 | // [assembly: AssemblyVersion("1.0.*")]
35 | [assembly: AssemblyVersion("1.0.0.0")]
36 | [assembly: AssemblyFileVersion("1.0.0.0")]
37 |
--------------------------------------------------------------------------------
/MenuFunctions/按键测试2/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 | using System.Runtime.InteropServices;
4 |
5 | // 有关程序集的一般信息由以下
6 | // 控制。更改这些特性值可修改
7 | // 与程序集关联的信息。
8 | [assembly: AssemblyTitle("按键测试2")]
9 | [assembly: AssemblyDescription("")]
10 | [assembly: AssemblyConfiguration("")]
11 | [assembly: AssemblyCompany("h3d.com")]
12 | [assembly: AssemblyProduct("按键测试2")]
13 | [assembly: AssemblyCopyright("Copyright © h3d.com 2023")]
14 | [assembly: AssemblyTrademark("")]
15 | [assembly: AssemblyCulture("")]
16 |
17 | // 将 ComVisible 设置为 false 会使此程序集中的类型
18 | //对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型
19 | //请将此类型的 ComVisible 特性设置为 true。
20 | [assembly: ComVisible(false)]
21 |
22 | // 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID
23 | [assembly: Guid("0ccad1a0-93f4-468f-a1e2-03e3c6c1bc08")]
24 |
25 | // 程序集的版本信息由下列四个值组成:
26 | //
27 | // 主版本
28 | // 次版本
29 | // 生成号
30 | // 修订号
31 | //
32 | //可以指定所有这些值,也可以使用“生成号”和“修订号”的默认值
33 | //通过使用 "*",如下所示:
34 | // [assembly: AssemblyVersion("1.0.*")]
35 | [assembly: AssemblyVersion("1.0.0.0")]
36 | [assembly: AssemblyFileVersion("1.0.0.0")]
37 |
--------------------------------------------------------------------------------
/MenuFunctions/MenuFunctions/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 | using System.Runtime.InteropServices;
4 |
5 | // 有关程序集的一般信息由以下
6 | // 控制。更改这些特性值可修改
7 | // 与程序集关联的信息。
8 | [assembly: AssemblyTitle("AuroraContextMenu")]
9 | [assembly: AssemblyDescription("")]
10 | [assembly: AssemblyConfiguration("")]
11 | [assembly: AssemblyCompany("")]
12 | [assembly: AssemblyProduct("AuroraContextMenu")]
13 | [assembly: AssemblyCopyright("Copyright © 2020")]
14 | [assembly: AssemblyTrademark("")]
15 | [assembly: AssemblyCulture("")]
16 |
17 | //将 ComVisible 设置为 false 将使此程序集中的类型
18 | //对 COM 组件不可见。 如果需要从 COM 访问此程序集中的类型,
19 | //请将此类型的 ComVisible 特性设置为 true。
20 | [assembly: ComVisible(true)]
21 |
22 | // 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID
23 | [assembly: Guid("e117fbc0-7ab4-4c15-a4a9-646e97854821")]
24 |
25 | // 程序集的版本信息由下列四个值组成:
26 | //
27 | // 主版本
28 | // 次版本
29 | // 生成号
30 | // 修订号
31 | //
32 | //可以指定所有这些值,也可以使用“生成号”和“修订号”的默认值,
33 | // 方法是按如下所示使用“*”: :
34 | // [assembly: AssemblyVersion("1.0.*")]
35 | [assembly: AssemblyVersion("1.0.0.0")]
36 | [assembly: AssemblyFileVersion("1.0.0.0")]
37 |
--------------------------------------------------------------------------------
/MenuFunctions/测试/Program.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Diagnostics;
4 | using System.Linq;
5 | using System.Text;
6 | using System.Threading.Tasks;
7 |
8 | namespace 测试
9 | {
10 | internal class Program
11 | {
12 | static void Main(string[] args)
13 | {
14 |
15 |
16 | string customParameter = ""; // 预留的自定义参数
17 | // 循环接受输入并处理
18 | while (true)
19 | {
20 | Console.WriteLine("请输入命令(输入'exit'退出):");
21 | string input = Console.ReadLine();
22 |
23 | if (input.ToLower() == "exit")
24 | {
25 | break;
26 | }
27 |
28 |
29 | try
30 | {
31 | Process.Start(input);
32 | }
33 | catch (Exception ex)
34 | {
35 | Console.WriteLine("直接执行命令时发生错误: " + ex.Message);
36 | Console.WriteLine("尝试通过cmd.exe执行...");
37 |
38 | RunProgram.ProcessInputCommand(input, customParameter);
39 | }
40 | }
41 | }
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/MenuFunctions/MenuFunctions_Panel/Properties/Settings.Designer.cs:
--------------------------------------------------------------------------------
1 | //------------------------------------------------------------------------------
2 | //
3 | // This code was generated by a tool.
4 | // Runtime Version:4.0.30319.42000
5 | //
6 | // Changes to this file may cause incorrect behavior and will be lost if
7 | // the code is regenerated.
8 | //
9 | //------------------------------------------------------------------------------
10 |
11 | namespace MenuFunctions_Panel.Properties
12 | {
13 |
14 |
15 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
16 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "11.0.0.0")]
17 | internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase
18 | {
19 |
20 | private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
21 |
22 | public static Settings Default
23 | {
24 | get
25 | {
26 | return defaultInstance;
27 | }
28 | }
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | 功能介绍:
2 | 可以分别设置显示在文件右键菜单,目录菜单,文件夹背景菜单
3 | 可直接运行程序,路径,网址,cmd命令
4 | 传递多路径到同一程序
5 | 图标可以设置常见图片格式,ico,png,gif,jpg,bmp,exe,msi,msc,com,lnk,网址
6 | 自定义传参,比如设置一个参数-k 这个可以分别传给所有的地址, 也可以附加在所有地址的最后面
7 | 可以设定按照固定的扩展名来显示菜单
8 | 多层级菜单,或者置顶到一级菜单
9 |
10 | 扩展功能
11 | 复制路径到剪贴板功能
12 | 打开所在文件夹并且选中文件或目录 (这个本来用explorer select可以实现,但是这个启动新进程会特别慢.所以增加这个功能.)
13 |
14 |
15 | 
16 |
17 |
18 |
19 | 第一次运行:注册dll,会将MenuFunctions.dll注册到系统,启用右键菜单.
20 | MenuConfig.json是配置文件,不可删.修改里面配置会实时生效.
21 | 建议你电脑装个notepad3.这样如果你配置写错了.他会标记错误.而普通记事本你配置写错了也不知道错哪了
22 | 如果要卸载的话,点击卸载dll.
23 | 注意这个路径你注册后不可改位置.别到时候给文件夹移动走了.. 那没准右键菜单就直接报错了..可以先卸载,再挪文件夹位置. 然后再注册
24 | 注意这个东西有固态盘请一定放固态盘. 包括图标用的图标,要不然每次这个右键都会读硬盘.读配置文件和图片. 你放普通硬盘慢的话,没准会卡菜单.. 当然只是没准. 其实配置文件现在30多kb. 读个30kb我觉得还是轻轻松松..要是30kb读着都慢.那可能是硬盘坏了..
25 | 文件夹内任何文件都不可删除.
26 |
27 | 更新 2023-12-7
28 | 1 路径现在改到添加到所有参数的后面,这样很多命令就正常了. 比如python.exe 显示路径.py 选中路径 这种好几个叠起来的就可以正常运行了.
29 | 2.图标现在除了常用图片外,改为获取全部格式的ico图标.就比如你见一个文件是json图标挺好看,你可以把这个json文件的路径填进去,然后就变成了json的图标..
30 | 3.增加使用cmd运行命令.这样可以直接在ProgramPath输入命令从而用cmd执行
31 | 4.cmd命令的一些拓展,可以隐藏cmd窗口启动,或者保持cmd不关闭.方便各种用途.比如你给文件设置隐藏属性,可能就不需要显示cmd窗口. 比如你要ping ip,就需要保持窗口不要一闪而过.
32 | 5.增加菜单分割线
33 | 6.增加自检弹窗. 这个可以检测实际运行的命令和路径是否符合预期.
34 | 7.增加菜单文本动态显示路径功能.就是那个压缩包.你选中文件点压缩包,会直接显示解压到xxx,或者压缩到xxx. 这个,可以把路径,或者文件名等传给菜单
35 |
36 | 这个配置文件模板 放到了原始Json文件备份里,名字是MenuConfig_new.json,有兴趣可以改名用这个试试
37 | 另外查了查GPT说是win11的多标签获取路径好像弄不了,先这样把.测试这个测试的我要吐啊...
--------------------------------------------------------------------------------
/MenuFunctions/MenuFunctions_Panel/项目说明.txt:
--------------------------------------------------------------------------------
1 | ═══════════════════════════════════════════════════════════
2 | 右键菜单配置编辑器 - MenuFunctions_Panel
3 | ═══════════════════════════════════════════════════════════
4 |
5 | 【项目简介】
6 | 这是一个 WPF 可视化工具,用于编辑 SharpShell 右键菜单的 JSON 配置文件。
7 | 替代手动编写 JSON,提供类似 PC Quicker 的友好编辑界面。
8 |
9 | 【主要文件】
10 | ├─ MenuFunctions_Panel.exe 主程序
11 | ├─ Newtonsoft.Json.dll JSON 处理库
12 | ├─ README.md 完整功能说明
13 | ├─ 快速入门.md 快速上手指南
14 | └─ 示例配置.json 示例配置文件
15 |
16 | 【技术架构】
17 | - 框架:WPF + .NET Framework 4.8
18 | - 模式:MVVM (Model-View-ViewModel)
19 | - 依赖:Newtonsoft.Json 13.0.3
20 |
21 | 【核心功能】
22 | ✓ 可视化编辑 JSON 配置
23 | ✓ 树形显示菜单结构
24 | ✓ 支持多级子菜单
25 | ✓ 拖拽式排序(上移/下移)
26 | ✓ 文件浏览器集成
27 | ✓ 自动加载配置
28 | ✓ 实时预览和保存
29 |
30 | 【界面特色】
31 | 参考 PC Quicker 风格:
32 | - 左侧:树形菜单结构
33 | - 右侧:详细配置面板(分组折叠)
34 | - 顶部:工具栏(常用操作)
35 | - 底部:状态栏(当前文件)
36 |
37 | 【配置项支持】
38 | 完整支持 MenuItemConfig 的所有属性:
39 | □ 基本信息:文本、可见性、排序
40 | □ 显示位置:文件/文件夹/背景/根菜单
41 | □ 程序设置:路径、参数、图标
42 | □ 文件类型:扩展名过滤
43 | □ 高级选项:引号、参数方式
44 | □ CMD 设置:隐藏窗口、保持打开
45 |
46 | 【使用流程】
47 | 1. 运行程序 → 自动加载或手动打开配置
48 | 2. 编辑配置 → 使用图形界面修改
49 | 3. 保存文件 → 生成格式化的 JSON
50 | 4. 应用配置 → 复制到 DLL 目录,重启资源管理器
51 |
52 | 【开发信息】
53 | 开发日期:2025-11-01
54 | 开发框架:Visual Studio 2022
55 | 目标平台:Windows 10/11
56 | 项目类型:WPF Application
57 |
58 | 【相关文档】
59 | - README.md:详细功能说明和技术文档
60 | - 快速入门.md:5分钟上手指南
61 | - 示例配置.json:参考示例
62 |
63 | ═══════════════════════════════════════════════════════════
64 | 如有问题,请参考文档或查看源代码
65 | ═══════════════════════════════════════════════════════════
66 |
67 |
--------------------------------------------------------------------------------
/MenuFunctions/MenuFunctions_Panel/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Resources;
3 | using System.Runtime.CompilerServices;
4 | using System.Runtime.InteropServices;
5 | using System.Windows;
6 |
7 | // 有关程序集的一般信息由以下
8 | // 控制。更改这些特性值可修改
9 | // 与程序集关联的信息。
10 | [assembly: AssemblyTitle("MenuFunctions_Panel")]
11 | [assembly: AssemblyDescription("")]
12 | [assembly: AssemblyConfiguration("")]
13 | [assembly: AssemblyCompany("")]
14 | [assembly: AssemblyProduct("MenuFunctions_Panel")]
15 | [assembly: AssemblyCopyright("Copyright © 2025")]
16 | [assembly: AssemblyTrademark("")]
17 | [assembly: AssemblyCulture("")]
18 |
19 | // 将 ComVisible 设置为 false 会使此程序集中的类型
20 | //对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型
21 | //请将此类型的 ComVisible 特性设置为 true。
22 | [assembly: ComVisible(false)]
23 |
24 | //若要开始生成可本地化的应用程序,请设置
25 | //.csproj 文件中的 CultureYouAreCodingWith
26 | //在 中。例如,如果你使用的是美国英语。
27 | //使用的是美国英语,请将 设置为 en-US。 然后取消
28 | //对以下 NeutralResourceLanguage 特性的注释。 更新
29 | //以下行中的“en-US”以匹配项目文件中的 UICulture 设置。
30 |
31 | //[assembly: NeutralResourcesLanguage("en-US", UltimateResourceFallbackLocation.Satellite)]
32 |
33 |
34 | [assembly: ThemeInfo(
35 | ResourceDictionaryLocation.None, //主题特定资源词典所处位置
36 | //(未在页面中找到资源时使用,
37 | //或应用程序资源字典中找到时使用)
38 | ResourceDictionaryLocation.SourceAssembly //常规资源词典所处位置
39 | //(未在页面中找到资源时使用,
40 | //、应用程序或任何主题专用资源字典中找到时使用)
41 | )]
42 |
43 |
44 | // 程序集的版本信息由下列四个值组成:
45 | //
46 | // 主版本
47 | // 次版本
48 | // 生成号
49 | // 修订号
50 | //
51 | [assembly: AssemblyVersion("1.0.0.0")]
52 | [assembly: AssemblyFileVersion("1.0.0.0")]
53 |
--------------------------------------------------------------------------------
/MenuFunctions/测试复选框/测试复选框.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | AnyCPU
7 | {436A0C07-A5A9-49A0-82EF-13FD9817CE6A}
8 | Exe
9 | 测试复选框
10 | 测试复选框
11 | v4.7.2
12 | 512
13 | true
14 | true
15 |
16 |
17 | AnyCPU
18 | true
19 | full
20 | false
21 | bin\Debug\
22 | DEBUG;TRACE
23 | prompt
24 | 4
25 |
26 |
27 | AnyCPU
28 | pdbonly
29 | true
30 | bin\Release\
31 | TRACE
32 | prompt
33 | 4
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
--------------------------------------------------------------------------------
/MenuFunctions/测试输入控件/测试输入控件.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | AnyCPU
7 | {91648DF0-52EF-499C-B21E-FC312BE51449}
8 | Exe
9 | 测试输入控件
10 | 测试输入控件
11 | v4.7.2
12 | 512
13 | true
14 | true
15 |
16 |
17 | AnyCPU
18 | true
19 | full
20 | false
21 | bin\Debug\
22 | DEBUG;TRACE
23 | prompt
24 | 4
25 |
26 |
27 | AnyCPU
28 | pdbonly
29 | true
30 | bin\Release\
31 | TRACE
32 | prompt
33 | 4
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
--------------------------------------------------------------------------------
/MenuFunctions/按键测试/按键测试.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | AnyCPU
7 | {AB5C5856-CD60-4994-B75F-01542D99F05D}
8 | Exe
9 | 按键测试
10 | 按键测试
11 | v4.8
12 | 512
13 | true
14 | true
15 |
16 |
17 | AnyCPU
18 | true
19 | full
20 | false
21 | bin\Debug\
22 | DEBUG;TRACE
23 | prompt
24 | 4
25 |
26 |
27 | AnyCPU
28 | pdbonly
29 | true
30 | bin\Release\
31 | TRACE
32 | prompt
33 | 4
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
--------------------------------------------------------------------------------
/MenuFunctions/MenuFunctions/Properties/Resources.Designer.cs:
--------------------------------------------------------------------------------
1 | //------------------------------------------------------------------------------
2 | //
3 | // 此代码由工具生成。
4 | // 运行时版本:4.0.30319.42000
5 | //
6 | // 对此文件的更改可能会导致不正确的行为,并且如果
7 | // 重新生成代码,这些更改将会丢失。
8 | //
9 | //------------------------------------------------------------------------------
10 |
11 | namespace MenuFunctions.Properties {
12 | using System;
13 |
14 |
15 | ///
16 | /// 一个强类型的资源类,用于查找本地化的字符串等。
17 | ///
18 | // 此类是由 StronglyTypedResourceBuilder
19 | // 类通过类似于 ResGen 或 Visual Studio 的工具自动生成的。
20 | // 若要添加或移除成员,请编辑 .ResX 文件,然后重新运行 ResGen
21 | // (以 /str 作为命令选项),或重新生成 VS 项目。
22 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")]
23 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
24 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
25 | internal class Resources {
26 |
27 | private static global::System.Resources.ResourceManager resourceMan;
28 |
29 | private static global::System.Globalization.CultureInfo resourceCulture;
30 |
31 | [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
32 | internal Resources() {
33 | }
34 |
35 | ///
36 | /// 返回此类使用的缓存的 ResourceManager 实例。
37 | ///
38 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
39 | internal static global::System.Resources.ResourceManager ResourceManager {
40 | get {
41 | if (object.ReferenceEquals(resourceMan, null)) {
42 | global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("MenuFunctions.Properties.Resources", typeof(Resources).Assembly);
43 | resourceMan = temp;
44 | }
45 | return resourceMan;
46 | }
47 | }
48 |
49 | ///
50 | /// 重写当前线程的 CurrentUICulture 属性,对
51 | /// 使用此强类型资源类的所有资源查找执行重写。
52 | ///
53 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
54 | internal static global::System.Globalization.CultureInfo Culture {
55 | get {
56 | return resourceCulture;
57 | }
58 | set {
59 | resourceCulture = value;
60 | }
61 | }
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/MenuFunctions/MenuFunctions_Panel/Properties/Resources.Designer.cs:
--------------------------------------------------------------------------------
1 | //------------------------------------------------------------------------------
2 | //
3 | // 此代码由工具生成。
4 | // 运行时版本: 4.0.30319.42000
5 | //
6 | // 对此文件的更改可能导致不正确的行为,如果
7 | // 重新生成代码,则所做更改将丢失。
8 | //
9 | //------------------------------------------------------------------------------
10 |
11 | namespace MenuFunctions_Panel.Properties
12 | {
13 |
14 |
15 | ///
16 | /// 强类型资源类,用于查找本地化字符串等。
17 | ///
18 | // 此类是由 StronglyTypedResourceBuilder
19 | // 类通过类似于 ResGen 或 Visual Studio 的工具自动生成的。
20 | // 若要添加或移除成员,请编辑 .ResX 文件,然后重新运行 ResGen
21 | // (以 /str 作为命令选项),或重新生成 VS 项目。
22 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
23 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
24 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
25 | internal class Resources
26 | {
27 |
28 | private static global::System.Resources.ResourceManager resourceMan;
29 |
30 | private static global::System.Globalization.CultureInfo resourceCulture;
31 |
32 | [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
33 | internal Resources()
34 | {
35 | }
36 |
37 | ///
38 | /// 返回此类使用的缓存 ResourceManager 实例。
39 | ///
40 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
41 | internal static global::System.Resources.ResourceManager ResourceManager
42 | {
43 | get
44 | {
45 | if ((resourceMan == null))
46 | {
47 | global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("MenuFunctions_Panel.Properties.Resources", typeof(Resources).Assembly);
48 | resourceMan = temp;
49 | }
50 | return resourceMan;
51 | }
52 | }
53 |
54 | ///
55 | /// 重写当前线程的 CurrentUICulture 属性,对
56 | /// 使用此强类型资源类的所有资源查找执行重写。
57 | ///
58 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
59 | internal static global::System.Globalization.CultureInfo Culture
60 | {
61 | get
62 | {
63 | return resourceCulture;
64 | }
65 | set
66 | {
67 | resourceCulture = value;
68 | }
69 | }
70 | }
71 | }
72 |
--------------------------------------------------------------------------------
/MenuFunctions/按键测试2/按键测试2.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | AnyCPU
7 | {0CCAD1A0-93F4-468F-A1E2-03E3C6C1BC08}
8 | Exe
9 | 按键测试2
10 | 按键测试2
11 | v4.8
12 | 512
13 | true
14 | true
15 |
16 |
17 | AnyCPU
18 | true
19 | full
20 | false
21 | bin\Debug\
22 | DEBUG;TRACE
23 | prompt
24 | 4
25 |
26 |
27 | AnyCPU
28 | pdbonly
29 | true
30 | bin\Release\
31 | TRACE
32 | prompt
33 | 4
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 | ..\packages\InputSimulatorCore.1.0.5\lib\netstandard2.0\WindowsInput.dll
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
--------------------------------------------------------------------------------
/MenuFunctions/测试/测试.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | AnyCPU
7 | {4E0DA51C-ECE6-40D6-A199-C2BEB44E8B15}
8 | Exe
9 | 测试
10 | 测试
11 | v4.8
12 | 512
13 | true
14 | true
15 |
16 |
17 | AnyCPU
18 | true
19 | full
20 | false
21 | bin\Debug\
22 | DEBUG;TRACE
23 | prompt
24 | 4
25 |
26 |
27 | AnyCPU
28 | pdbonly
29 | true
30 | bin\Release\
31 | TRACE
32 | prompt
33 | 4
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 | {F935DC20-1CF0-11D0-ADB9-00C04FD58A0B}
57 | 1
58 | 0
59 | 0
60 | tlbimp
61 | False
62 | True
63 |
64 |
65 |
66 |
--------------------------------------------------------------------------------
/MenuFunctions/MenuFunctions_Panel/README.md:
--------------------------------------------------------------------------------
1 | # 右键菜单配置编辑器
2 |
3 | 这是一个用于可视化编辑 SharpShell 右键菜单配置的 WPF 工具。
4 |
5 | ## 功能特性
6 |
7 | - ✅ **可视化编辑**:通过图形界面编辑 JSON 配置,无需手动编写
8 | - ✅ **树形结构**:清晰显示菜单层级结构,支持子菜单
9 | - ✅ **拖拽排序**:使用上移/下移按钮调整菜单项顺序
10 | - ✅ **完整配置**:支持所有配置选项,包括显示位置、CMD 设置等
11 | - ✅ **文件浏览**:集成文件浏览器,方便选择程序和图标
12 | - ✅ **自动加载**:启动时自动查找并加载配置文件
13 |
14 | ## 界面布局
15 |
16 | ### 顶部工具栏
17 | - 📂 **打开**:打开现有的 MenuConfig.json 文件
18 | - 💾 **保存**:保存配置到文件
19 | - ➕ **新增**:添加根菜单项
20 | - 📑 **添加子项**:为选中项添加子菜单
21 | - ➖ **分隔线**:添加菜单分隔线
22 | - 🗑️ **删除**:删除选中的菜单项
23 | - ⬆️ **上移** / ⬇️ **下移**:调整菜单项顺序
24 |
25 | ### 左侧面板 - 菜单结构
26 | 显示所有菜单项的树形结构,支持:
27 | - 查看菜单层级关系
28 | - 选择要编辑的菜单项
29 | - 查看菜单项状态(分隔线、隐藏等)
30 |
31 | ### 右侧面板 - 详细配置
32 | 分为多个可折叠区域:
33 |
34 | #### 📌 基本信息
35 | - **菜单文本**:显示在右键菜单中的文字(支持动态变量)
36 | - **是否为分隔线**:设置为菜单分隔线
37 | - **是否可见**:控制菜单项的显示/隐藏
38 | - **排序序号**:菜单项的排序值
39 |
40 | #### 📍 显示位置
41 | - **显示在根菜单**:直接显示在右键菜单根部
42 | - **显示在文件上**:右键点击文件时显示
43 | - **显示在文件夹上**:右键点击文件夹时显示
44 | - **显示在文件夹背景**:在文件夹空白处右键时显示
45 |
46 | #### ⚙️ 程序设置
47 | - **程序路径**:要执行的程序(支持预设命令如 `copypath`)
48 | - **命令参数**:传递给程序的参数
49 | - **图标路径**:菜单项图标(支持 .ico、.png、.exe 等)
50 |
51 | #### 📄 文件类型过滤
52 | - 指定适用的文件扩展名(如 `.txt, .doc`)
53 | - 留空表示适用于所有文件
54 |
55 | #### 🔧 高级选项
56 | - **参数跟在每条路径后面**:控制参数的拼接方式
57 | - **路径使用引号**:为文件路径添加双引号
58 | - **只使用程序路径**:不传递文件路径,只运行程序
59 | - **添加文件类型参数**:在末尾添加 `&file` 或 `&folder` 标识
60 | - **显示完整路径和命令**:调试模式,执行前显示完整命令
61 |
62 | #### 💻 CMD 设置
63 | - **通过 CMD 运行程序**:使用 cmd.exe 执行命令
64 | - **隐藏 CMD 窗口**:不显示命令行窗口
65 | - **保持 CMD 窗口打开**:命令执行后保持窗口(/K 参数)
66 |
67 | ## 动态变量
68 |
69 | 在"菜单文本"中可以使用以下动态变量:
70 |
71 | - `${filename}` - 文件名(无扩展名)
72 | - `${filename-single}` - 第一个文件名
73 | - `${extension}` - 文件扩展名
74 | - `${extension-single}` - 第一个文件的扩展名
75 | - `${parentdir}` - 父目录路径
76 | - `${parentdir-single}` - 第一个文件的父目录
77 | - `${fullpath}` - 完整路径
78 | - `${fullpath-single}` - 第一个文件的完整路径
79 |
80 | 示例:`复制 ${filename} 到剪贴板`
81 |
82 | ## 预设命令
83 |
84 | 在"程序路径"中可以使用预设命令:
85 |
86 | - `copypath` - 复制路径到剪贴板
87 | - `openfolderandselectitems` - 打开文件夹并选中项目
88 | - `messagebox.show` - 显示消息框
89 |
90 | ## 使用流程
91 |
92 | 1. **打开配置**:
93 | - 点击"打开"按钮选择 `MenuConfig.json`
94 | - 或将配置文件放在程序同目录,自动加载
95 |
96 | 2. **编辑菜单**:
97 | - 点击"新增"添加新菜单项
98 | - 在左侧树中选择要编辑的项
99 | - 在右侧面板修改配置
100 | - 使用"添加子项"创建子菜单
101 |
102 | 3. **调整顺序**:
103 | - 选中要移动的菜单项
104 | - 点击"上移"或"下移"按钮
105 |
106 | 4. **保存配置**:
107 | - 点击"保存"按钮
108 | - 配置会保存为格式化的 JSON 文件
109 |
110 | 5. **应用配置**:
111 | - 将生成的 `MenuConfig.json` 放到右键菜单 DLL 所在目录
112 | - 重新注册 SharpShell 扩展或重启资源管理器
113 |
114 | ## 快捷操作
115 |
116 | - **复制菜单配置**:先创建一个模板项,编辑后可在 JSON 中复制
117 | - **批量编辑**:直接在 JSON 中编辑,然后用此工具验证和调整
118 | - **测试配置**:使用"显示完整路径和命令"选项测试命令是否正确
119 |
120 | ## 注意事项
121 |
122 | 1. 保存前请确保所有必填字段已填写
123 | 2. 文件路径建议使用绝对路径或环境变量
124 | 3. 修改配置后需要重新注册 SharpShell 扩展才能生效
125 | 4. 建议在修改前备份原配置文件
126 |
127 | ## 技术细节
128 |
129 | - **开发框架**:WPF (.NET Framework 4.8)
130 | - **数据绑定**:MVVM 架构
131 | - **JSON 处理**:Newtonsoft.Json 13.0.3
132 | - **配置格式**:与 SharpShell MenuFunctions 项目兼容
133 |
134 | ## 开发者
135 |
136 | 此工具是 SharpShell 右键菜单扩展项目的配套工具,简化了 JSON 配置的编辑过程。
137 |
138 |
--------------------------------------------------------------------------------
/MenuFunctions/测试复选框/Program.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Runtime.InteropServices;
3 | using System.Text;
4 |
5 | namespace WindowTextExtractor
6 | {
7 | public class Program
8 | {
9 | [DllImport("user32.dll", CharSet = CharSet.Auto)]
10 | static extern IntPtr SendMessage(IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam);
11 |
12 | [DllImport("user32.dll", CharSet = CharSet.Auto)]
13 | static extern IntPtr SendMessage(IntPtr hWnd, uint Msg, IntPtr wParam, uint lParam);
14 |
15 | [DllImport("user32.dll")]
16 | [return: MarshalAs(UnmanagedType.Bool)]
17 | static extern bool EnumChildWindows(IntPtr window, EnumWindowProc callback, IntPtr lParam);
18 |
19 | [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
20 | static extern int GetClassName(IntPtr hWnd, StringBuilder lpClassName, int nMaxCount);
21 |
22 | private delegate bool EnumWindowProc(IntPtr hWnd, IntPtr parameter);
23 |
24 | const uint BM_GETCHECK = 0x00F0;
25 | const uint BM_SETCHECK = 0x00F1;
26 | const uint BST_CHECKED = 0x0001;
27 | const uint BST_UNCHECKED = 0x0000;
28 |
29 | public static void Main(string[] args)
30 | {
31 | // 写死的参数
32 | string handle = "205930588";
33 | IntPtr hWnd = new IntPtr(Convert.ToInt32(handle)); // 字符串句柄转成句柄变量
34 |
35 | // 将所有复选框设置为未选中状态
36 | bool result = DisableAllCheckBoxes(hWnd);
37 | if (result)
38 | {
39 | Console.WriteLine("操作成功");
40 | }
41 | else
42 | {
43 | Console.WriteLine("操作失败");
44 | }
45 | Console.ReadLine();
46 | }
47 |
48 | public static bool DisableAllCheckBoxes(IntPtr hWnd)
49 | {
50 | bool operationResult = false;
51 |
52 | EnumWindowProc callback = (childHandle, parameter) =>
53 | {
54 | StringBuilder classText = new StringBuilder(256);
55 | GetClassName(childHandle, classText, classText.Capacity);
56 |
57 | Console.WriteLine($"找到控件,句柄: {childHandle}, 类名: {classText}");
58 |
59 | if (classText.ToString() == "Button" || classText.ToString().Contains("BUTTON"))
60 | {
61 | // 获取当前复选框状态
62 | IntPtr checkState = SendMessage(childHandle, BM_GETCHECK, IntPtr.Zero, IntPtr.Zero);
63 | Console.WriteLine($"找到复选框,当前状态: {checkState}");
64 |
65 | // 设置复选框状态为未选中
66 | if (checkState != (IntPtr)BST_UNCHECKED)
67 | {
68 | SendMessage(childHandle, BM_SETCHECK, (IntPtr)BST_UNCHECKED, IntPtr.Zero);
69 | IntPtr newCheckState = SendMessage(childHandle, BM_GETCHECK, IntPtr.Zero, IntPtr.Zero);
70 | Console.WriteLine($"新状态: {newCheckState}");
71 | operationResult = (newCheckState == (IntPtr)BST_UNCHECKED);
72 | }
73 | }
74 |
75 | return true; // 继续枚举
76 | };
77 |
78 | EnumChildWindows(hWnd, callback, IntPtr.Zero);
79 | return operationResult;
80 | }
81 | }
82 | }
83 |
--------------------------------------------------------------------------------
/MenuFunctions/按键测试2/Program.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Runtime.InteropServices;
3 | using System.Threading.Tasks;
4 | using System.Windows.Forms;
5 | using WindowsInput.Native;
6 | using WindowsInput;
7 |
8 | using System.Diagnostics;
9 |
10 | using System.Threading;
11 |
12 | using System.Text;
13 |
14 |
15 |
16 | public class PushKey
17 | {
18 | static void Main()
19 | {
20 |
21 | //string handle = ProgramRunner.StartProcessAndGetHandle("notepad.exe");
22 | string handle = "4138042";
23 | Console.WriteLine(handle);
24 | //Thread.Sleep(2000); // 稍微延迟,以模拟正常的按键速度
25 | WindowMessageSender.SendStringToWindow(handle, "直接变");
26 |
27 | //WindowMessageSender_ADD.SendStringToWindow(handle, "nihao111你好");
28 | //SendKeys.SendWait("abc");
29 |
30 |
31 |
32 | }
33 | }
34 |
35 |
36 | public class ProgramRunner
37 | {
38 | [DllImport("user32.dll")]
39 | private static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
40 |
41 | public static string StartProcessAndGetHandle(string filePath)
42 | {
43 | Process process = new Process();
44 | process.StartInfo.FileName = filePath;
45 | process.Start();
46 |
47 | process.WaitForInputIdle(); // 等待程序准备好接收用户输入
48 | IntPtr handle = process.MainWindowHandle;
49 |
50 | // 如果 MainWindowHandle 不可用,可以尝试使用 FindWindow 方法
51 | if (handle == IntPtr.Zero)
52 | {
53 | handle = FindWindow(null, process.MainWindowTitle);
54 | }
55 |
56 | return handle.ToString();
57 | }
58 | }
59 |
60 | public class WindowMessageSender
61 | {
62 |
63 | [DllImport("user32.dll", CharSet = CharSet.Unicode)]
64 | private static extern IntPtr SendMessageW(IntPtr hWnd, uint Msg, IntPtr wParam, string lParam);
65 |
66 | private const uint WM_SETTEXT = 0x000C;
67 |
68 | public static void SendStringToWindow(string windowHandle, string message)
69 | {
70 | IntPtr hWnd = new IntPtr(Convert.ToInt32(windowHandle));
71 | SendMessageW(hWnd, WM_SETTEXT, IntPtr.Zero, message);
72 | }
73 |
74 | }
75 |
76 | public class WindowMessageSender_ADD
77 | {
78 | [DllImport("user32.dll", CharSet = CharSet.Unicode)]
79 | private static extern IntPtr SendMessageW(IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam);
80 |
81 |
82 | private const uint WM_CHAR = 0x0102;
83 |
84 | public static void SendStringToWindow(string windowHandle, string message)
85 | {
86 | IntPtr hWnd = new IntPtr(Convert.ToInt32(windowHandle));
87 | foreach (char c in message)
88 | {
89 | SendMessageW(hWnd, WM_CHAR, (IntPtr)c, IntPtr.Zero);
90 | Thread.Sleep(0); // 可以调整这个延迟
91 | }
92 | }
93 | }
94 |
95 |
96 |
97 | public class ScintillaHelper
98 | {
99 | [DllImport("user32.dll", CharSet = CharSet.Unicode)]
100 | private static extern IntPtr SendMessageW(IntPtr hWnd, int Msg, IntPtr wParam, string lParam);
101 |
102 | private const int SCI_SETTEXT = 2181;
103 |
104 | public static void SendStringToScintilla(string windowHandle, string message)
105 | {
106 | IntPtr hWnd = new IntPtr(Convert.ToInt32(windowHandle));
107 | SendMessageW(hWnd, SCI_SETTEXT, IntPtr.Zero, message);
108 | }
109 | }
--------------------------------------------------------------------------------
/MenuFunctions/实现运行效果/实现运行效果.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | AnyCPU
7 | {81868E36-4BFF-43EF-9010-E436789B19EE}
8 | Exe
9 | 实现运行效果
10 | 实现运行效果
11 | v4.8
12 | 512
13 | true
14 | true
15 |
16 |
17 | AnyCPU
18 | true
19 | full
20 | false
21 | bin\Debug\
22 | DEBUG;TRACE
23 | prompt
24 | 4
25 |
26 |
27 | AnyCPU
28 | pdbonly
29 | true
30 | bin\Release\
31 | TRACE
32 | prompt
33 | 4
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 | ..\packages\Toolbox.0.2.2\lib\net40\Toolbox.Extensions.dll
46 |
47 |
48 | ..\packages\Toolbox.0.2.2\lib\net40\Toolbox.Logger.dll
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 | {F935DC20-1CF0-11D0-ADB9-00C04FD58A0B}
63 | 1
64 | 0
65 | 0
66 | tlbimp
67 | False
68 | True
69 |
70 |
71 |
72 |
--------------------------------------------------------------------------------
/MenuFunctions/卸载计算机全部sharpshelldll.ps1:
--------------------------------------------------------------------------------
1 | # 自动提权部分
2 | if (-not ([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)) {
3 | Write-Host "需要管理员权限,正在尝试以管理员身份重新启动..."
4 | Start-Process powershell -ArgumentList "-ExecutionPolicy Bypass -File `"$PSCommandPath`"" -Verb RunAs
5 | exit
6 | }
7 |
8 | Write-Host "==============================="
9 | Write-Host " 正在清理 SharpShell 残留注册项..."
10 | Write-Host "==============================="
11 |
12 | # 自动结束 Explorer
13 | Write-Host ""
14 | Write-Host "正在结束 explorer.exe..."
15 | Get-Process explorer -ErrorAction SilentlyContinue | Stop-Process -Force
16 |
17 | $views = @("Registry64", "Registry32")
18 |
19 | foreach ($view in $views) {
20 | Write-Host ""
21 | Write-Host "[$view] 清理中..."
22 |
23 | # 打开 HKCR\CLSID,找 InprocServer32 指向 mscoree.dll 且带 SharpShell 信息的项
24 | $base = [Microsoft.Win32.RegistryKey]::OpenBaseKey([Microsoft.Win32.RegistryHive]::ClassesRoot, $view)
25 | $clsid = $base.OpenSubKey("CLSID",$true)
26 | if ($clsid -eq $null) {
27 | Write-Host " 未找到 CLSID 节点。"
28 | continue
29 | }
30 |
31 | foreach ($sub in $clsid.GetSubKeyNames()) {
32 | if ($sub -notmatch '^{.*}$') { continue }
33 |
34 | try {
35 | $key = $clsid.OpenSubKey($sub,$false)
36 | if ($null -eq $key) { continue }
37 |
38 | $inproc = $key.OpenSubKey("InprocServer32",$false)
39 | if ($null -ne $inproc) {
40 | $asm = $inproc.GetValue("Assembly")
41 | $code = $inproc.GetValue("CodeBase")
42 |
43 | if (($asm -and $asm -like "*SharpShell*") -or ($code -and $code -like "*SharpShell*")) {
44 | try {
45 | $clsid.DeleteSubKeyTree($sub,$false)
46 | Write-Host " 删除 HKCR\CLSID\$sub"
47 | } catch {
48 | Write-Host (" 删除失败 {0}: {1}" -f $sub, $_.Exception.Message)
49 | }
50 | }
51 | $inproc.Close()
52 | }
53 | $key.Close()
54 | } catch {
55 | Write-Host (" 遍历出错 {0}: {1}" -f $sub, $_.Exception.Message)
56 | }
57 | }
58 | $clsid.Close()
59 | $base.Close()
60 |
61 | # 清理 Approved 列表
62 | Write-Host " 清理 Shell Extensions\Approved..."
63 | $lm = [Microsoft.Win32.RegistryKey]::OpenBaseKey([Microsoft.Win32.RegistryHive]::LocalMachine, $view)
64 | $approved = $lm.OpenSubKey("Software\Microsoft\Windows\CurrentVersion\Shell Extensions\Approved",$true)
65 | if ($approved) {
66 | foreach ($v in $approved.GetValueNames()) {
67 | $val = $approved.GetValue($v)
68 | if ($val -like "*SharpShell*" -or $v -like "*SharpShell*") {
69 | try {
70 | $approved.DeleteValue($v,$false)
71 | Write-Host " 删除 Approved 值:$v"
72 | } catch {
73 | Write-Host (" 删除失败 {0}: {1}" -f $v, $_.Exception.Message)
74 | }
75 | }
76 | }
77 | $approved.Close()
78 | }
79 | $lm.Close()
80 | }
81 |
82 | Write-Host ""
83 | Write-Host "正在重新启动 explorer.exe..."
84 | Start-Process "explorer.exe"
85 |
86 | Write-Host ""
87 | Write-Host "===================================="
88 | Write-Host " SharpShell 清理完成 ✅"
89 | Write-Host " 已自动重启资源管理器。"
90 | Write-Host "===================================="
91 | Start-Sleep -Seconds 3
92 |
--------------------------------------------------------------------------------
/MenuFunctions/测试输入控件/Program.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Runtime.InteropServices;
3 | using System.Text;
4 | using System.Windows.Forms;
5 |
6 | namespace WindowTextExtractor
7 | {
8 | public class Program
9 | {
10 | [DllImport("user32.dll", CharSet = CharSet.Auto)]
11 | static extern bool SendMessageString(IntPtr hWnd, uint Msg, IntPtr wParam, string lParam);
12 |
13 | [DllImport("user32.dll", CharSet = CharSet.Auto)]
14 | static extern IntPtr SendMessage(IntPtr hWnd, uint Msg, IntPtr wParam, StringBuilder lParam);
15 |
16 | [DllImport("user32.dll")]
17 | [return: MarshalAs(UnmanagedType.Bool)]
18 | static extern bool EnumChildWindows(IntPtr window, EnumWindowProc callback, IntPtr lParam);
19 |
20 | [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
21 | static extern int GetClassName(IntPtr hWnd, StringBuilder lpClassName, int nMaxCount);
22 |
23 | private delegate bool EnumWindowProc(IntPtr hWnd, IntPtr parameter);
24 |
25 | const uint WM_SETTEXT = 0x000C;
26 | const uint WM_GETTEXT = 0x000D;
27 | const uint WM_GETTEXTLENGTH = 0x000E;
28 |
29 | public static void Main(string[] args)
30 | {
31 | if (args.Length < 1)
32 | {
33 | Console.WriteLine("Usage: WindowTextExtractor ");
34 | return;
35 | }
36 |
37 | string handle = args[0];
38 | IntPtr hWnd = new IntPtr(Convert.ToInt32(handle)); //字符串句柄转成句柄变量
39 |
40 | //// 示例调用获取控件文本的方法
41 | //string text = GetTextFromWindow(handle, "WindowsForms10.EDIT.app.0.3c3ecb7_r24_ad1", 27);
42 | //Console.WriteLine(text);
43 |
44 | for (int i = 1; i <= 27; i++)
45 | {
46 | //WindowsForms10.EDIT.app.0.1e35270_r24_ad1 这个可能会变化, 去spy++里找到这个编辑框 ,然后获取他的新类名,改到下面这个地方
47 | string text = GetTextFromWindow(handle, "WindowsForms10.EDIT.app.0.1e35270_r32_ad1", i);
48 | if (text!=null && text.StartsWith(".."))
49 | {
50 | Console.WriteLine(text);
51 | break;
52 | }
53 | }
54 | }
55 |
56 |
57 |
58 | public static string GetTextFromWindow(string windowHandle, string className, int instance)
59 | {
60 | IntPtr hWnd = new IntPtr(Convert.ToInt32(windowHandle));
61 | int count = 0;
62 | string windowText = null;
63 |
64 | EnumWindowProc callback = (childHandle, parameter) =>
65 | {
66 | StringBuilder classText = new StringBuilder(256);
67 | GetClassName(childHandle, classText, classText.Capacity);
68 |
69 | if (classText.ToString() == className)
70 | {
71 | if (count == instance)
72 | {
73 | int length = (int)SendMessage(childHandle, WM_GETTEXTLENGTH, IntPtr.Zero, null);
74 | StringBuilder sb = new StringBuilder(length + 1);
75 | SendMessage(childHandle, WM_GETTEXT, (IntPtr)sb.Capacity, sb);
76 | windowText = sb.ToString();
77 | return false; // Stop enumeration
78 | }
79 | count++;
80 | }
81 |
82 | return true; // Continue enumeration
83 | };
84 |
85 | EnumChildWindows(hWnd, callback, IntPtr.Zero);
86 | return windowText;
87 | }
88 | }
89 | }
90 |
--------------------------------------------------------------------------------
/MenuFunctions/MenuFunctions_Panel/快速入门.md:
--------------------------------------------------------------------------------
1 | # 快速入门指南
2 |
3 | ## 第一次使用
4 |
5 | ### 1. 启动程序
6 | 运行 `MenuFunctions_Panel.exe`,程序会自动尝试加载配置文件。
7 |
8 | ### 2. 加载示例配置
9 | 如果自动加载失败,点击工具栏的 **📂 打开** 按钮,选择:
10 | - `示例配置.json` - 查看示例
11 | - 或你的 `MenuConfig.json` 文件
12 |
13 | ### 3. 界面介绍
14 | ```
15 | ┌─────────────────────────────────────────────────┐
16 | │ 📂打开 💾保存 ➕新增 📑添加子项 ➖分隔线 │ ← 工具栏
17 | ├──────────┬──────────────────────────────────────┤
18 | │ │ │
19 | │ 菜单 │ 详细配置面板 │
20 | │ 结构 │ │
21 | │ 树 │ 📌 基本信息 │
22 | │ │ 📍 显示位置 │
23 | │ │ ⚙️ 程序设置 │
24 | │ │ 📄 文件类型过滤 │
25 | │ │ 🔧 高级选项 │
26 | │ │ 💻 CMD 设置 │
27 | └──────────┴──────────────────────────────────────┘
28 | ```
29 |
30 | ## 常见操作
31 |
32 | ### 添加新菜单项
33 |
34 | 1. 点击 **➕ 新增** 按钮
35 | 2. 在右侧面板编辑配置:
36 | - **菜单文本**:输入显示名称,如"用记事本打开"
37 | - **程序路径**:点击"浏览..."选择程序,如 `notepad.exe`
38 | - **图标路径**:选择图标文件(可选)
39 | 3. 设置显示位置(勾选需要的选项)
40 | 4. 点击 **💾 保存**
41 |
42 | ### 创建子菜单
43 |
44 | 1. 在左侧树中选择父菜单项
45 | 2. 点击 **📑 添加子项** 按钮
46 | 3. 编辑子菜单的配置
47 | 4. 重复此过程可创建多级菜单
48 |
49 | ### 调整顺序
50 |
51 | 1. 在左侧树中选择要移动的菜单项
52 | 2. 点击 **⬆️ 上移** 或 **⬇️ 下移** 按钮
53 | 3. 同级菜单项会按 Order 字段排序
54 |
55 | ### 添加分隔线
56 |
57 | 点击 **➖ 分隔线** 按钮即可添加一个菜单分隔线。
58 |
59 | ### 删除菜单项
60 |
61 | 1. 选择要删除的菜单项
62 | 2. 点击 **🗑️ 删除** 按钮
63 | 3. 确认删除
64 |
65 | ## 实用技巧
66 |
67 | ### 💡 技巧 1:复制路径到剪贴板
68 |
69 | ```json
70 | {
71 | "Text": "复制路径",
72 | "ProgramPath": "copypath",
73 | "ShowInRootMenu": true
74 | }
75 | ```
76 |
77 | - **ProgramPath** 设为 `copypath`(预设命令)
78 | - 勾选"显示在根菜单"可直接显示在右键菜单顶层
79 |
80 | ### 💡 技巧 2:用特定程序打开文件
81 |
82 | ```json
83 | {
84 | "Text": "用记事本打开",
85 | "ProgramPath": "notepad.exe",
86 | "FileTypes": [".txt", ".log", ".ini"],
87 | "ShowOnFiles": true,
88 | "ShowOnFolderBackground": false
89 | }
90 | ```
91 |
92 | - 指定文件类型,只在 .txt/.log/.ini 文件上显示
93 | - 不在文件夹背景显示
94 |
95 | ### 💡 技巧 3:在当前文件夹打开 CMD
96 |
97 | ```json
98 | {
99 | "Text": "在此处打开命令窗口",
100 | "ProgramPath": "cmd.exe",
101 | "ShowOnFolderBackground": true,
102 | "ShowOnFolder": true,
103 | "ShowOnFiles": false
104 | }
105 | ```
106 |
107 | - 只在文件夹和文件夹背景显示
108 | - 不在文件上显示
109 |
110 | ### 💡 技巧 4:执行批处理脚本
111 |
112 | ```json
113 | {
114 | "Text": "运行清理脚本",
115 | "ProgramPath": "C:\\Scripts\\cleanup.bat",
116 | "RunningProgramWithCMD": true,
117 | "HideCmdWindow": true,
118 | "ShowOnFolderBackground": true
119 | }
120 | ```
121 |
122 | - 通过 CMD 运行批处理
123 | - 隐藏 CMD 窗口,后台执行
124 |
125 | ### 💡 技巧 5:使用动态变量
126 |
127 | ```json
128 | {
129 | "Text": "重命名 ${filename}",
130 | "ProgramPath": "MyRenamer.exe"
131 | }
132 | ```
133 |
134 | 菜单文本会动态显示为"重命名 文件名"。
135 |
136 | 支持的变量:
137 | - `${filename}` - 文件名(无扩展名)
138 | - `${extension}` - 扩展名
139 | - `${fullpath}` - 完整路径
140 | - `${parentdir}` - 父目录
141 |
142 | ## 配置检查清单
143 |
144 | 保存前请确认:
145 |
146 | - ✅ 菜单文本已填写
147 | - ✅ 程序路径正确(或使用预设命令)
148 | - ✅ 显示位置至少勾选一项
149 | - ✅ 如果有文件类型限制,格式正确(如 `.txt`)
150 | - ✅ 图标路径正确(可选)
151 |
152 | ## 应用配置
153 |
154 | 1. 保存 `MenuConfig.json` 到:
155 | ```
156 | MenuFunctions\bin\Release\MenuConfig.json
157 | ```
158 |
159 | 2. 如果是新配置,需要重新注册 SharpShell:
160 | ```powershell
161 | # 注册(管理员权限)
162 | regasm /codebase MenuFunctions.dll
163 | srm install MenuFunctions.dll
164 | ```
165 |
166 | 3. 如果只是修改配置,重启资源管理器即可:
167 | ```powershell
168 | # 重启资源管理器
169 | taskkill /f /im explorer.exe
170 | start explorer.exe
171 | ```
172 |
173 | ## 故障排除
174 |
175 | ### 问题:无法加载配置文件
176 | - 检查文件是否为有效的 JSON 格式
177 | - 使用 JSON 验证工具检查语法
178 |
179 | ### 问题:修改后不生效
180 | - 确保配置文件保存在正确位置
181 | - 重启资源管理器
182 | - 检查 DLL 是否正确注册
183 |
184 | ### 问题:菜单项不显示
185 | - 检查"是否可见"选项是否勾选
186 | - 检查显示位置设置是否正确
187 | - 检查文件类型过滤是否过于严格
188 |
189 | ## 下一步
190 |
191 | - 📖 阅读完整的 [README.md](README.md) 了解所有功能
192 | - 🔧 参考 [示例配置.json](示例配置.json) 学习更多配置方式
193 | - 💻 查看主项目的 MenuFunctions.cs 了解实现细节
194 |
195 | 祝使用愉快! 🎉
196 |
197 |
--------------------------------------------------------------------------------
/MenuFunctions/MenuFunctions.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio Version 17
4 | VisualStudioVersion = 17.7.34202.233
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MenuFunctions", "MenuFunctions\MenuFunctions.csproj", "{E117FBC0-7AB4-4C15-A4A9-646E97854821}"
7 | EndProject
8 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "实现运行效果", "实现运行效果\实现运行效果.csproj", "{81868E36-4BFF-43EF-9010-E436789B19EE}"
9 | EndProject
10 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "测试", "测试\测试.csproj", "{4E0DA51C-ECE6-40D6-A199-C2BEB44E8B15}"
11 | EndProject
12 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "按键测试", "按键测试\按键测试.csproj", "{AB5C5856-CD60-4994-B75F-01542D99F05D}"
13 | EndProject
14 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "按键测试2", "按键测试2\按键测试2.csproj", "{0CCAD1A0-93F4-468F-A1E2-03E3C6C1BC08}"
15 | EndProject
16 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "测试输入控件", "测试输入控件\测试输入控件.csproj", "{91648DF0-52EF-499C-B21E-FC312BE51449}"
17 | EndProject
18 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "测试复选框", "测试复选框\测试复选框.csproj", "{436A0C07-A5A9-49A0-82EF-13FD9817CE6A}"
19 | EndProject
20 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MenuFunctions_Panel", "MenuFunctions_Panel\MenuFunctions_Panel.csproj", "{6E33F453-89DB-4A0B-8D6E-DBB7CA31BBC3}"
21 | EndProject
22 | Global
23 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
24 | Debug|Any CPU = Debug|Any CPU
25 | Release|Any CPU = Release|Any CPU
26 | EndGlobalSection
27 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
28 | {E117FBC0-7AB4-4C15-A4A9-646E97854821}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
29 | {E117FBC0-7AB4-4C15-A4A9-646E97854821}.Debug|Any CPU.Build.0 = Debug|Any CPU
30 | {E117FBC0-7AB4-4C15-A4A9-646E97854821}.Release|Any CPU.ActiveCfg = Release|Any CPU
31 | {E117FBC0-7AB4-4C15-A4A9-646E97854821}.Release|Any CPU.Build.0 = Release|Any CPU
32 | {81868E36-4BFF-43EF-9010-E436789B19EE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
33 | {81868E36-4BFF-43EF-9010-E436789B19EE}.Debug|Any CPU.Build.0 = Debug|Any CPU
34 | {81868E36-4BFF-43EF-9010-E436789B19EE}.Release|Any CPU.ActiveCfg = Release|Any CPU
35 | {81868E36-4BFF-43EF-9010-E436789B19EE}.Release|Any CPU.Build.0 = Release|Any CPU
36 | {4E0DA51C-ECE6-40D6-A199-C2BEB44E8B15}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
37 | {4E0DA51C-ECE6-40D6-A199-C2BEB44E8B15}.Debug|Any CPU.Build.0 = Debug|Any CPU
38 | {4E0DA51C-ECE6-40D6-A199-C2BEB44E8B15}.Release|Any CPU.ActiveCfg = Release|Any CPU
39 | {4E0DA51C-ECE6-40D6-A199-C2BEB44E8B15}.Release|Any CPU.Build.0 = Release|Any CPU
40 | {AB5C5856-CD60-4994-B75F-01542D99F05D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
41 | {AB5C5856-CD60-4994-B75F-01542D99F05D}.Debug|Any CPU.Build.0 = Debug|Any CPU
42 | {AB5C5856-CD60-4994-B75F-01542D99F05D}.Release|Any CPU.ActiveCfg = Release|Any CPU
43 | {AB5C5856-CD60-4994-B75F-01542D99F05D}.Release|Any CPU.Build.0 = Release|Any CPU
44 | {0CCAD1A0-93F4-468F-A1E2-03E3C6C1BC08}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
45 | {0CCAD1A0-93F4-468F-A1E2-03E3C6C1BC08}.Debug|Any CPU.Build.0 = Debug|Any CPU
46 | {0CCAD1A0-93F4-468F-A1E2-03E3C6C1BC08}.Release|Any CPU.ActiveCfg = Release|Any CPU
47 | {0CCAD1A0-93F4-468F-A1E2-03E3C6C1BC08}.Release|Any CPU.Build.0 = Release|Any CPU
48 | {91648DF0-52EF-499C-B21E-FC312BE51449}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
49 | {91648DF0-52EF-499C-B21E-FC312BE51449}.Debug|Any CPU.Build.0 = Debug|Any CPU
50 | {91648DF0-52EF-499C-B21E-FC312BE51449}.Release|Any CPU.ActiveCfg = Release|Any CPU
51 | {91648DF0-52EF-499C-B21E-FC312BE51449}.Release|Any CPU.Build.0 = Release|Any CPU
52 | {436A0C07-A5A9-49A0-82EF-13FD9817CE6A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
53 | {436A0C07-A5A9-49A0-82EF-13FD9817CE6A}.Debug|Any CPU.Build.0 = Debug|Any CPU
54 | {436A0C07-A5A9-49A0-82EF-13FD9817CE6A}.Release|Any CPU.ActiveCfg = Release|Any CPU
55 | {436A0C07-A5A9-49A0-82EF-13FD9817CE6A}.Release|Any CPU.Build.0 = Release|Any CPU
56 | {6E33F453-89DB-4A0B-8D6E-DBB7CA31BBC3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
57 | {6E33F453-89DB-4A0B-8D6E-DBB7CA31BBC3}.Debug|Any CPU.Build.0 = Debug|Any CPU
58 | {6E33F453-89DB-4A0B-8D6E-DBB7CA31BBC3}.Release|Any CPU.ActiveCfg = Release|Any CPU
59 | {6E33F453-89DB-4A0B-8D6E-DBB7CA31BBC3}.Release|Any CPU.Build.0 = Release|Any CPU
60 | EndGlobalSection
61 | GlobalSection(SolutionProperties) = preSolution
62 | HideSolutionNode = FALSE
63 | EndGlobalSection
64 | GlobalSection(ExtensibilityGlobals) = postSolution
65 | SolutionGuid = {F8BAF846-176F-4FD5-B99A-B131DB174BF3}
66 | EndGlobalSection
67 | EndGlobal
68 |
--------------------------------------------------------------------------------
/MenuFunctions/MenuFunctions_Panel/示例配置.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "Text": "复制路径",
4 | "Command": "",
5 | "ProgramPath": "copypath",
6 | "SubItems": [],
7 | "FileTypes": [],
8 | "ShowInRootMenu": true,
9 | "IconPath": "shell32.dll",
10 | "IsVisible": true,
11 | "ShowOnFiles": true,
12 | "AppendCommandToEachPath": true,
13 | "ShowOnFolderBackground": true,
14 | "ShowOnFolder": true,
15 | "OnlyUsingProgram": false,
16 | "RunningProgramWithCMD": false,
17 | "HideCmdWindow": false,
18 | "KeepCmdWindows": false,
19 | "IsSeparator": false,
20 | "DisplayCompletePathAndCommand": false,
21 | "UseQuotes": true,
22 | "Order": 0,
23 | "AddFileTypeParameter": false
24 | },
25 | {
26 | "Text": "用记事本打开",
27 | "Command": "",
28 | "ProgramPath": "notepad.exe",
29 | "SubItems": [],
30 | "FileTypes": [
31 | ".txt",
32 | ".log",
33 | ".ini",
34 | ".cfg"
35 | ],
36 | "ShowInRootMenu": false,
37 | "IconPath": "notepad.exe",
38 | "IsVisible": true,
39 | "ShowOnFiles": true,
40 | "AppendCommandToEachPath": false,
41 | "ShowOnFolderBackground": false,
42 | "ShowOnFolder": false,
43 | "OnlyUsingProgram": false,
44 | "RunningProgramWithCMD": false,
45 | "HideCmdWindow": false,
46 | "KeepCmdWindows": false,
47 | "IsSeparator": false,
48 | "DisplayCompletePathAndCommand": false,
49 | "UseQuotes": true,
50 | "Order": 1,
51 | "AddFileTypeParameter": false
52 | },
53 | {
54 | "Text": "文件操作",
55 | "Command": "",
56 | "ProgramPath": "",
57 | "SubItems": [
58 | {
59 | "Text": "打开文件位置",
60 | "Command": "",
61 | "ProgramPath": "openfolderandselectitems",
62 | "SubItems": [],
63 | "FileTypes": [],
64 | "ShowInRootMenu": false,
65 | "IconPath": "",
66 | "IsVisible": true,
67 | "ShowOnFiles": true,
68 | "AppendCommandToEachPath": true,
69 | "ShowOnFolderBackground": false,
70 | "ShowOnFolder": false,
71 | "OnlyUsingProgram": false,
72 | "RunningProgramWithCMD": false,
73 | "HideCmdWindow": false,
74 | "KeepCmdWindows": false,
75 | "IsSeparator": false,
76 | "DisplayCompletePathAndCommand": false,
77 | "UseQuotes": false,
78 | "Order": 0,
79 | "AddFileTypeParameter": false
80 | },
81 | {
82 | "Text": "分隔线",
83 | "Command": "",
84 | "ProgramPath": "",
85 | "SubItems": [],
86 | "FileTypes": [],
87 | "ShowInRootMenu": false,
88 | "IconPath": "",
89 | "IsVisible": true,
90 | "ShowOnFiles": true,
91 | "AppendCommandToEachPath": true,
92 | "ShowOnFolderBackground": true,
93 | "ShowOnFolder": true,
94 | "OnlyUsingProgram": false,
95 | "RunningProgramWithCMD": false,
96 | "HideCmdWindow": false,
97 | "KeepCmdWindows": false,
98 | "IsSeparator": true,
99 | "DisplayCompletePathAndCommand": false,
100 | "UseQuotes": true,
101 | "Order": 1,
102 | "AddFileTypeParameter": false
103 | },
104 | {
105 | "Text": "在命令行中打开",
106 | "Command": "",
107 | "ProgramPath": "cmd.exe",
108 | "SubItems": [],
109 | "FileTypes": [],
110 | "ShowInRootMenu": false,
111 | "IconPath": "cmd.exe",
112 | "IsVisible": true,
113 | "ShowOnFiles": false,
114 | "AppendCommandToEachPath": false,
115 | "ShowOnFolderBackground": true,
116 | "ShowOnFolder": true,
117 | "OnlyUsingProgram": false,
118 | "RunningProgramWithCMD": false,
119 | "HideCmdWindow": false,
120 | "KeepCmdWindows": false,
121 | "IsSeparator": false,
122 | "DisplayCompletePathAndCommand": false,
123 | "UseQuotes": true,
124 | "Order": 2,
125 | "AddFileTypeParameter": false
126 | }
127 | ],
128 | "FileTypes": [],
129 | "ShowInRootMenu": false,
130 | "IconPath": "",
131 | "IsVisible": true,
132 | "ShowOnFiles": true,
133 | "AppendCommandToEachPath": true,
134 | "ShowOnFolderBackground": true,
135 | "ShowOnFolder": true,
136 | "OnlyUsingProgram": false,
137 | "RunningProgramWithCMD": false,
138 | "HideCmdWindow": false,
139 | "KeepCmdWindows": false,
140 | "IsSeparator": false,
141 | "DisplayCompletePathAndCommand": false,
142 | "UseQuotes": true,
143 | "Order": 2,
144 | "AddFileTypeParameter": false
145 | }
146 | ]
147 |
148 |
--------------------------------------------------------------------------------
/MenuFunctions/MenuFunctions_Panel/MenuFunctions_Panel.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | AnyCPU
7 | {6E33F453-89DB-4A0B-8D6E-DBB7CA31BBC3}
8 | WinExe
9 | MenuFunctions_Panel
10 | MenuFunctions_Panel
11 | v4.8
12 | 512
13 | {60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}
14 | 4
15 | true
16 | true
17 |
18 |
19 | AnyCPU
20 | true
21 | full
22 | false
23 | bin\Debug\
24 | DEBUG;TRACE
25 | prompt
26 | 4
27 |
28 |
29 | AnyCPU
30 | pdbonly
31 | true
32 | bin\Release\
33 | TRACE
34 | prompt
35 | 4
36 |
37 |
38 |
39 | ..\packages\Newtonsoft.Json.13.0.3\lib\net45\Newtonsoft.Json.dll
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 | 4.0
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 | MSBuild:Compile
59 |
60 |
61 | MSBuild:Compile
62 | Designer
63 |
64 |
65 | App.xaml
66 | Code
67 |
68 |
69 | MainWindow.xaml
70 | Code
71 |
72 |
73 |
74 |
75 |
76 |
77 | Code
78 |
79 |
80 | True
81 | True
82 | Resources.resx
83 |
84 |
85 | True
86 | Settings.settings
87 | True
88 |
89 |
90 | ResXFileCodeGenerator
91 | Resources.Designer.cs
92 |
93 |
94 |
95 | SettingsSingleFileGenerator
96 | Settings.Designer.cs
97 |
98 |
99 |
100 |
101 |
102 |
103 |
--------------------------------------------------------------------------------
/MenuFunctions/MenuFunctions/MenuFunctions.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | AnyCPU
7 | {E117FBC0-7AB4-4C15-A4A9-646E97854821}
8 | Library
9 | Properties
10 | MenuFunctions
11 | MenuFunctions
12 | v4.8
13 | 512
14 |
15 |
16 |
17 | true
18 | full
19 | false
20 | bin\Debug\
21 | DEBUG;TRACE
22 | prompt
23 | 4
24 |
25 |
26 | pdbonly
27 | true
28 | bin\Release\
29 | TRACE
30 | prompt
31 | 4
32 |
33 |
34 | true
35 |
36 |
37 | key.snk
38 |
39 |
40 |
41 | ..\packages\Newtonsoft.Json.13.0.3\lib\net45\Newtonsoft.Json.dll
42 |
43 |
44 | ..\packages\SharpShell.2.7.2\lib\net40-client\SharpShell.dll
45 | True
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 | True
65 | True
66 | Resources.resx
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 | ResXFileCodeGenerator
76 | Resources.Designer.cs
77 |
78 |
79 |
80 |
81 | {F935DC20-1CF0-11D0-ADB9-00C04FD58A0B}
82 | 1
83 | 0
84 | 0
85 | tlbimp
86 | False
87 | True
88 |
89 |
90 | {EAB22AC0-30C1-11CF-A7EB-0000C05BAE0B}
91 | 1
92 | 1
93 | 0
94 | tlbimp
95 | False
96 | True
97 |
98 |
99 |
100 |
101 |
102 |
103 |
110 |
--------------------------------------------------------------------------------
/MenuFunctions/实现运行效果/ExplorerHelper.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Diagnostics;
4 | using System.IO;
5 | using System.Linq;
6 | using System.Runtime.InteropServices;
7 | using System.Text;
8 | using System.Threading.Tasks;
9 |
10 | namespace 实现运行效果
11 | {
12 | internal class ExplorerHelper
13 | {
14 |
15 | [DllImport("shell32.dll", CharSet = CharSet.Auto)]
16 | static extern bool ShellExecuteEx(ref SHELLEXECUTEINFO lpExecInfo);
17 |
18 | [DllImport("shell32.dll")]
19 | static extern int SHOpenFolderAndSelectItems(IntPtr pidlFolder, uint cidl, IntPtr apidl, uint dwFlags);
20 |
21 | [DllImport("shell32.dll")]
22 | static extern int SHParseDisplayName([MarshalAs(UnmanagedType.LPWStr)] string name, IntPtr bindingContext, out IntPtr pidl, uint sfgaoIn, out uint psfgaoOut);
23 |
24 | [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
25 | public struct SHELLEXECUTEINFO
26 | {
27 | public int cbSize;
28 | public uint fMask;
29 | public IntPtr hwnd;
30 | [MarshalAs(UnmanagedType.LPTStr)]
31 | public string lpVerb;
32 | [MarshalAs(UnmanagedType.LPTStr)]
33 | public string lpFile;
34 | [MarshalAs(UnmanagedType.LPTStr)]
35 | public string lpParameters;
36 | [MarshalAs(UnmanagedType.LPTStr)]
37 | public string lpDirectory;
38 | public int nShow;
39 | public IntPtr hInstApp;
40 | public IntPtr lpIDList;
41 | [MarshalAs(UnmanagedType.LPTStr)]
42 | public string lpClass;
43 | public IntPtr hkeyClass;
44 | public uint dwHotKey;
45 | public IntPtr hIcon;
46 | public IntPtr hProcess;
47 | }
48 |
49 | private const int SW_SHOW = 5;
50 |
51 | // 打开文件夹并选择文件
52 | public static void OpenFolderAndSelectItem(string filePath)
53 | {
54 | IntPtr pidl = IntPtr.Zero;
55 | SHParseDisplayName(filePath, IntPtr.Zero, out pidl, 0, out _);
56 | if (pidl != IntPtr.Zero)
57 | {
58 | SHOpenFolderAndSelectItems(pidl, 0, IntPtr.Zero, 0);
59 | Marshal.FreeCoTaskMem(pidl);
60 | }
61 | }
62 |
63 | // 打开文件夹
64 | public static void OpenFolder(string folderPath)
65 | {
66 | SHELLEXECUTEINFO sei = new SHELLEXECUTEINFO
67 | {
68 | cbSize = Marshal.SizeOf(typeof(SHELLEXECUTEINFO)),
69 | lpVerb = "open",
70 | lpFile = folderPath,
71 | nShow = SW_SHOW
72 | };
73 | ShellExecuteEx(ref sei);
74 | }
75 |
76 | // 打开项目,可以是文件夹、可执行文件、URL或其他文件类型
77 | public static void OpenItem(string path)
78 | {
79 |
80 |
81 | // 只取第一行作为路径
82 | path = path.Split(new[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries).FirstOrDefault();
83 |
84 | if (string.IsNullOrEmpty(path))
85 | {
86 | throw new ArgumentException("提供的路径无效或为空。");
87 | }
88 |
89 | // 验证路径是否合法
90 | string extension = string.Empty;
91 | try
92 | {
93 | extension = Path.GetExtension(path);
94 | }
95 | catch (ArgumentException ex)
96 | {
97 | // 如果获取扩展名时出现异常,打印出错的路径并继续执行
98 | Console.WriteLine($"获取扩展名时出错。传入的路径为: {path}。错误信息: {ex.Message}");
99 | return; // 由于无法获取扩展名,此处选择退出方法
100 | }
101 |
102 |
103 |
104 | // 如果没有扩展名,我们假定它是一个文件夹
105 | if (string.IsNullOrEmpty(extension))
106 | {
107 | OpenFolder(path);
108 | }
109 | else if (File.Exists(path)) // 如果路径指向一个文件
110 | {
111 | extension = extension.ToLowerInvariant();
112 |
113 | switch (extension)
114 | {
115 | case ".exe":
116 | // 如果是可执行文件,启动该应用程序
117 | Process.Start(path);
118 | break;
119 | case ".url":
120 | // 如果是URL文件,用默认浏览器打开它
121 | Process.Start(path);
122 | break;
123 | default:
124 | // 对于其他文件类型,使用默认程序打开
125 | // 对于其他文件类型,使用默认程序打开
126 | var sei = new SHELLEXECUTEINFO
127 | {
128 | cbSize = Marshal.SizeOf(typeof(SHELLEXECUTEINFO)),
129 | lpVerb = "open",
130 | lpFile = path,
131 | nShow = SW_SHOW
132 | };
133 | ShellExecuteEx(ref sei); // 注意这里使用了 ref 关键字
134 |
135 | break;
136 | }
137 | }
138 | else
139 | {
140 | // 如果文件不存在或不被识别,显示“打开方式”对话框
141 | // 对于其他文件类型,使用默认程序打开
142 | var sei = new SHELLEXECUTEINFO
143 | {
144 | cbSize = Marshal.SizeOf(typeof(SHELLEXECUTEINFO)),
145 | lpVerb = "open",
146 | lpFile = path,
147 | nShow = SW_SHOW
148 | };
149 | ShellExecuteEx(ref sei); // 注意这里使用了 ref 关键字
150 |
151 | }
152 | }
153 | }
154 | }
155 |
156 |
--------------------------------------------------------------------------------
/MenuFunctions/测试/ExplorerHelper.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Diagnostics;
4 | using System.IO;
5 | using System.Linq;
6 | using System.Runtime.InteropServices;
7 | using System.Text;
8 | using System.Threading.Tasks;
9 |
10 |
11 |
12 |
13 | namespace 测试
14 | {
15 | public class ExplorerHelper
16 | {
17 |
18 | [DllImport("shell32.dll", CharSet = CharSet.Auto)]
19 | static extern bool ShellExecuteEx(ref SHELLEXECUTEINFO lpExecInfo);
20 |
21 | [DllImport("shell32.dll")]
22 | static extern int SHOpenFolderAndSelectItems(IntPtr pidlFolder, uint cidl, IntPtr apidl, uint dwFlags);
23 |
24 | [DllImport("shell32.dll")]
25 | static extern int SHParseDisplayName([MarshalAs(UnmanagedType.LPWStr)] string name, IntPtr bindingContext, out IntPtr pidl, uint sfgaoIn, out uint psfgaoOut);
26 |
27 | [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
28 | public struct SHELLEXECUTEINFO
29 | {
30 | public int cbSize;
31 | public uint fMask;
32 | public IntPtr hwnd;
33 | [MarshalAs(UnmanagedType.LPTStr)]
34 | public string lpVerb;
35 | [MarshalAs(UnmanagedType.LPTStr)]
36 | public string lpFile;
37 | [MarshalAs(UnmanagedType.LPTStr)]
38 | public string lpParameters;
39 | [MarshalAs(UnmanagedType.LPTStr)]
40 | public string lpDirectory;
41 | public int nShow;
42 | public IntPtr hInstApp;
43 | public IntPtr lpIDList;
44 | [MarshalAs(UnmanagedType.LPTStr)]
45 | public string lpClass;
46 | public IntPtr hkeyClass;
47 | public uint dwHotKey;
48 | public IntPtr hIcon;
49 | public IntPtr hProcess;
50 | }
51 |
52 | private const int SW_SHOW = 5;
53 |
54 | // 打开文件夹并选择文件
55 | public static void OpenFolderAndSelectItem(string filePath)
56 | {
57 | IntPtr pidl = IntPtr.Zero;
58 | SHParseDisplayName(filePath, IntPtr.Zero, out pidl, 0, out _);
59 | if (pidl != IntPtr.Zero)
60 | {
61 | SHOpenFolderAndSelectItems(pidl, 0, IntPtr.Zero, 0);
62 | Marshal.FreeCoTaskMem(pidl);
63 | }
64 | }
65 |
66 | // 打开文件夹
67 | public static void OpenFolder(string folderPath)
68 | {
69 | SHELLEXECUTEINFO sei = new SHELLEXECUTEINFO
70 | {
71 | cbSize = Marshal.SizeOf(typeof(SHELLEXECUTEINFO)),
72 | lpVerb = "open",
73 | lpFile = folderPath,
74 | nShow = SW_SHOW
75 | };
76 | ShellExecuteEx(ref sei);
77 | }
78 |
79 | // 打开项目,可以是文件夹、可执行文件、URL或其他文件类型
80 | public static void OpenItem(string path)
81 | {
82 |
83 |
84 | // 只取第一行作为路径
85 | path = path.Split(new[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries).FirstOrDefault();
86 |
87 | if (string.IsNullOrEmpty(path))
88 | {
89 | throw new ArgumentException("提供的路径无效或为空。");
90 | }
91 |
92 | // 验证路径是否合法
93 | string extension = string.Empty;
94 | try
95 | {
96 | extension = Path.GetExtension(path);
97 | }
98 | catch (ArgumentException ex)
99 | {
100 | // 如果获取扩展名时出现异常,打印出错的路径并继续执行
101 | Console.WriteLine($"获取扩展名时出错。传入的路径为: {path}。错误信息: {ex.Message}");
102 | return; // 由于无法获取扩展名,此处选择退出方法
103 | }
104 |
105 |
106 |
107 | // 如果没有扩展名,我们假定它是一个文件夹
108 | if (string.IsNullOrEmpty(extension))
109 | {
110 | OpenFolder(path);
111 | }
112 | else if (File.Exists(path)) // 如果路径指向一个文件
113 | {
114 | extension = extension.ToLowerInvariant();
115 |
116 | switch (extension)
117 | {
118 | case ".exe":
119 | // 如果是可执行文件,启动该应用程序
120 | Process.Start(path);
121 | break;
122 | case ".url":
123 | // 如果是URL文件,用默认浏览器打开它
124 | Process.Start(path);
125 | break;
126 | default:
127 | // 对于其他文件类型,使用默认程序打开
128 | // 对于其他文件类型,使用默认程序打开
129 | var sei = new SHELLEXECUTEINFO
130 | {
131 | cbSize = Marshal.SizeOf(typeof(SHELLEXECUTEINFO)),
132 | lpVerb = "open",
133 | lpFile = path,
134 | nShow = SW_SHOW
135 | };
136 | ShellExecuteEx(ref sei); // 注意这里使用了 ref 关键字
137 |
138 | break;
139 | }
140 | }
141 | else
142 | {
143 | // 如果文件不存在或不被识别,显示“打开方式”对话框
144 | // 对于其他文件类型,使用默认程序打开
145 | var sei = new SHELLEXECUTEINFO
146 | {
147 | cbSize = Marshal.SizeOf(typeof(SHELLEXECUTEINFO)),
148 | lpVerb = "open",
149 | lpFile = path,
150 | nShow = SW_SHOW
151 | };
152 | ShellExecuteEx(ref sei); // 注意这里使用了 ref 关键字
153 |
154 | }
155 | }
156 | }
157 | }
158 |
159 |
--------------------------------------------------------------------------------
/MenuFunctions/MenuFunctions/ExplorerHelper.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Diagnostics;
4 | using System.IO;
5 | using System.Linq;
6 | using System.Runtime.InteropServices;
7 | using System.Text;
8 | using System.Threading.Tasks;
9 |
10 |
11 |
12 |
13 | namespace MenuFunctions
14 | {
15 | public class ExplorerHelper
16 | {
17 |
18 | [DllImport("shell32.dll", CharSet = CharSet.Auto)]
19 | static extern bool ShellExecuteEx(ref SHELLEXECUTEINFO lpExecInfo);
20 |
21 | [DllImport("shell32.dll")]
22 | static extern int SHOpenFolderAndSelectItems(IntPtr pidlFolder, uint cidl, IntPtr apidl, uint dwFlags);
23 |
24 | [DllImport("shell32.dll")]
25 | static extern int SHParseDisplayName([MarshalAs(UnmanagedType.LPWStr)] string name, IntPtr bindingContext, out IntPtr pidl, uint sfgaoIn, out uint psfgaoOut);
26 |
27 | [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
28 | public struct SHELLEXECUTEINFO
29 | {
30 | public int cbSize;
31 | public uint fMask;
32 | public IntPtr hwnd;
33 | [MarshalAs(UnmanagedType.LPTStr)]
34 | public string lpVerb;
35 | [MarshalAs(UnmanagedType.LPTStr)]
36 | public string lpFile;
37 | [MarshalAs(UnmanagedType.LPTStr)]
38 | public string lpParameters;
39 | [MarshalAs(UnmanagedType.LPTStr)]
40 | public string lpDirectory;
41 | public int nShow;
42 | public IntPtr hInstApp;
43 | public IntPtr lpIDList;
44 | [MarshalAs(UnmanagedType.LPTStr)]
45 | public string lpClass;
46 | public IntPtr hkeyClass;
47 | public uint dwHotKey;
48 | public IntPtr hIcon;
49 | public IntPtr hProcess;
50 | }
51 |
52 | private const int SW_SHOW = 5;
53 |
54 | // 打开文件夹并选择文件
55 | public static void OpenFolderAndSelectItem(string filePath)
56 | {
57 | IntPtr pidl = IntPtr.Zero;
58 | SHParseDisplayName(filePath, IntPtr.Zero, out pidl, 0, out _);
59 | if (pidl != IntPtr.Zero)
60 | {
61 | SHOpenFolderAndSelectItems(pidl, 0, IntPtr.Zero, 0);
62 | Marshal.FreeCoTaskMem(pidl);
63 | }
64 | }
65 |
66 | // 打开文件夹
67 | public static void OpenFolder(string folderPath)
68 | {
69 | SHELLEXECUTEINFO sei = new SHELLEXECUTEINFO
70 | {
71 | cbSize = Marshal.SizeOf(typeof(SHELLEXECUTEINFO)),
72 | lpVerb = "open",
73 | lpFile = folderPath,
74 | nShow = SW_SHOW
75 | };
76 | ShellExecuteEx(ref sei);
77 | }
78 |
79 | // 打开项目,可以是文件夹、可执行文件、URL或其他文件类型
80 | public static void OpenItem(string path)
81 | {
82 |
83 |
84 | // 只取第一行作为路径
85 | path = path.Split(new[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries).FirstOrDefault();
86 |
87 | if (string.IsNullOrEmpty(path))
88 | {
89 | throw new ArgumentException("提供的路径无效或为空。");
90 | }
91 |
92 | // 验证路径是否合法
93 | string extension = string.Empty;
94 | try
95 | {
96 | extension = Path.GetExtension(path);
97 | }
98 | catch (ArgumentException ex)
99 | {
100 | // 如果获取扩展名时出现异常,打印出错的路径并继续执行
101 | Console.WriteLine($"获取扩展名时出错。传入的路径为: {path}。错误信息: {ex.Message}");
102 | return; // 由于无法获取扩展名,此处选择退出方法
103 | }
104 |
105 |
106 |
107 | // 如果没有扩展名,我们假定它是一个文件夹
108 | if (string.IsNullOrEmpty(extension))
109 | {
110 | OpenFolder(path);
111 | }
112 | else if (File.Exists(path)) // 如果路径指向一个文件
113 | {
114 | extension = extension.ToLowerInvariant();
115 |
116 | switch (extension)
117 | {
118 | case ".exe":
119 | // 如果是可执行文件,启动该应用程序
120 | Process.Start(path);
121 | break;
122 | case ".url":
123 | // 如果是URL文件,用默认浏览器打开它
124 | Process.Start(path);
125 | break;
126 | default:
127 | // 对于其他文件类型,使用默认程序打开
128 | // 对于其他文件类型,使用默认程序打开
129 | var sei = new SHELLEXECUTEINFO
130 | {
131 | cbSize = Marshal.SizeOf(typeof(SHELLEXECUTEINFO)),
132 | lpVerb = "open",
133 | lpFile = path,
134 | nShow = SW_SHOW
135 | };
136 | ShellExecuteEx(ref sei); // 注意这里使用了 ref 关键字
137 |
138 | break;
139 | }
140 | }
141 | else
142 | {
143 | // 如果文件不存在或不被识别,显示“打开方式”对话框
144 | // 对于其他文件类型,使用默认程序打开
145 | var sei = new SHELLEXECUTEINFO
146 | {
147 | cbSize = Marshal.SizeOf(typeof(SHELLEXECUTEINFO)),
148 | lpVerb = "open",
149 | lpFile = path,
150 | nShow = SW_SHOW
151 | };
152 | ShellExecuteEx(ref sei); // 注意这里使用了 ref 关键字
153 |
154 | }
155 | }
156 | }
157 | }
158 |
159 |
--------------------------------------------------------------------------------
/MenuFunctions/MenuFunctions_Panel/Models/MenuItemConfig.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Collections.ObjectModel;
4 | using System.ComponentModel;
5 | using System.Runtime.CompilerServices;
6 |
7 | namespace MenuFunctions_Panel.Models
8 | {
9 | ///
10 | /// 菜单项配置类,对应 JSON 配置文件的数据结构
11 | ///
12 | public class MenuItemConfig : INotifyPropertyChanged
13 | {
14 | private string _text;
15 | private string _command;
16 | private string _programPath;
17 | private ObservableCollection _subItems;
18 | private List _fileTypes;
19 | private bool _showInRootMenu;
20 | private string _iconPath;
21 | private bool _isVisible = true;
22 | private bool _showOnFiles = true;
23 | private bool _appendCommandToEachPath = true;
24 | private bool _showOnFolderBackground = true;
25 | private bool _showOnFolder = true;
26 | private bool _onlyUsingProgram;
27 | private bool _runningProgramWithCMD;
28 | private bool _hideCmdWindow;
29 | private bool _keepCmdWindows;
30 | private bool _isSeparator;
31 | private bool _displayCompletePathAndCommand;
32 | private bool _useQuotes = true;
33 | private int _order;
34 | private bool _addFileTypeParameter;
35 |
36 | public string Text
37 | {
38 | get => _text;
39 | set { _text = value; OnPropertyChanged(); }
40 | }
41 |
42 | public string Command
43 | {
44 | get => _command;
45 | set { _command = value; OnPropertyChanged(); }
46 | }
47 |
48 | public string ProgramPath
49 | {
50 | get => _programPath;
51 | set { _programPath = value; OnPropertyChanged(); }
52 | }
53 |
54 | public ObservableCollection SubItems
55 | {
56 | get => _subItems;
57 | set { _subItems = value; OnPropertyChanged(); }
58 | }
59 |
60 | public List FileTypes
61 | {
62 | get => _fileTypes;
63 | set { _fileTypes = value; OnPropertyChanged(); }
64 | }
65 |
66 | public bool ShowInRootMenu
67 | {
68 | get => _showInRootMenu;
69 | set { _showInRootMenu = value; OnPropertyChanged(); }
70 | }
71 |
72 | public string IconPath
73 | {
74 | get => _iconPath;
75 | set { _iconPath = value; OnPropertyChanged(); }
76 | }
77 |
78 | public bool IsVisible
79 | {
80 | get => _isVisible;
81 | set { _isVisible = value; OnPropertyChanged(); }
82 | }
83 |
84 | public bool ShowOnFiles
85 | {
86 | get => _showOnFiles;
87 | set { _showOnFiles = value; OnPropertyChanged(); }
88 | }
89 |
90 | public bool AppendCommandToEachPath
91 | {
92 | get => _appendCommandToEachPath;
93 | set { _appendCommandToEachPath = value; OnPropertyChanged(); }
94 | }
95 |
96 | public bool ShowOnFolderBackground
97 | {
98 | get => _showOnFolderBackground;
99 | set { _showOnFolderBackground = value; OnPropertyChanged(); }
100 | }
101 |
102 | public bool ShowOnFolder
103 | {
104 | get => _showOnFolder;
105 | set { _showOnFolder = value; OnPropertyChanged(); }
106 | }
107 |
108 | public bool OnlyUsingProgram
109 | {
110 | get => _onlyUsingProgram;
111 | set { _onlyUsingProgram = value; OnPropertyChanged(); }
112 | }
113 |
114 | public bool RunningProgramWithCMD
115 | {
116 | get => _runningProgramWithCMD;
117 | set { _runningProgramWithCMD = value; OnPropertyChanged(); }
118 | }
119 |
120 | public bool HideCmdWindow
121 | {
122 | get => _hideCmdWindow;
123 | set { _hideCmdWindow = value; OnPropertyChanged(); }
124 | }
125 |
126 | public bool KeepCmdWindows
127 | {
128 | get => _keepCmdWindows;
129 | set { _keepCmdWindows = value; OnPropertyChanged(); }
130 | }
131 |
132 | public bool IsSeparator
133 | {
134 | get => _isSeparator;
135 | set { _isSeparator = value; OnPropertyChanged(); }
136 | }
137 |
138 | public bool DisplayCompletePathAndCommand
139 | {
140 | get => _displayCompletePathAndCommand;
141 | set { _displayCompletePathAndCommand = value; OnPropertyChanged(); }
142 | }
143 |
144 | public bool UseQuotes
145 | {
146 | get => _useQuotes;
147 | set { _useQuotes = value; OnPropertyChanged(); }
148 | }
149 |
150 | public int Order
151 | {
152 | get => _order;
153 | set { _order = value; OnPropertyChanged(); }
154 | }
155 |
156 | public bool AddFileTypeParameter
157 | {
158 | get => _addFileTypeParameter;
159 | set { _addFileTypeParameter = value; OnPropertyChanged(); }
160 | }
161 |
162 | public event PropertyChangedEventHandler PropertyChanged;
163 |
164 | protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
165 | {
166 | PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
167 | }
168 |
169 | public MenuItemConfig()
170 | {
171 | SubItems = new ObservableCollection();
172 | FileTypes = new List();
173 | }
174 | }
175 | }
176 |
177 |
--------------------------------------------------------------------------------
/MenuFunctions/MenuFunctions_Panel/Properties/Resources.resx:
--------------------------------------------------------------------------------
1 |
2 |
3 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 | text/microsoft-resx
107 |
108 |
109 | 2.0
110 |
111 |
112 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
113 |
114 |
115 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
116 |
117 |
--------------------------------------------------------------------------------
/MenuFunctions/MenuFunctions/Properties/Resources.resx:
--------------------------------------------------------------------------------
1 |
2 |
3 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 | text/microsoft-resx
110 |
111 |
112 | 2.0
113 |
114 |
115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
116 |
117 |
118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
119 |
120 |
121 |
--------------------------------------------------------------------------------
/MenuFunctions/MenuFunctions_Panel/MainWindow.xaml.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Globalization;
4 | using System.IO;
5 | using System.Linq;
6 | using System.Text;
7 | using System.Threading.Tasks;
8 | using System.Windows;
9 | using System.Windows.Controls;
10 | using System.Windows.Data;
11 | using System.Windows.Documents;
12 | using System.Windows.Input;
13 | using System.Windows.Media;
14 | using System.Windows.Media.Imaging;
15 | using System.Windows.Navigation;
16 | using System.Windows.Shapes;
17 | using MenuFunctions_Panel.Models;
18 | using MenuFunctions_Panel.ViewModels;
19 | using Microsoft.Win32;
20 |
21 | namespace MenuFunctions_Panel
22 | {
23 | ///
24 | /// MainWindow.xaml 的交互逻辑
25 | ///
26 | public partial class MainWindow : Window
27 | {
28 | private MainViewModel _viewModel;
29 |
30 | public MainWindow()
31 | {
32 | InitializeComponent();
33 |
34 | _viewModel = new MainViewModel();
35 | this.DataContext = _viewModel;
36 |
37 | // 尝试自动加载配置文件
38 | AutoLoadConfig();
39 | }
40 |
41 | private void AutoLoadConfig()
42 | {
43 | // 尝试从 MenuFunctions 项目的 bin/Release 目录加载配置
44 | var possiblePaths = new[]
45 | {
46 | System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "MenuConfig.json"),
47 | System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "..", "..", "..", "MenuFunctions", "bin", "Release", "MenuConfig.json"),
48 | System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "..", "..", "..", "..", "MenuFunctions", "bin", "Release", "MenuConfig.json")
49 | };
50 |
51 | foreach (var path in possiblePaths)
52 | {
53 | try
54 | {
55 | var fullPath = System.IO.Path.GetFullPath(path);
56 | if (File.Exists(fullPath))
57 | {
58 | _viewModel.LoadConfig(fullPath);
59 | return;
60 | }
61 | }
62 | catch { }
63 | }
64 | }
65 |
66 | private void LoadConfig_Click(object sender, RoutedEventArgs e)
67 | {
68 | var dialog = new OpenFileDialog
69 | {
70 | Filter = "JSON 文件|*.json|所有文件|*.*",
71 | Title = "打开配置文件"
72 | };
73 |
74 | if (dialog.ShowDialog() == true)
75 | {
76 | _viewModel.LoadConfig(dialog.FileName);
77 | }
78 | }
79 |
80 | private void SaveConfig_Click(object sender, RoutedEventArgs e)
81 | {
82 | if (string.IsNullOrEmpty(_viewModel.ConfigFilePath))
83 | {
84 | var dialog = new SaveFileDialog
85 | {
86 | Filter = "JSON 文件|*.json|所有文件|*.*",
87 | Title = "保存配置文件",
88 | FileName = "MenuConfig.json"
89 | };
90 |
91 | if (dialog.ShowDialog() == true)
92 | {
93 | _viewModel.SaveConfig(dialog.FileName);
94 | }
95 | }
96 | else
97 | {
98 | _viewModel.SaveConfig(_viewModel.ConfigFilePath);
99 | }
100 | }
101 |
102 | private void AddMenuItem_Click(object sender, RoutedEventArgs e)
103 | {
104 | _viewModel.AddMenuItem();
105 | }
106 |
107 | private void AddSubMenuItem_Click(object sender, RoutedEventArgs e)
108 | {
109 | _viewModel.AddSubMenuItem();
110 | }
111 |
112 | private void AddSeparator_Click(object sender, RoutedEventArgs e)
113 | {
114 | _viewModel.AddSeparator();
115 | }
116 |
117 | private void DeleteMenuItem_Click(object sender, RoutedEventArgs e)
118 | {
119 | _viewModel.DeleteMenuItem();
120 | }
121 |
122 | private void MoveUp_Click(object sender, RoutedEventArgs e)
123 | {
124 | _viewModel.MoveUp();
125 | }
126 |
127 | private void MoveDown_Click(object sender, RoutedEventArgs e)
128 | {
129 | _viewModel.MoveDown();
130 | }
131 |
132 | private void MenuTreeView_SelectedItemChanged(object sender, RoutedPropertyChangedEventArgs