如何用Python案例实现右键菜单扩展?

wen python案例 2

本文目录导读:

如何用Python案例实现右键菜单扩展?

  1. 方法一:使用注册表(简单方式)
  2. 方法二:使用自定义类(高级方式)
  3. 方法三:使用 pywin32(最完整)
  4. 使用示例
  5. 注意事项

我来通过一个完整的Python案例,演示如何实现Windows右键菜单扩展。

使用注册表(简单方式)

为特定文件类型添加右键菜单

import winreg
import os
import sys
import json
class RightClickMenu:
    def __init__(self):
        self.script_path = sys.executable if getattr(sys, 'frozen', False) else __file__
    def add_menu_for_txt(self, menu_name, python_script):
        """为.txt文件添加右键菜单"""
        try:
            # 打开.txt文件的注册表项
            key_path = r"*\shell"
            key = winreg.OpenKey(winreg.HKEY_CLASSES_ROOT, key_path, 0, winreg.KEY_SET_VALUE)
            # 创建菜单项
            menu_key = winreg.CreateKey(key, menu_name)
            winreg.SetValue(menu_key, '', winreg.REG_SZ, menu_name)
            # 设置命令
            command_key = winreg.CreateKey(menu_key, 'command')
            command = f'"{sys.executable}" "{python_script}" "%1"'
            winreg.SetValue(command_key, '', winreg.REG_SZ, command)
            winreg.CloseKey(command_key)
            winreg.CloseKey(menu_key)
            winreg.CloseKey(key)
            print(f"成功添加 '{menu_name}' 右键菜单")
            return True
        except Exception as e:
            print(f"添加右键菜单失败: {e}")
            return False
    def remove_menu(self, menu_name):
        """移除右键菜单"""
        try:
            key_path = r"*\shell"
            key = winreg.OpenKey(winreg.HKEY_CLASSES_ROOT, key_path, 0, winreg.KEY_SET_VALUE)
            winreg.DeleteKey(key, menu_name + "\\command")
            winreg.DeleteKey(key, menu_name)
            winreg.CloseKey(key)
            print(f"成功移除 '{menu_name}' 右键菜单")
            return True
        except Exception as e:
            print(f"移除右键菜单失败: {e}")
            return False
# 右键菜单处理脚本示例
def txt_processor():
    """处理选中文件的脚本"""
    import sys
    if len(sys.argv) > 1:
        file_path = sys.argv[1]
        print(f"处理文件: {file_path}")
        # 读取文件内容
        try:
            with open(file_path, 'r', encoding='utf-8') as f:
                content = f.read()
            # 示例:统计文件信息
            info = {
                '文件名': os.path.basename(file_path),
                '大小': f"{len(content)} 字符",
                '行数': len(content.splitlines()),
                '单词数': len(content.split())
            }
            print(json.dumps(info, ensure_ascii=False, indent=2))
        except Exception as e:
            print(f"处理文件失败: {e}")
if __name__ == "__main__":
    # 使用示例
    menu = RightClickMenu()
    print("1. 添加右键菜单")
    print("2. 移除右键菜单")
    print("3. 处理文件测试")
    choice = input("请选择操作: ")
    if choice == '1':
        menu_name = input("请输入菜单名称: ")
        script_path = input("请输入Python脚本路径: ")
        menu.add_menu_for_txt(menu_name, script_path)
    elif choice == '2':
        menu_name = input("请输入要移除的菜单名称: ")
        menu.remove_menu(menu_name)
    elif choice == '3':
        txt_processor()

使用自定义类(高级方式)

