C# 实现windows鼠标右键动态菜单
·
实现内容
- 1 鼠标右键点击单个.xlsx或.xls文件,显示与左边文件进行对比

- 2 选中两个文件,点击鼠标右键,显示表格对比

代码
using Microsoft.Win32;
using SharpShell.Attributes;
using SharpShell.SharpContextMenu;
using System;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Windows.Forms;
namespace ExcelCompareExtension
{
// 声明COM可见性
[ComVisible(true)]
// 关联文件类型
[COMServerAssociation(AssociationType.ClassOfExtension, ".xlsx")]
[COMServerAssociation(AssociationType.ClassOfExtension, ".xls")]
public class ExcelCompareExtension : SharpContextMenu
{
static string dllPath = typeof(ExcelCompareExtension).Assembly.Location;
static string dllDirectory = Path.GetDirectoryName(dllPath);
string exeFullPath = Path.Combine(dllDirectory, "Excel Compare.exe");
/// <summary>
/// 决定是否显示菜单项
/// </summary>
protected override bool CanShowMenu()
{
// 这里可以添加更复杂的逻辑,例如检查选中文件的数量或类型
// SelectedItemPaths 是 SharpShell 提供的属性,包含所有选中文件的路径
return SelectedItemPaths.Count() > 0;
}
/// <summary>
/// 创建并返回上下文菜单
/// </summary>
protected override ContextMenuStrip CreateMenu()
{
var menu = new ContextMenuStrip();
if (SelectedItemPaths.Count() == 1)
{
var leftValue = RegistryHelper.ReadValue("SaveLeftExcel");
if (leftValue == "")
{
var itemChooseLeftCompare = new ToolStripMenuItem
{
Text = "选择左边文件进行比较"
// 如果有图标资源,可以在此处设置 Image 属性
// Image = Properties.Resources.CountLines
};
itemChooseLeftCompare.Click += (sender, args) => WriteLeftvalue();
menu.Items.Add(itemChooseLeftCompare);
}
else
{
var itemChooseLeftCompare = new ToolStripMenuItem
{
Text = "选择左边文件进行比较"
};
itemChooseLeftCompare.Click += (sender, args) => WriteLeftvalue();
menu.Items.Add(itemChooseLeftCompare);
var itemWithLeftCompare = new ToolStripMenuItem
{
Text = $"与{Path.GetFileName(leftValue)}进行比较"
};
itemWithLeftCompare.Click += (sender, args) => CompareExcel();
menu.Items.Add(itemWithLeftCompare);
}
}
if (SelectedItemPaths.Count() == 2)
{
var itenExcleCompare = new ToolStripMenuItem
{
Text = "表格对比"
};
itenExcleCompare.Click += (sender, args) => CompareExcel2();
menu.Items.Add(itenExcleCompare);
}
return menu;
}
private void WriteLeftvalue()
{
foreach (var filePath in SelectedItemPaths)
RegistryHelper.WriteValue("SaveLeftExcel", filePath);
}
private void CompareExcel()
{
string excelPath = "";
foreach (var filePath in SelectedItemPaths)
excelPath = filePath;
var LeftExclePath = RegistryHelper.ReadValue("SaveLeftExcel");
string exePath = exeFullPath;
string executeArgs = $"{LeftExclePath} {excelPath}";
ExecuteExternalExe(exePath, executeArgs);
//注册表SaveLeftExcel值写空
RegistryHelper.WriteValue("SaveLeftExcel", "");
}
private void CompareExcel2()
{
string exePath = exeFullPath;
string executeArgs = "";
foreach (var filePath in SelectedItemPaths)
{
executeArgs += $"{filePath} ";
}
ExecuteExternalExe(exePath, executeArgs);
}
public class RegistryHelper
{
private const string SubKey = @"SOFTWARE\MyShellExtension";
// 读取值
public static string ReadValue(string valueName, string defaultValue = "")
{
try
{
// 优先检查当前用户配置,若无则检查本地机器
using (var key = Registry.CurrentUser.OpenSubKey(SubKey))
{
if (key != null)
{
return key.GetValue(valueName, defaultValue)?.ToString() ?? defaultValue;
}
}
}
catch (Exception ex)
{
// 记录日志,避免崩溃
System.Diagnostics.Debug.WriteLine($"Read Reg Error: {ex.Message}");
}
return defaultValue;
}
// 写入值
public static void WriteValue(string valueName, string value)
{
try
{
// CreateSubKey 若不存在则创建,存在则打开
using (var key = Registry.CurrentUser.CreateSubKey(SubKey))
{
if (key != null)
{
key.SetValue(valueName, value, RegistryValueKind.String);
}
}
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine($"Write Reg Error: {ex.Message}");
}
}
}
public void ExecuteExternalExe(string exePath, string arguments)
{
try
{
var startInfo = new ProcessStartInfo
{
FileName = exePath,
Arguments = arguments,
UseShellExecute = false, // 必须为 false 才能重定向输出或隐藏窗口
CreateNoWindow = true, // 不显示控制台窗口
RedirectStandardOutput = true, // 如需获取返回结果
RedirectStandardError = true
};
using (var process = Process.Start(startInfo))
{
// 同步等待(慎用,可能导致资源管理器假死)
// process.WaitForExit();
// 推荐:异步读取或仅启动后忽略
string output = process.StandardOutput.ReadToEnd();
string error = process.StandardError.ReadToEnd();
// 记录日志或处理结果
}
}
catch (Exception ex)
{
// 记录异常,防止崩溃
}
}
}
}
windows注册
编译代码生成DLL,使用regasm手动处理注册表项以让资源管理器识别,"%DLL_PATH%",DLL_PATH为DLL文件绝对路径
C:\Windows\Microsoft.NET\Framework64\v4.0.30319\regasm.exe /codebase "%DLL_PATH%"
取消注册
C:\Windows\Microsoft.NET\Framework64\v4.0.30319\regasm.exe /u "%DLL_PATH%"
更多推荐


所有评论(0)