欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Python+PyQt5開發(fā)一個(gè)Windows電腦啟動(dòng)項(xiàng)管理神器

 更新時(shí)間:2025年05月06日 14:19:56   作者:創(chuàng)客白澤  
這篇文章主要介紹了如何使用PyQt5開發(fā)一款顏值與功能并存的Windows啟動(dòng)項(xiàng)管理工具,不僅能查看/刪除現(xiàn)有啟動(dòng)項(xiàng),還能智能添加新啟動(dòng)項(xiàng),支持拖拽操作,下面就跟隨小編一起了解一下吧

開篇:為什么我們需要啟動(dòng)項(xiàng)管理工具

在日常使用Windows電腦時(shí),你是否遇到過這些問題?

電腦開機(jī)越來越慢,像老牛拉破車

莫名其妙的后臺程序占用大量資源

想禁用某些啟動(dòng)項(xiàng)卻找不到入口

需要添加自定義啟動(dòng)項(xiàng)但操作復(fù)雜

今天,我將帶大家用PyQt5開發(fā)一款顏值與功能并存的Windows啟動(dòng)項(xiàng)管理工具!不僅能查看/刪除現(xiàn)有啟動(dòng)項(xiàng),還能智能添加新啟動(dòng)項(xiàng),支持拖拽操作,界面美觀大方!

功能全景圖

先來看看我們開發(fā)的工具具備哪些殺手級功能:

? 雙模式啟動(dòng)項(xiàng)查看

  • 當(dāng)前用戶啟動(dòng)項(xiàng)(HKCU)
  • 所有用戶啟動(dòng)項(xiàng)(HKLM)
  • 啟動(dòng)文件夾項(xiàng)目

? 智能分類展示

  • 名稱/狀態(tài)/路徑/參數(shù) 四維信息
  • 樹形結(jié)構(gòu)清晰明了

? 三種添加方式

  • 拖拽文件快捷添加(超方便!)
  • 表單手動(dòng)填寫添加
  • 瀏覽文件選擇添加

? 多位置支持

  • 當(dāng)前用戶注冊表
  • 所有用戶注冊表(需管理員權(quán)限)
  • 啟動(dòng)文件夾

? 右鍵快捷操作

一鍵刪除不需要的啟動(dòng)項(xiàng)

核心技術(shù)解析

1. Windows注冊表操作

我們通過Python的winreg模塊訪問Windows注冊表:

import winreg

???????# 讀取當(dāng)前用戶啟動(dòng)項(xiàng)
def load_registry_startup_items(self, parent_item, hive, subkey):
    try:
        with winreg.OpenKey(hive, subkey) as key:
            i = 0
            while True:
                try:
                    name, value, _ = winreg.EnumValue(key, i)
                    # 解析注冊表值
                    path, args = self.parse_command(value)
                    # 創(chuàng)建樹形項(xiàng)目...
                    i += 1
                except OSError:
                    break

關(guān)鍵點(diǎn):

  • HKEY_CURRENT_USER - 當(dāng)前用戶配置
  • HKEY_LOCAL_MACHINE - 所有用戶配置
  • EnumValue - 枚舉注冊表值
  • SetValueEx - 寫入新值

2. 啟動(dòng)文件夾處理

除了注冊表,Windows還會(huì)從兩個(gè)特殊文件夾加載啟動(dòng)項(xiàng):

# 獲取啟動(dòng)文件夾路徑
user_startup = os.path.join(os.getenv('APPDATA'), 
                          r'Microsoft\Windows\Start Menu\Programs\Startup')
all_users_startup = os.path.join(os.getenv('ProgramData'),
                               r'Microsoft\Windows\Start Menu\Programs\Startup')

對于.lnk快捷方式,我們使用win32com解析真實(shí)路徑:

from win32com.client import Dispatch

???????shell = Dispatch('WScript.Shell')
shortcut = shell.CreateShortCut(item_path)
target_path = shortcut.TargetPath  # 獲取實(shí)際目標(biāo)

UI設(shè)計(jì)美學(xué)

我們的工具采用紫色系漸變風(fēng)格,看起來專業(yè)又不失活潑:

1. 全局樣式設(shè)置

def set_style(self):
    palette = QPalette()
    palette.setColor(QPalette.Window, QColor(250, 245, 255))  # 淺紫色背景
    palette.setColor(QPalette.Highlight, QColor(138, 43, 226))  # 紫羅蘭選中色
    QApplication.setPalette(palette)
    
    # 精致按鈕樣式
    button_style = """
    QPushButton {
        background: qlineargradient(x1:0, y1:0, x2:0, y2:1,
                                  stop:0 #e6e6fa, stop:1 #d8bfd8);
        border: 1px solid #9370db;
        border-radius: 6px;
        padding: 8px 15px;
        color: #4b0082;
    }
    """
    self.setStyleSheet(button_style)

2. 創(chuàng)新UI元素

拖拽添加區(qū)域:

def create_drop_area(self, layout):
    drop_group = QGroupBox("拖拽添加 (將文件拖到此處)")
    drop_group.setAcceptDrops(True)
    drop_group.dragEnterEvent = self.drag_enter_event
    drop_group.dropEvent = self.drop_event
    
    # 添加圖標(biāo)和提示文本...