import winreg
import os
import sys
import subprocess
from pathlib import Path
class AdvancedRightClickMenu:
    """高级右键菜单管理器"""
    def __init__(self, app_name="MyPythonApp"):
        self.app_name = app_name
        self.registry_base = r"Software\Classes"
    def add_menu_to_all_files(self, menu_text, icon_path="", command=""):
        """为所有文件添加右键菜单"""
        base_key = winreg.HKEY_CLASSES_ROOT
        shell_path = r"*\shell"
        try:
            # 打开或创建shell键
            with winreg.OpenKey(base_key, shell_path, 0, winreg.KEY_SET_VALUE) as shell_key:
                # 创建菜单项
                with winreg.CreateKey(shell_key, self.app_name) as app_key:
                    # 设置菜单显示文本
                    winreg.SetValueEx(app_key, "", 0, winreg.REG_SZ, menu_text)
                    # 设置图标(可选)
                    if icon_path:
                        winreg.SetValueEx(app_key, "Icon", 0, winreg.REG_SZ, icon_path)
                    # 设置扩展验证
                    winreg.SetValueEx(app_key, "AppliesTo", 0, winreg.REG_SZ, "System.FileName")
                    # 创建命令键
                    with winreg.CreateKey(app_key, "command") as cmd_key:
                        if command:
                            cmd = f'"{sys.executable}" "{command}" "%1"'
                        else:
                            # 使用当前脚本
                            cmd = f'"{sys.executable}" "{__file__}" "%1"'
                        winreg.SetValueEx(cmd_key, "", 0, winreg.REG_SZ, cmd)
            print(f"成功添加右键菜单: {menu_text}")
            return True
        except Exception as e:
            print(f"添加菜单失败: {e}")
            return False
    def add_menu_to_folder(self, menu_text, command=""):
        """为文件夹添加右键菜单"""
        base_key = winreg.HKEY_CLASSES_ROOT
        shell_path = r"Directory\shell"
        try:
            with winreg.OpenKey(base_key, shell_path, 0, winreg.KEY_SET_VALUE) as shell_key:
                with winreg.CreateKey(shell_key, self.app_name) as app_key:
                    winreg.SetValueEx(app_key, "", 0, winreg.REG_SZ, menu_text)
                    with winreg.CreateKey(app_key, "command") as cmd_key:
                        if command:
                            cmd = f'"{sys.executable}" "{command}" "%1"'
                        else:
                            cmd = f'"{sys.executable}" "{__file__}" "%1"'
                        winreg.SetValueEx(cmd_key, "", 0, winreg.REG_SZ, cmd)
            print(f"成功添加文件夹右键菜单: {menu_text}")
            return True
        except Exception as e:
            print(f"添加菜单失败: {e}")
            return False
    def add_submenu(self, menu_text, submenu_items):
        """添加子菜单(多级菜单)"""
        base_key = winreg.HKEY_CLASSES_ROOT
        shell_path = r"*\shell"
        try:
            with winreg.OpenKey(base_key, shell_path, 0, winreg.KEY_SET_VALUE) as shell_key:
                with winreg.CreateKey(shell_key, self.app_name) as app_key:
                    winreg.SetValueEx(app_key, "", 0, winreg.REG_SZ, menu_text)
                    winreg.SetValueEx(app_key, "SubCommands", 0, winreg.REG_SZ, "")
                    winreg.SetValueEx(app_key, "MUIVerb", 0, winreg.REG_SZ, menu_text)
                # 创建子菜单项
                for i, (sub_text, sub_cmd) in enumerate(submenu_items, 1):
                    sub_key_name = f"{self.app_name}\\shell\\item{i}"
                    with winreg.CreateKey(base_key, sub_key_name) as sub_key:
                        winreg.SetValueEx(sub_key, "MUIVerb", 0, winreg.REG_SZ, sub_text)
                        with winreg.CreateKey(sub_key, "command") as cmd_key:
                            cmd = f'"{sys.executable}" "{sub_cmd}" "%1"'
                            winreg.SetValueEx(cmd_key, "", 0, winreg.REG_SZ, cmd)
            print(f"成功添加子菜单: {menu_text}")
            return True
        except Exception as e:
            print(f"添加子菜单失败: {e}")
            return False
    def remove_menu(self):
        """移除右键菜单"""
        paths = [
            f"*\\shell\\{self.app_name}",
            f"Directory\\shell\\{self.app_name}",
            f"*\\shell\\{self.app_name}\\shell",
        ]
        base_key = winreg.HKEY_CLASSES_ROOT
        for path in paths:
            try:
                # 递归删除子键
                self._delete_key_recursive(base_key, path)
            except:
                pass
        print(f"成功移除右键菜单: {self.app_name}")
    def _delete_key_recursive(self, base_key, key_path):
        """递归删除注册表键"""
        try:
            with winreg.OpenKey(base_key, key_path, 0, winreg.KEY_READ) as key:
                # 获取子键列表
                i = 0
                while True:
                    try:
                        sub_key = winreg.EnumKey(key, i)
                        self._delete_key_recursive(base_key, f"{key_path}\\{sub_key}")
                        i += 1
                    except WindowsError:
                        break
            winreg.DeleteKey(base_key, key_path)
        except Exception:
            pass
