1. 需求:

为资源管理器的右键菜单添加两个菜单项,其一点击后,打开NextCloud本地同步目录,其二点击后打开NextCloud网页。

(两个菜单项分别用于打开本地同步目录和云盘网站)
(菜单未添加时,点击按钮进行添加)
(菜单已存在时,点击按钮移除)

2. 原理:

资源管理器空白处右键时的弹出菜单的菜单项位于HKEY_CLASSES_ROOT\Directory\Background\shell,新建一个项目,并为新项目创建子项目command。新项的默认值用于定义菜单项文本,command的默认值用于定义执行的命令。

3. 实例:

因为注册表操作需要管理员权限,所以需要为程序请求管理员级别的UAC权限。方法为:向项目添加应用程序清单文件,将requestedExecutionLevel小节的level属性改为requireAdministrator)。

using Microsoft.Win32;
using System;
using System.Linq;
using System.Windows.Forms;

namespace YunMenus
{
    public partial class frmMain : Form
    {
        RegistryKey BaseKey = Registry.ClassesRoot.OpenSubKey("Directory\\Background\\shell", true);
        const string KeyName0 = "云盘-文件夹(&0)";
        const string KeyName1 = "云盘-网站(&1)";
        const string Key0 = "yunpan0";
        const string Key1 = "yunpan1";
        public frmMain() => InitializeComponent();
        private void BtnGo_Click(object sender, EventArgs e)
        {
            RegistryKey key = BaseKey.OpenSubKey(Key0, true);
            if (key == null)
            {
                using (FolderBrowserDialog dialog = new FolderBrowserDialog
                {
                    Description = "选择NextCloud的本地文件夹(同步目录)",
                    ShowNewFolderButton = false
                })
                {
                    DialogResult result = dialog.ShowDialog();
                    if (result == DialogResult.OK && 
                        System.IO.Directory.Exists(dialog.SelectedPath))
                    {
                        AddKey(
                            Key0, 
                            KeyName0, 
                            "explorer " + dialog.SelectedPath);
                        AddKey(
                            Key1, 
                            KeyName1, 
                            "rundll32 url.dll,FileProtocolHandler https://url.of.you.cloud");
                        MessageBox.Show(
                            "快捷菜单添加完成。", 
                            "成功添加", 
                            MessageBoxButtons.OK, 
                            MessageBoxIcon.Information);
                    }
                    else
                    {
                        MessageBox.Show(
                            "用户放弃操作。", 
                            "添加失败", 
                            MessageBoxButtons.OK, 
                            MessageBoxIcon.Warning);
                    }
                }
            }
            else
            {
                key.Close();
                RemoveKey();
            }

            CheckKey();
        }
        void CheckKey()
        {
            if (BaseKey.GetSubKeyNames().Contains(Key0))
            {
                lblState.Text = "菜单已存在";
                btnGo.Text = "移除";
            }
            else
            {
                lblState.Text = "菜单未添加";
                btnGo.Text = "添加";
            }
        }
        void AddKey(string index, string key, string cmd)
        {
            RegistryKey regkey = BaseKey.CreateSubKey(index);
            regkey.SetValue("", key);
            regkey.CreateSubKey("command").SetValue("", cmd);
            regkey.Close();
        }
        void RemoveKey()
        {
            BaseKey.DeleteSubKeyTree(Key0);
            BaseKey.DeleteSubKeyTree(Key1);
            MessageBox.Show(
                "快捷菜单成功移除完成。",
                "成功移除",
                MessageBoxButtons.OK,
                MessageBoxIcon.Information);
        }
        private void FrmMain_Load(object sender, EventArgs e) => CheckKey();
        private void FrmMain_FormClosing(object sender, FormClosingEventArgs e)
        {
            BaseKey.Close();
            BaseKey.Dispose();
        }
    }
}