選項(xiàng)卡設(shè)計(jì):

self.tabs = QTabWidget()
self.tabs.setTabPosition(QTabWidget.North)
self.tabs.setDocumentMode(True)
self.tabs.setStyleSheet("""
    QTabBar::tab {
        padding: 10px 20px;
        background: qlineargradient(...);
        border: 1px solid #9370db;
    }
""")

完整源碼剖析

由于源碼較長(約500行),這里重點(diǎn)分析幾個(gè)核心部分:

1. 主窗口結(jié)構(gòu)

class StartupManager(QMainWindow):
    def __init__(self):
        super().__init__()
        # 窗口基本設(shè)置
        self.setWindowTitle("電腦啟動(dòng)項(xiàng)管理工具")
        self.setGeometry(100, 100, 1000, 750)
        
        # 初始化UI
        self.set_style()
        self.init_ui()
        
        # 加載數(shù)據(jù)
        self.load_startup_items()

2. 啟動(dòng)項(xiàng)加載邏輯

def load_startup_items(self):
    self.tree.clear()
    
    # 1. 加載注冊表啟動(dòng)項(xiàng)
    user_item = QTreeWidgetItem(["當(dāng)前用戶啟動(dòng)項(xiàng)"])
    self.load_registry_startup_items(user_item, winreg.HKEY_CURRENT_USER, ...)
    
    # 2. 加載啟動(dòng)文件夾
    folder_item = QTreeWidgetItem(["啟動(dòng)文件夾項(xiàng)目"])
    self.load_startup_folder_items(folder_item)

3. 添加新啟動(dòng)項(xiàng)

def add_manual_startup_item(self):
    # 獲取表單數(shù)據(jù)
    name = self.name_input.text()
    path = self.path_input.text()
    
    # 驗(yàn)證輸入
    if not name or not path:
        QMessageBox.warning("名稱和路徑不能為空")
        return
    
    # 根據(jù)選擇的位置執(zhí)行添加
    if self.location_radio_all.isChecked():
        # 寫入HKLM注冊表(需要管理員權(quán)限)
    elif self.location_radio_folder.isChecked():
        # 創(chuàng)建快捷方式到啟動(dòng)文件夾
    else:
        # 寫入HKCU注冊表

完整源碼下載

 import os
import sys
import winreg
from PyQt5.QtWidgets import (QApplication, QMainWindow, QTreeWidget, QTreeWidgetItem, 
                             QVBoxLayout, QWidget, QHeaderView, QMenu, QFileDialog,
                             QAbstractItemView, QMessageBox, QLabel, QPushButton, 
                             QHBoxLayout, QTabWidget, QGroupBox, QFormLayout, QLineEdit,
                             QFrame, QScrollArea, QStyle)
from PyQt5.QtCore import Qt, QMimeData, QSize
from PyQt5.QtGui import QIcon, QPalette, QColor, QFont, QPixmap