# 实际处理脚本
class FileProcessor:
    """文件处理器示例"""
    @staticmethod
    def analyze_file(file_path):
        """分析文件"""
        if not os.path.exists(file_path):
            return {"error": "文件不存在"}
        file_size = os.path.getsize(file_path)
        file_ext = os.path.splitext(file_path)[1]
        file_name = os.path.basename(file_path)
        result = {
            "文件名": file_name,
            "扩展名": file_ext,
            "大小": f"{file_size / 1024:.2f} KB",
            "路径": file_path
        }
        # 如果是文本文件,读取内容
        if file_ext in ['.txt', '.py', '.md', '.json', '.xml', '.html', '.css', '.js']:
            try:
                with open(file_path, 'r', encoding='utf-8') as f:
                    content = f.read()
                result.update({
                    "字符数": len(content),
                    "行数": len(content.splitlines()),
                    "单词数": len(content.split())
                })
            except:
                result["编码"] = "无法读取"
        return result
    @staticmethod
    def backup_file(file_path):
        """备份文件"""
        if os.path.exists(file_path):
            backup_path = file_path + ".backup"
            import shutil
            shutil.copy2(file_path, backup_path)
            return {"success": True, "backup_path": backup_path}
        return {"success": False, "error": "源文件不存在"}
def main():
    """主入口"""
    import sys
    if len(sys.argv) > 1:
        file_path = sys.argv[1]
        processor = FileProcessor()
        # 分析文件
        info = processor.analyze_file(file_path)
        print("文件分析结果:")
        for key, value in info.items():
            print(f"{key}: {value}")
    else:
        # 管理界面
        menu = AdvancedRightClickMenu("PythonTools")
        print("右键菜单管理器")
        print("=" * 30)
        print("1. 为所有文件添加 '文件分析' 菜单")
        print("2. 为文件夹添加 '文件夹分析' 菜单")
        print("3. 添加子菜单(分析/备份)")
        print("4. 移除所有菜单")
        print("5. 退出")
        choice = input("请选择 (1-5): ")
        if choice == '1':
            # 添加文件分析菜单
            menu.add_menu_to_all_files("Python 文件分析")
        elif choice == '2':
            # 添加文件夹菜单
            menu.add_menu_to_folder("Python 文件夹分析")
        elif choice == '3':
            # 添加子菜单
            submenu_items = [
                ("分析文件", __file__),
                ("备份文件", __file__)
            ]
            menu.add_submenu("Python 工具", submenu_items)
        elif choice == '4':
            # 移除菜单
            menu.remove_menu()
        elif choice == '5':
            print("退出程序")
            sys.exit(0)
if __name__ == "__main__":
    main()

使用 pywin32(最完整)

import win32con
import win32api
import win32security
import pythoncom
import sys
import os
class ContextMenuHandler:
    """Windows右键菜单COM组件"""
    def __init__(self):
        self._reg_clsid = "{YOUR_GUID}"  # 需要生成GUID
        self._reg_progid = "PythonContextMenu"
        self._reg_desc = "Python Context Menu Handler"
    def register(self):
        """注册COM组件"""
        import win32com.server.register
        win32com.server.register.UseCommandLine(
            self._reg_clsid,
            self._reg_progid,
            self._reg_desc,
            "PythonContextMenu.ContextMenu"
        )
    def unregister(self):
        """注销COM组件"""
        import win32com.server.unregister
        win32com.server.unregister.UseCommandLine(
            self._reg_clsid,
            self._reg_progid
        )
# 实际右键菜单处理
def handle_right_click():
    """处理右键点击事件"""
    import sys
    if len(sys.argv) > 1:
        selected_files = sys.argv[1:]
        print("选中的文件:")
        for file in selected_files:
            print(f"  - {file}")
        # 在这里添加你的处理逻辑
        # 批量重命名、压缩、加密等
if __name__ == "__main__":
    # 检查是否传递了文件参数
    if len(sys.argv) > 1:
        handle_right_click()
    else:
        # 注册/注销菜单
        handler = ContextMenuHandler()
        print("1. 注册右键菜单")
        print("2. 注销右键菜单")
        choice = input("请选择: ")
        if choice == '1':
            handler.register()
            print("右键菜单已注册")
        elif choice == '2':
            handler.unregister()
            print("右键菜单已注销")

