前言
為了將“解決自媒體一鍵多平臺(tái)發(fā)布”項(xiàng)目做得更適合自己的使用習(xí)慣,Windows端的桌面版也立項(xiàng)了。
本篇文章分享的內(nèi)容是:實(shí)現(xiàn)系統(tǒng)右鍵菜單按鈕關(guān)聯(lián)桌面程序問(wèn)題。
一、開(kāi)發(fā)環(huán)境
- vs2019
- Windows 10
二、具體代碼
本次實(shí)現(xiàn)系統(tǒng)右鍵菜單按鈕功能,是通過(guò)Windows注冊(cè)表實(shí)現(xiàn)的。
1、訪問(wèn)HKEY_CURRENT_USER
使用HKEY_CURRENT_USER,是為了避免向用戶申請(qǐng)管理員權(quán)限。具體代碼如下:
//using Microsoft.Win32;
var userRegistry = Registry.CurrentUser;
2、訪問(wèn)Software\Classes\*\shell
當(dāng)前用戶的右鍵菜單按鈕信息(僅指文件),是儲(chǔ)存在Software\Classes\*\shell中的,所以我們需要拿到shell的寫權(quán)限。具體代碼如下:
var shellRegistryKey = userRegistry.OpenSubKey("Software").OpenSubKey("Classes").OpenSubKey("*").OpenSubKey("shell", true);
提示:OpenSubKey("shell", true)中的第二個(gè)參數(shù)設(shè)置為true,是為了在shell中寫入子項(xiàng)(也就是拿到shell的寫權(quán)限)。
3、判斷準(zhǔn)備生成的右鍵菜單按鈕名是否存在
為防止重復(fù)寫入導(dǎo)致出錯(cuò),先判斷子項(xiàng)名(右鍵菜單按鈕名)是否存在。代碼如下:
var isRegistryKeyNameExsit = shellRegistryKey.GetSubKeyNames().Contains(keyName);
4、寫入右鍵菜單按鈕名
首先shell中寫入子項(xiàng)(可以理解為在注冊(cè)表中的名字),然后設(shè)置剛創(chuàng)建的子項(xiàng)在右鍵菜單中的按鈕名。具體代碼:
var contextMenuRegistryKey = shellRegistryKey.CreateSubKey(keyName);
contextMenuRegistryKey.SetValue("", keyName);
提示:contextMenuRegistryKey.SetValue("", keyName)中的keyName是顯示在右鍵菜單中的按鈕名,可以不同子項(xiàng)名,使用其他名字。
5、關(guān)聯(lián)指定程序
首先在新建的子項(xiàng)中創(chuàng)建名為command的子項(xiàng),然后設(shè)置子項(xiàng)中的默認(rèn)項(xiàng)的值為"程序路徑" "%1",這樣就將指定程序與右鍵菜單按鈕進(jìn)行了關(guān)聯(lián)。
contextMenuRegistryKey.CreateSubKey("command");
command.SetValue("", $"\"{programPath}\" \"%1\"");
提示:"程序路徑" "%1"中%1是為了把右鍵打開(kāi)關(guān)聯(lián)程序時(shí),把選擇的文件路徑傳給關(guān)聯(lián)程序。
如果關(guān)聯(lián)程序時(shí)Winform程序,則還需要修改Winform默認(rèn)程序,實(shí)現(xiàn)接收傳入的文件路徑的功能。
5.1、修改Winform默認(rèn)程序
(1)修改Program.cs
將默認(rèn)的無(wú)參Main()方法修改為如下代碼:
static void Main(string[] args)
(2)修改Main()方法的默認(rèn)啟動(dòng)窗口程序
代碼如下:
Application.Run(new Form1(args));
(3)修改Form1.cs
為了接收參數(shù),需要一個(gè)新的構(gòu)造函數(shù),具體代碼如下:
public Form1(string[] args) : this()
{
this.label1.Text = string.Join(",", args);
}
提示:this()是為了不修改默認(rèn)的無(wú)參構(gòu)造函數(shù),直接調(diào)用它。
三、完整的程序代碼
1、注冊(cè)表修改
/// <summary>
/// 注冊(cè)表幫助類
/// 版本:v1
/// 日期:2022年10月15日
/// 作者:hxsfx
/// </summary>
public class RegistryHelper
{
/// <summary>
/// 計(jì)算機(jī)\HKEY_CURRENT_USER\Software\Classes\*\shell
/// </summary>
private static RegistryKey RegistryUserSoftwareClassesAllShell
{
get
{
return Registry.CurrentUser.OpenSubKey("Software").OpenSubKey("Classes").OpenSubKey("*").OpenSubKey("shell", true);
}
}
/// <summary>
/// 生成右鍵菜單按鈕(當(dāng)前用戶)
/// </summary>
/// <param name="keyName">右鍵菜單名</param>
/// <param name="programPath">點(diǎn)擊按鈕后打開(kāi)的程序路徑</param>
public static void CreateUserContextMenu(string keyName, string programPath)
{
if (!RegistryUserSoftwareClassesAllShell.GetSubKeyNames().Contains(keyName))
{
var contextMenuRegistryKey = RegistryUserSoftwareClassesAllShell.CreateSubKey(keyName);
contextMenuRegistryKey.SetValue("", keyName);
var command = contextMenuRegistryKey.CreateSubKey("command");
command.SetValue("", $"\"{programPath}\" \"%1\"");
}
}
/// <summary>
/// 刪除右鍵菜單按鈕(當(dāng)前用戶)
/// </summary>
/// <param name="keyName">右鍵菜單名</param>
public static void DeleteUserContextMenu(string keyName)
{
if (RegistryUserSoftwareClassesAllShell.GetSubKeyNames().Contains(keyName))
{
RegistryUserSoftwareClassesAllShell.DeleteSubKeyTree(keyName);
}
}
}
2、Winform代碼
(1)Program.cs
static class Program
{
/// <summary>
/// 應(yīng)用程序的主入口點(diǎn)。
/// </summary>
[STAThread]
static void Main(string[] args)
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1(args));
}
}
(1)窗口Form1.cs
public partial class Form1 : Form
{
public Form1(string[] args) : this()
{
this.label1.Text = string.Join(",", args);
}
public Form1()
{
InitializeComponent();
}
}
四、最后
其實(shí)個(gè)人不是很喜歡通過(guò)注冊(cè)表來(lái)實(shí)現(xiàn)功能,一方面是不了解注冊(cè)表,另一方面是總覺(jué)得注冊(cè)表不夠優(yōu)雅。哈哈~
如果各位小伙伴有什么其他更好的辦法,可以告訴我哦~