class StartupManager(QMainWindow):
    def __init__(self):
        super().__init__()
        self.setWindowTitle("電腦啟動(dòng)項(xiàng)管理工具")
        self.setWindowIcon(self.style().standardIcon(QStyle.SP_ComputerIcon))
        self.setGeometry(100, 100, 1000, 750)
        
        # 設(shè)置應(yīng)用樣式
        self.set_style()
        
        self.init_ui()
        self.load_startup_items()
        
    def set_style(self):
        # 設(shè)置多彩配色方案
        palette = QPalette()
        palette.setColor(QPalette.Window, QColor(250, 245, 255))
        palette.setColor(QPalette.WindowText, QColor(80, 80, 80))
        palette.setColor(QPalette.Base, QColor(255, 255, 255))
        palette.setColor(QPalette.AlternateBase, QColor(245, 245, 255))
        palette.setColor(QPalette.ToolTipBase, QColor(255, 255, 255))
        palette.setColor(QPalette.ToolTipText, QColor(80, 80, 80))
        palette.setColor(QPalette.Text, QColor(80, 80, 80))
        palette.setColor(QPalette.Button, QColor(230, 230, 250))
        palette.setColor(QPalette.ButtonText, QColor(80, 80, 80))
        palette.setColor(QPalette.BrightText, QColor(255, 255, 255))
        palette.setColor(QPalette.Highlight, QColor(138, 43, 226))  # 紫羅蘭色
        palette.setColor(QPalette.HighlightedText, QColor(255, 255, 255))
        QApplication.setPalette(palette)
        
        # 設(shè)置全局樣式表
        style = """
        QMainWindow {
            background: qlineargradient(x1:0, y1:0, x2:1, y2:1,
                                      stop:0 #faf5ff, stop:1 #e6e6fa);
        }
        QTreeWidget {
            border: 2px solid #d8bfd8;
            border-radius: 8px;
            background-color: white;
            padding: 5px;
        }
        QTreeWidget::item {
            padding: 5px;
        }
        QTreeWidget::item:hover {
            background: #e6e6fa;
        }
        QGroupBox {
            border: 2px solid #d8bfd8;
            border-radius: 8px;
            margin-top: 15px;
            padding-top: 20px;
            background: rgba(255, 255, 255, 0.8);
        }
        QGroupBox::title {
            subcontrol-origin: margin;
            left: 15px;
            padding: 0 5px;
            color: #9370db;
            font-weight: bold;
        }
        QPushButton {
            background: qlineargradient(x1:0, y1:0, x2:0, y2:1,
                                      stop:0 #e6e6fa, stop:1 #d8bfd8);
            border: 1px solid #9370db;
            border-radius: 6px;
            padding: 8px 15px;
            min-width: 100px;
            color: #4b0082;
            font-weight: bold;
        }
        QPushButton:hover {
            background: qlineargradient(x1:0, y1:0, x2:0, y2:1,
                                      stop:0 #d8bfd8, stop:1 #e6e6fa);
        }
        QPushButton:pressed {
            background: qlineargradient(x1:0, y1:0, x2:0, y2:1,
                                      stop:0 #9370db, stop:1 #d8bfd8);
            color: white;
        }
        QLineEdit {
            border: 1px solid #d8bfd8;
            border-radius: 6px;
            padding: 8px;
            background: white;
        }
        QTabWidget::pane {
            border: 2px solid #d8bfd8;
            border-radius: 8px;
            background: rgba(255, 255, 255, 0.9);
            margin: 5px;
        }
        QTabBar::tab {
            padding: 10px 20px;
            background: qlineargradient(x1:0, y1:0, x2:0, y2:1,
                                      stop:0 #e6e6fa, stop:1 #d8bfd8);
            border: 1px solid #9370db;
            border-bottom: none;
            border-top-left-radius: 8px;
            border-top-right-radius: 8px;
            color: #4b0082;
            font-weight: bold;
        }
        QTabBar::tab:selected {
            background: white;
            margin-bottom: -1px;
        }
        QTabBar::tab:hover {
            background: qlineargradient(x1:0, y1:0, x2:0, y2:1,
                                      stop:0 #d8bfd8, stop:1 #e6e6fa);
        }
        QHeaderView::section {
            background: qlineargradient(x1:0, y1:0, x2:0, y2:1,
                                      stop:0 #e6e6fa, stop:1 #d8bfd8);
            padding: 5px;
            border: 1px solid #9370db;
            color: #4b0082;
            font-weight: bold;
        }
        QScrollArea {
            border: none;
            background: transparent;
        }
        """
        self.setStyleSheet(style)
        
    def init_ui(self):
        # 主窗口部件
        central_widget = QWidget()
        self.setCentralWidget(central_widget)
        
        # 主布局
        main_layout = QVBoxLayout(central_widget)
        main_layout.setContentsMargins(15, 15, 15, 15)
        main_layout.setSpacing(15)
        
        # 創(chuàng)建標(biāo)題欄
        self.create_title_bar(main_layout)
        
        # 創(chuàng)建選項(xiàng)卡
        self.tabs = QTabWidget()
        self.tabs.setTabPosition(QTabWidget.North)
        self.tabs.setDocumentMode(True)
        main_layout.addWidget(self.tabs)
        
        # 創(chuàng)建"查看啟動(dòng)項(xiàng)"標(biāo)簽頁
        self.create_view_tab()
        
        # 創(chuàng)建"添加啟動(dòng)項(xiàng)"標(biāo)簽頁
        self.create_add_tab()
        
        # 創(chuàng)建狀態(tài)欄
        self.statusBar().showMessage("就緒")
        
    def create_title_bar(self, layout):
        # 標(biāo)題欄布局
        title_layout = QHBoxLayout()
        
        # 圖標(biāo)
        icon_label = QLabel()
        icon_pixmap = self.style().standardIcon(QStyle.SP_ComputerIcon).pixmap(48, 48)
        icon_label.setPixmap(icon_pixmap)
        title_layout.addWidget(icon_label)
        
        # 標(biāo)題和副標(biāo)題
        text_layout = QVBoxLayout()
        title_label = QLabel("電腦啟動(dòng)項(xiàng)管理")
        title_label.setStyleSheet("font-size: 24px; font-weight: bold; color: #9370db;")
        subtitle_label = QLabel("輕松管理系統(tǒng)啟動(dòng)項(xiàng)")
        subtitle_label.setStyleSheet("font-size: 14px; color: #9370db;")
        text_layout.addWidget(title_label)
        text_layout.addWidget(subtitle_label)
        title_layout.addLayout(text_layout)
        
        title_layout.addStretch()
        
        # 刷新按鈕
        refresh_btn = QPushButton()
        refresh_btn.setIcon(self.style().standardIcon(QStyle.SP_BrowserReload))
        refresh_btn.setIconSize(QSize(24, 24))
        refresh_btn.setToolTip("刷新列表")
        refresh_btn.clicked.connect(self.load_startup_items)
        refresh_btn.setFixedSize(40, 40)
        title_layout.addWidget(refresh_btn)
        
        layout.addLayout(title_layout)
        
        # 添加分隔線
        separator = QFrame()
        separator.setFrameShape(QFrame.HLine)
        separator.setFrameShadow(QFrame.Sunken)
        separator.setStyleSheet("color: #d8bfd8;")
        layout.addWidget(separator)
    
    def create_view_tab(self):
        # 查看啟動(dòng)項(xiàng)標(biāo)簽頁
        view_tab = QWidget()
        layout = QVBoxLayout(view_tab)
        layout.setContentsMargins(10, 10, 10, 10)
        layout.setSpacing(10)
        
        # 樹形列表
        self.tree = QTreeWidget()
        self.tree.setColumnCount(4)
        self.tree.setHeaderLabels(["名稱", "狀態(tài)", "命令行/路徑", "參數(shù)"])
        self.tree.setSelectionMode(QAbstractItemView.SingleSelection)
        self.tree.setContextMenuPolicy(Qt.CustomContextMenu)
        self.tree.customContextMenuRequested.connect(self.show_context_menu)
        
        # 設(shè)置列寬
        self.tree.header().setSectionResizeMode(0, QHeaderView.ResizeToContents)
        self.tree.header().setSectionResizeMode(1, QHeaderView.ResizeToContents)
        self.tree.header().setSectionResizeMode(2, QHeaderView.Stretch)
        self.tree.header().setSectionResizeMode(3, QHeaderView.ResizeToContents)
        
        # 添加到滾動(dòng)區(qū)域
        scroll_area = QScrollArea()
        scroll_area.setWidgetResizable(True)
        scroll_area.setWidget(self.tree)
        layout.addWidget(scroll_area)
        
        self.tabs.addTab(view_tab, "查看啟動(dòng)項(xiàng)")
    
    def create_add_tab(self):
        # 添加啟動(dòng)項(xiàng)標(biāo)簽頁
        add_tab = QWidget()
        layout = QVBoxLayout(add_tab)
        layout.setContentsMargins(15, 15, 15, 15)
        layout.setSpacing(15)
        
        # 創(chuàng)建拖拽區(qū)域
        self.create_drop_area(layout)
        
        # 創(chuàng)建表單區(qū)域
        self.create_form_area(layout)
        
        self.tabs.addTab(add_tab, "添加啟動(dòng)項(xiàng)")
    
    def create_drop_area(self, layout):
        # 拖拽區(qū)域
        drop_group = QGroupBox("拖拽添加 (將文件拖到此處)")
        drop_group.setAcceptDrops(True)
        drop_group.dragEnterEvent = self.drag_enter_event
        drop_group.dropEvent = lambda e: self.drop_event(e, drop_group)
        
        drop_layout = QVBoxLayout(drop_group)
        drop_layout.setContentsMargins(20, 20, 20, 20)
        drop_layout.setSpacing(20)
        
        # 圖標(biāo)
        drop_icon = QLabel()
        drop_icon.setPixmap(self.style().standardIcon(QStyle.SP_FileIcon).pixmap(64, 64))
        drop_icon.setAlignment(Qt.AlignCenter)
        drop_layout.addWidget(drop_icon)
        
        # 文本
        drop_label = QLabel("拖拽可執(zhí)行文件或快捷方式到此處")
        drop_label.setAlignment(Qt.AlignCenter)
        drop_label.setStyleSheet("""
            font-size: 16px; 
            font-weight: bold; 
            color: #9370db;
        """)
        drop_layout.addWidget(drop_label)
        
        # 提示
        drop_hint = QLabel("支持 .exe, .lnk, .bat, .cmd 文件")
        drop_hint.setAlignment(Qt.AlignCenter)
        drop_hint.setStyleSheet("font-size: 12px; color: #9370db;")
        drop_layout.addWidget(drop_hint)
        
        layout.addWidget(drop_group)
    
    def create_form_area(self, layout):
        # 表單區(qū)域
        form_group = QGroupBox("手動(dòng)添加")
        form_layout = QFormLayout(form_group)
        form_layout.setContentsMargins(15, 15, 15, 15)
        form_layout.setSpacing(15)
        form_layout.setLabelAlignment(Qt.AlignRight)
        
        # 名稱輸入
        self.name_input = QLineEdit()
        self.name_input.setPlaceholderText("輸入啟動(dòng)項(xiàng)名稱")
        form_layout.addRow("名稱:", self.name_input)
        
        # 路徑輸入
        path_layout = QHBoxLayout()
        self.path_input = QLineEdit()
        self.path_input.setPlaceholderText("選擇或輸入程序路徑")
        browse_btn = QPushButton("瀏覽...")
        browse_btn.setIcon(self.style().standardIcon(QStyle.SP_DirOpenIcon))
        browse_btn.clicked.connect(self.browse_file)
        path_layout.addWidget(self.path_input)
        path_layout.addWidget(browse_btn)
        form_layout.addRow("路徑:", path_layout)
        
        # 參數(shù)輸入
        self.args_input = QLineEdit()
        self.args_input.setPlaceholderText("可選參數(shù)")
        form_layout.addRow("參數(shù):", self.args_input)
        
        layout.addWidget(form_group)
        
        # 添加位置選擇
        self.create_location_selector(layout)
        
        # 添加按鈕
        add_btn = QPushButton("添加啟動(dòng)項(xiàng)")
        add_btn.setIcon(self.style().standardIcon(QStyle.SP_DialogOkButton))
        add_btn.clicked.connect(self.add_manual_startup_item)
        add_btn.setStyleSheet("""
            background: qlineargradient(x1:0, y1:0, x2:0, y2:1,
                                      stop:0 #9370db, stop:1 #8a2be2);
            color: white;
            font-size: 16px;
            padding: 12px;
        """)
        layout.addWidget(add_btn)
        
        layout.addStretch()
    
    def create_location_selector(self, layout):
        # 位置選擇器
        location_group = QGroupBox("添加位置")
        location_layout = QHBoxLayout(location_group)
        location_layout.setSpacing(20)
        
        # 當(dāng)前用戶選項(xiàng)
        self.location_radio_user = QPushButton("當(dāng)前用戶")
        self.location_radio_user.setCheckable(True)
        self.location_radio_user.setChecked(True)
        self.location_radio_user.setIcon(self.style().standardIcon(QStyle.SP_ComputerIcon))
        self.location_radio_user.setStyleSheet("""
            QPushButton {
                background: qlineargradient(x1:0, y1:0, x2:0, y2:1,
                                          stop:0 #e6e6fa, stop:1 #d8bfd8);
                border: 2px solid #9370db;
                border-radius: 6px;
                padding: 10px;
            }
            QPushButton:checked {
                background: qlineargradient(x1:0, y1:0, x2:0, y2:1,
                                          stop:0 #9370db, stop:1 #8a2be2);
                color: white;
            }
        """)
        
        # 所有用戶選項(xiàng)
        self.location_radio_all = QPushButton("所有用戶")
        self.location_radio_all.setCheckable(True)
        self.location_radio_all.setIcon(self.style().standardIcon(QStyle.SP_DesktopIcon))
        self.location_radio_all.setStyleSheet(self.location_radio_user.styleSheet())
        
        # 啟動(dòng)文件夾選項(xiàng)
        self.location_radio_folder = QPushButton("啟動(dòng)文件夾")
        self.location_radio_folder.setCheckable(True)
        self.location_radio_folder.setIcon(self.style().standardIcon(QStyle.SP_DirIcon))
        self.location_radio_folder.setStyleSheet(self.location_radio_user.styleSheet())
        
        location_layout.addWidget(self.location_radio_user)
        location_layout.addWidget(self.location_radio_all)
        location_layout.addWidget(self.location_radio_folder)
        
        layout.addWidget(location_group)
    
    def load_startup_items(self):
        self.tree.clear()
        
        # 加載當(dāng)前用戶的啟動(dòng)項(xiàng)
        user_item = QTreeWidgetItem(self.tree, ["當(dāng)前用戶啟動(dòng)項(xiàng)", "", "", ""])
        user_item.setExpanded(True)
        self.load_registry_startup_items(user_item, winreg.HKEY_CURRENT_USER,
                                      r"Software\Microsoft\Windows\CurrentVersion\Run")
        
        # 加載所有用戶的啟動(dòng)項(xiàng)
        all_users_item = QTreeWidgetItem(self.tree, ["所有用戶啟動(dòng)項(xiàng)", "", "", ""])
        all_users_item.setExpanded(True)
        self.load_registry_startup_items(all_users_item, winreg.HKEY_LOCAL_MACHINE,
                                       r"Software\Microsoft\Windows\CurrentVersion\Run")
        
        # 加載啟動(dòng)文件夾中的項(xiàng)目
        startup_folder_item = QTreeWidgetItem(self.tree, ["啟動(dòng)文件夾項(xiàng)目", "", "", ""])
        startup_folder_item.setExpanded(True)
        self.load_startup_folder_items(startup_folder_item)
        
        # 切換到查看標(biāo)簽頁
        self.tabs.setCurrentIndex(0)
        self.statusBar().showMessage("啟動(dòng)項(xiàng)列表已刷新", 3000)
    
    def load_registry_startup_items(self, parent_item, hive, subkey):
        try:
            with winreg.OpenKey(hive, subkey) as key:
                i = 0
                while True:
                    try:
                        name, value, _ = winreg.EnumValue(key, i)
                        # 解析值和參數(shù)
                        path, args = self.parse_command(value)
                        
                        item = QTreeWidgetItem(parent_item)
                        item.setText(0, name)
                        item.setText(1, "已啟用")
                        item.setText(2, path)
                        item.setText(3, args)
                        
                        # 存儲(chǔ)額外信息用于刪除
                        item.setData(0, Qt.UserRole, ("registry", hive, subkey, name))
                        
                        i += 1
                    except OSError:
                        break
        except WindowsError:
            pass
    
    def load_startup_folder_items(self, parent_item):
        # 獲取當(dāng)前用戶的啟動(dòng)文件夾
        user_startup = os.path.join(os.getenv('APPDATA'), 
                                  r'Microsoft\Windows\Start Menu\Programs\Startup')
        self.load_folder_items(parent_item, user_startup, "user")
        
        # 獲取所有用戶的啟動(dòng)文件夾
        all_users_startup = os.path.join(os.getenv('ProgramData'),
                                       r'Microsoft\Windows\Start Menu\Programs\Startup')
        self.load_folder_items(parent_item, all_users_startup, "all_users")
    
    def load_folder_items(self, parent_item, folder_path, folder_type):
        if not os.path.exists(folder_path):
            return
            
        for item_name in os.listdir(folder_path):
            item_path = os.path.join(folder_path, item_name)
            
            # 如果是快捷方式,解析目標(biāo)
            if item_name.lower().endswith('.lnk'):
                try:
                    from win32com.client import Dispatch
                    shell = Dispatch('WScript.Shell')
                    shortcut = shell.CreateShortCut(item_path)
                    target_path = shortcut.TargetPath
                    arguments = shortcut.Arguments
                    working_dir = shortcut.WorkingDirectory
                    
                    # 構(gòu)建完整路徑
                    full_path = target_path
                    if working_dir:
                        full_path = os.path.join(working_dir, target_path)
                    
                    item = QTreeWidgetItem(parent_item)
                    item.setText(0, os.path.splitext(item_name)[0])
                    item.setText(1, "已啟用")
                    item.setText(2, full_path)
                    item.setText(3, arguments)
                    
                    # 存儲(chǔ)額外信息用于刪除
                    item.setData(0, Qt.UserRole, ("folder", folder_path, item_name))
                except:
                    # 如果解析快捷方式失敗,直接顯示路徑
                    item = QTreeWidgetItem(parent_item)
                    item.setText(0, os.path.splitext(item_name)[0])
                    item.setText(1, "已啟用")
                    item.setText(2, item_path)
                    item.setText(3, "")
                    item.setData(0, Qt.UserRole, ("folder", folder_path, item_name))
            else:
                # 普通文件
                item = QTreeWidgetItem(parent_item)
                item.setText(0, item_name)
                item.setText(1, "已啟用")
                item.setText(2, item_path)
                item.setText(3, "")
                item.setData(0, Qt.UserRole, ("folder", folder_path, item_name))
    
    def parse_command(self, command):
        # 簡單的命令解析,分離路徑和參數(shù)
        if command.startswith('"'):
            # 處理帶引號的路徑
            end_quote = command.find('"', 1)
            if end_quote != -1:
                path = command[1:end_quote]
                args = command[end_quote+1:].strip()
                return path, args
        else:
            # 不帶引號的路徑
            space_pos = command.find(' ')
            if space_pos != -1:
                return command[:space_pos], command[space_pos+1:].strip()
        
        # 沒有參數(shù)的情況
        return command, ""
    
    def show_context_menu(self, position):
        item = self.tree.itemAt(position)
        if not item or not item.parent():
            return
            
        menu = QMenu()
        delete_action = menu.addAction("刪除啟動(dòng)項(xiàng)")
        delete_action.setIcon(self.style().standardIcon(QStyle.SP_TrashIcon))
        delete_action.triggered.connect(lambda: self.delete_startup_item(item))
        menu.exec_(self.tree.viewport().mapToGlobal(position))
    
    def delete_startup_item(self, item):
        item_type, *item_data = item.data(0, Qt.UserRole)
        
        reply = QMessageBox.question(self, '確認(rèn)刪除', 
                                    '確定要?jiǎng)h除這個(gè)啟動(dòng)項(xiàng)嗎?', 
                                    QMessageBox.Yes | QMessageBox.No, 
                                    QMessageBox.No)
        
        if reply == QMessageBox.Yes:
            try:
                if item_type == "registry":
                    hive, subkey, name = item_data
                    with winreg.OpenKey(hive, subkey, 0, winreg.KEY_WRITE) as key:
                        winreg.DeleteValue(key, name)
                elif item_type == "folder":
                    folder_path, item_name = item_data
                    os.remove(os.path.join(folder_path, item_name))
                
                # 從樹中移除
                item.parent().removeChild(item)
                QMessageBox.information(self, "成功", "啟動(dòng)項(xiàng)已刪除")
                self.statusBar().showMessage("啟動(dòng)項(xiàng)已刪除", 3000)
            except Exception as e:
                QMessageBox.critical(self, "錯(cuò)誤", f"刪除失敗: {str(e)}")
                self.statusBar().showMessage(f"刪除失敗: {str(e)}", 3000)
    
    def browse_file(self):
        file_path, _ = QFileDialog.getOpenFileName(
            self, "選擇可執(zhí)行文件", "", 
            "可執(zhí)行文件 (*.exe *.bat *.cmd);;快捷方式 (*.lnk);;所有文件 (*.*)")
        
        if file_path:
            self.path_input.setText(file_path)
            if not self.name_input.text():
                # 自動(dòng)填充名稱
                name = os.path.splitext(os.path.basename(file_path))[0]
                self.name_input.setText(name)
            self.statusBar().showMessage(f"已選擇文件: {file_path}", 3000)
    
    def drag_enter_event(self, event):
        if event.mimeData().hasUrls():
            event.acceptProposedAction()
    
    def drop_event(self, event, drop_group):
        urls = event.mimeData().urls()
        if urls:
            file_path = urls[0].toLocalFile()
            if file_path.lower().endswith(('.exe', '.lnk', '.bat', '.cmd')):
                # 更新UI顯示
                drop_label = drop_group.findChild(QLabel)
                drop_label.setText(f"已選擇: {os.path.basename(file_path)}")
                drop_label.setStyleSheet("""
                    font-size: 16px; 
                    font-weight: bold; 
                    color: #8a2be2;
                """)
                
                # 自動(dòng)填充表單
                self.path_input.setText(file_path)
                if not self.name_input.text():
                    name = os.path.splitext(os.path.basename(file_path))[0]
                    self.name_input.setText(name)
                
                event.acceptProposedAction()
                self.statusBar().showMessage(f"已拖入文件: {file_path}", 3000)
    
    def add_manual_startup_item(self):
        name = self.name_input.text().strip()
        path = self.path_input.text().strip()
        args = self.args_input.text().strip()
        
        if not name or not path:
            QMessageBox.warning(self, "警告", "名稱和路徑不能為空")
            self.statusBar().showMessage("錯(cuò)誤: 名稱和路徑不能為空", 3000)
            return
            
        if not os.path.exists(path):
            QMessageBox.warning(self, "警告", "指定的路徑不存在")
            self.statusBar().showMessage("錯(cuò)誤: 指定的路徑不存在", 3000)
            return
        
        # 確定添加位置
        location = "user"
        if self.location_radio_all.isChecked():
            location = "all_users"
        elif self.location_radio_folder.isChecked():
            location = "folder"
        
        try:
            if location in ["user", "all_users"]:
                # 添加到注冊表
                hive = winreg.HKEY_CURRENT_USER if location == "user" else winreg.HKEY_LOCAL_MACHINE
                subkey = r"Software\Microsoft\Windows\CurrentVersion\Run"
                
                # 構(gòu)建完整命令
                command = f'"{path}"' if ' ' in path else path
                if args:
                    command += f" {args}"
                
                try:
                    with winreg.OpenKey(hive, subkey, 0, winreg.KEY_WRITE) as key:
                        winreg.SetValueEx(key, name, 0, winreg.REG_SZ, command)
                except PermissionError:
                    QMessageBox.critical(self, "錯(cuò)誤", "需要管理員權(quán)限才能添加所有用戶啟動(dòng)項(xiàng)")
                    self.statusBar().showMessage("錯(cuò)誤: 需要管理員權(quán)限", 3000)
                    return
            else:
                # 添加到啟動(dòng)文件夾
                startup_folder = os.path.join(os.getenv('APPDATA'), 
                                           r'Microsoft\Windows\Start Menu\Programs\Startup')
                
                # 如果是快捷方式,直接復(fù)制
                if path.lower().endswith('.lnk'):
                    import shutil
                    shutil.copy(path, os.path.join(startup_folder, f"{name}.lnk"))
                else:
                    # 創(chuàng)建快捷方式
                    try:
                        from win32com.client import Dispatch
                        shell = Dispatch('WScript.Shell')
                        shortcut = shell.CreateShortCut(
                            os.path.join(startup_folder, f"{name}.lnk"))
                        shortcut.TargetPath = path
                        shortcut.Arguments = args
                        shortcut.WorkingDirectory = os.path.dirname(path)
                        shortcut.save()
                    except:
                        QMessageBox.critical(self, "錯(cuò)誤", "無法創(chuàng)建快捷方式")
                        self.statusBar().showMessage("錯(cuò)誤: 無法創(chuàng)建快捷方式", 3000)
                        return
            
            QMessageBox.information(self, "成功", "啟動(dòng)項(xiàng)已添加")
            
            # 清空表單
            self.name_input.clear()
            self.path_input.clear()
            self.args_input.clear()
            
            # 重置拖拽區(qū)域
            drop_group = self.findChild(QGroupBox, "拖拽添加")
            if drop_group:
                drop_label = drop_group.findChild(QLabel)
                drop_label.setText("拖拽可執(zhí)行文件或快捷方式到此處")
                drop_label.setStyleSheet("""
                    font-size: 16px; 
                    font-weight: bold; 
                    color: #9370db;
                """)
            
            # 刷新列表
            self.load_startup_items()
            self.statusBar().showMessage("啟動(dòng)項(xiàng)已成功添加", 3000)
            
        except Exception as e:
            QMessageBox.critical(self, "錯(cuò)誤", f"添加失敗: {str(e)}")
            self.statusBar().showMessage(f"添加失敗: {str(e)}", 3000)