使用示例

创建处理脚本 process_files.py

import sys
import os
import json
from datetime import datetime
def process_selected_file(file_path):
    """处理选中的文件"""
    print(f"""
    ==================== 文件处理结果 ====================
    文件路径: {file_path}
    处理时间: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}
    =================================================
    """)
    # 获取文件信息
    if os.path.exists(file_path):
        stat = os.stat(file_path)
        info = {
            "文件大小": f"{stat.st_size / 1024:.2f} KB",
            "创建时间": datetime.fromtimestamp(stat.st_ctime).strftime('%Y-%m-%d %H:%M:%S'),
            "修改时间": datetime.fromtimestamp(stat.st_mtime).strftime('%Y-%m-%d %H:%M:%S'),
            "访问时间": datetime.fromtimestamp(stat.st_atime).strftime('%Y-%m-%d %H:%M:%S')
        }
        print("文件信息:")
        for key, value in info.items():
            print(f"  {key}: {value}")
        # 如果是文本文件,添加内容分析
        if file_path.endswith(('.txt', '.py', '.md', '.log')):
            try:
                with open(file_path, 'r', encoding='utf-8') as f:
                    content = f.read()
                print(f"\n文本分析:")
                print(f"  字符数: {len(content)}")
                print(f"  行数: {len(content.splitlines())}")
            except:
                print("\n无法读取文件内容")
if __name__ == "__main__":
    if len(sys.argv) > 1:
        file_path = sys.argv[1]
        process_selected_file(file_path)
    else:
        print("请右键点击文件,然后选择此程序")

安装脚本 install_menu.py

import winreg
import sys
import os
def install_right_click_menu():
    """安装右键菜单"""
    script_path = os.path.abspath("process_files.py")
    menu_name = "Python 文件分析"
    try:
        # 为所有文件添加菜单
        key_path = r"*\shell"
        key = winreg.OpenKey(winreg.HKEY_CLASSES_ROOT, key_path, 0, winreg.KEY_SET_VALUE)
        # 创建菜单项
        menu_key = winreg.CreateKey(key, menu_name)
        winreg.SetValue(menu_key, '', winreg.REG_SZ, menu_name)
        # 设置命令
        command_key = winreg.CreateKey(menu_key, 'command')
        command = f'"{sys.executable}" "{script_path}" "%1"'
        winreg.SetValue(command_key, '', winreg.REG_SZ, command)
        winreg.CloseKey(command_key)
        winreg.CloseKey(menu_key)
        winreg.CloseKey(key)
        print(f"✓ 右键菜单 '{menu_name}' 安装成功!")
        print(f"  执行脚本: {script_path}")
    except Exception as e:
        print(f"✗ 安装失败: {e}")
        sys.exit(1)
def uninstall_right_click_menu():
    """卸载右键菜单"""
    menu_name = "Python 文件分析"
    try:
        key_path = r"*\shell"
        key = winreg.OpenKey(winreg.HKEY_CLASSES_ROOT, key_path, 0, winreg.KEY_SET_VALUE)
        # 删除命令子键和菜单主键
        try:
            winreg.DeleteKey(key, menu_name + "\\command")
            winreg.DeleteKey(key, menu_name)
        except:
            pass  # 键可能已经不存在
        winreg.CloseKey(key)
        print(f"✓ 右键菜单 '{menu_name}' 已卸载")
    except Exception as e:
        print(f"✗ 卸载失败: {e}")
        sys.exit(1)
if __name__ == "__main__":
    print("右键菜单安装工具")
    print("=" * 30)
    print("1. 安装右键菜单")
    print("2. 卸载右键菜单")
    choice = input("请选择 (1-2): ")
    if choice == '1':
        install_right_click_menu()
    elif choice == '2':
        uninstall_right_click_menu()
    else:
        print("无效选择")

注意事项

  1. 管理员权限:修改注册表需要管理员权限
  2. 安全考虑:不要添加恶意功能
  3. 测试环境:先在测试环境验证
  4. 备份注册表:修改前备份
  5. GUID生成:使用COM组件时需要唯一GUID

这些示例涵盖了不同复杂度的右键菜单实现,你可以根据需求选择合适的方案。

抱歉,评论功能暂时关闭!