if __name__ == "__main__":
    app = QApplication(sys.argv)
    
    # 設(shè)置應(yīng)用程序字體
    font = QFont("微軟雅黑", 10)
    app.setFont(font)
    
    window = StartupManager()
    window.show()
    sys.exit(app.exec_())

擴(kuò)展思考

我們的工具還可以進(jìn)一步優(yōu)化:

1.啟動(dòng)延遲設(shè)置:通過/delay參數(shù)或任務(wù)計(jì)劃程序?qū)崿F(xiàn)分批啟動(dòng)

2.啟動(dòng)影響評估:監(jiān)控各啟動(dòng)項(xiàng)的資源占用情況

3.云同步功能:將配置保存到云端,多設(shè)備同步

4.黑白名單機(jī)制:自動(dòng)識別可疑啟動(dòng)項(xiàng)

5.管理員權(quán)限自動(dòng)提權(quán):使用ctypes調(diào)用ShellExecute以管理員身份運(yùn)行

import ctypes
ctypes.windll.shell32.ShellExecuteW(None, "runas", sys.executable, __file__, None, 1)

總結(jié)

通過本項(xiàng)目,我們學(xué)到了:

  • PyQt5高級UI開發(fā) - 自定義樣式、復(fù)雜布局、拖放功能
  • Windows注冊表操作 - 安全讀寫系統(tǒng)關(guān)鍵配置
  • 系統(tǒng)工具開發(fā)思路 - 從用戶需求出發(fā)設(shè)計(jì)功能
  • 異常處理重要性 - 特別是涉及系統(tǒng)級操作時(shí)

完整代碼已在上文提供,建議大家:

  • 先理解核心邏輯
  • 分段測試各個(gè)功能模塊
  • 嘗試添加自己的創(chuàng)新功能

以上就是Python+PyQt5開發(fā)一個(gè)Windows電腦啟動(dòng)項(xiàng)管理神器的詳細(xì)內(nèi)容,更多關(guān)于Python電腦啟動(dòng)項(xiàng)管理的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • Python登錄注冊驗(yàn)證功能實(shí)現(xiàn)

    Python登錄注冊驗(yàn)證功能實(shí)現(xiàn)

    本篇文章給大家整理了用python實(shí)現(xiàn)登陸注冊驗(yàn)證的基本會(huì)員功能,對此有需要的朋友可以參考下。
    2018-06-06
  • 徹底解決Python包下載慢問題

    徹底解決Python包下載慢問題

    這篇文章主要介紹了徹底解決Python包下載慢問題,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-11-11
  • Python中下劃線含義詳解

    Python中下劃線含義詳解

    大家好,本篇文章主要講的是Python中下劃線含義詳解,感興趣的同學(xué)趕快來看一看吧,對你有幫助的話記得收藏一下,方便下次瀏覽
    2022-01-01
  • 一篇文章讓你快速掌握Pandas可視化圖表

    一篇文章讓你快速掌握Pandas可視化圖表

    大家都知道Pandas是基于Python平臺的大數(shù)據(jù)分析與處理的利器,它可以把十分復(fù)雜的可視化過程,變得簡單一點(diǎn),這篇文章主要給大家介紹了關(guān)于Pandas可視化圖表的相關(guān)資料,需要的朋友可以參考下
    2021-08-08
  • 教你用Python實(shí)現(xiàn)Excel表格處理

    教你用Python實(shí)現(xiàn)Excel表格處理

    今天教各位小伙伴怎么用Python處理excel,文中有非常詳細(xì)的代碼示例及相關(guān)知識總結(jié),對正在學(xué)習(xí)python的小伙伴們很有幫助,需要的朋友可以參考下
    2021-05-05
  • 詳解Python中生成隨機(jī)數(shù)據(jù)的示例詳解

    詳解Python中生成隨機(jī)數(shù)據(jù)的示例詳解

    在日常工作編程中存在著各種隨機(jī)事件,同樣在編程中生成隨機(jī)數(shù)字的時(shí)候也是一樣。每當(dāng)在?Python?中生成隨機(jī)數(shù)據(jù)、字符串或數(shù)字時(shí),最好至少大致了解這些數(shù)據(jù)是如何生成的。所以本文將詳細(xì)為大家講解一下Python是如何生成隨機(jī)數(shù)據(jù),需要的可以參考一下
    2022-04-04
  • Python中的單行、多行、中文注釋方法

    Python中的單行、多行、中文注釋方法

    今天小編就為大家分享一篇Python中的單行、多行、中文注釋方法,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2018-07-07
  • pandas如何實(shí)現(xiàn)兩個(gè)dataframe相減

    pandas如何實(shí)現(xiàn)兩個(gè)dataframe相減

    這篇文章主要介紹了pandas如何實(shí)現(xiàn)兩個(gè)dataframe相減方式,具有很好的參考價(jià)值,希望對大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-02-02
  • 用Python實(shí)現(xiàn)一個(gè)簡單的多線程TCP服務(wù)器的教程

    用Python實(shí)現(xiàn)一個(gè)簡單的多線程TCP服務(wù)器的教程

    這篇文章主要介紹了用Python實(shí)現(xiàn)一個(gè)簡單的多線程TCP服務(wù)器的教程,示例的運(yùn)行環(huán)境為Windows操作系統(tǒng),需要的朋友可以參考下
    2015-05-05
  • 關(guān)于python線程池的四種實(shí)現(xiàn)方式

    關(guān)于python線程池的四種實(shí)現(xiàn)方式

    這篇文章主要介紹了關(guān)于python線程池的四種實(shí)現(xiàn)方式,一個(gè)程序運(yùn)行起來后,一定有一個(gè)執(zhí)行代碼的東西,這個(gè)東西就是線程,需要的朋友可以參考下
    2023-04-04

最新評論