使用 Python构建 Windows 进程管理器应用程序

在这篇博客中,我们将探讨如何使用 wxPython 构建一个简单的 Windows 进程管理器应用程序。这个应用程序允许用户列出当前系统上的所有进程,选择和终止进程,并将特定进程保存到文件中以供将来加载。

C:\pythoncode\new\manageprocess.py

全部代码

python 复制代码
import wx
import psutil
import os
import signal

class ProcessManager(wx.Frame):
    def __init__(self, parent, title):
        super(ProcessManager,self).__init__(parent, title=title, size=(800, 500))

        self.panel = wx.Panel(self)

        self.search_box = wx.TextCtrl(self.panel, style=wx.TE_PROCESS_ENTER)
        self.Bind(wx.EVT_TEXT_ENTER, self.OnSearchProcess, self.search_box)

        self.btn_list_processes = wx.Button(self.panel, label='List All Processes')

        # Create ListView1 with a checkbox column
        self.process_listview = wx.ListView(self.panel, style=wx.LC_REPORT | wx.LC_HRULES | wx.LC_VRULES)
        self.process_listview.InsertColumn(0, '', width=40)  # Checkbox column
        self.process_listview.InsertColumn(1, 'Process Name', width=200)
        self.process_listview.InsertColumn(2, 'PID', width=100)
        self.process_listview.InsertColumn(3, 'CPU %', width=100)
        self.process_listview.InsertColumn(4, 'RAM %', width=100)

        self.selected_listview = wx.ListView(self.panel, style=wx.LC_REPORT)
        self.selected_listview.InsertColumn(0, 'Process Name', width=200)
        self.selected_listview.InsertColumn(1, 'PID', width=100)

        self.btn_select_all = wx.Button(self.panel, label='Select All')
        self.btn_deselect_all = wx.Button(self.panel, label='Deselect All')
        self.btn_add_to_listview2 = wx.Button(self.panel, label='Add to ListView2')
        self.btn_kill_processes = wx.Button(self.panel, label='Kill Selected Processes')
        self.btn_kill_by_name = wx.Button(self.panel, label='Kill by Name')
        self.btn_save = wx.Button(self.panel, label='Save')
        self.btn_load = wx.Button(self.panel, label='Load')
        self.btn_delete_selected = wx.Button(self.panel, label='Delete Selected')

        # Organize layout with BoxSizers
        main_sizer = wx.BoxSizer(wx.VERTICAL)
        search_sizer = wx.BoxSizer(wx.HORIZONTAL)
        listview1_sizer = wx.BoxSizer(wx.VERTICAL)
        button_sizer = wx.BoxSizer(wx.HORIZONTAL)
        listview2_sizer = wx.BoxSizer(wx.VERTICAL)

        search_sizer.Add(self.search_box, 1, wx.EXPAND | wx.ALL, 5)
        search_sizer.Add(self.btn_list_processes, 0, wx.EXPAND | wx.ALL, 5)

        listview1_sizer.Add(search_sizer, 0, wx.EXPAND | wx.ALL, 5)
        listview1_sizer.Add(self.process_listview, 1, wx.EXPAND | wx.ALL, 5)

        button_sizer.Add(self.btn_select_all, 0, wx.EXPAND | wx.ALL, 5)
        button_sizer.Add(self.btn_deselect_all, 0, wx.EXPAND | wx.ALL, 5)
        button_sizer.Add(self.btn_add_to_listview2, 0, wx.EXPAND | wx.ALL, 5)

        listview1_sizer.Add(button_sizer, 0, wx.ALIGN_CENTER | wx.ALL, 5)

        listview2_sizer.Add(self.selected_listview, 1, wx.EXPAND | wx.ALL, 5)
        listview2_sizer.Add(self.btn_kill_processes, 0, wx.EXPAND | wx.ALL, 5)
        listview2_sizer.Add(self.btn_kill_by_name, 0, wx.EXPAND | wx.ALL, 5)
        listview2_sizer.Add(self.btn_save, 0, wx.EXPAND | wx.ALL, 5)
        listview2_sizer.Add(self.btn_load, 0, wx.EXPAND | wx.ALL, 5)
        listview2_sizer.Add(self.btn_delete_selected, 0, wx.EXPAND | wx.ALL, 5)

        main_sizer.Add(listview1_sizer, 1, wx.EXPAND | wx.ALL, 5)
        main_sizer.Add(listview2_sizer, 1, wx.EXPAND | wx.ALL, 5)

        self.panel.SetSizer(main_sizer)

        self.Bind(wx.EVT_BUTTON, self.OnListProcesses, self.btn_list_processes)
        self.Bind(wx.EVT_BUTTON, self.OnKillProcesses, self.btn_kill_processes)
        self.Bind(wx.EVT_BUTTON, self.OnKillProcessesByName, self.btn_kill_by_name)
        self.Bind(wx.EVT_BUTTON, self.OnSaveProcesses, self.btn_save)
        self.Bind(wx.EVT_BUTTON, self.OnLoadProcesses, self.btn_load)
        self.Bind(wx.EVT_BUTTON, self.OnSelectAll, self.btn_select_all)
        self.Bind(wx.EVT_BUTTON, self.OnDeselectAll, self.btn_deselect_all)
        self.Bind(wx.EVT_BUTTON, self.OnAddToListView2, self.btn_add_to_listview2)
        self.Bind(wx.EVT_BUTTON, self.OnDeleteSelected, self.btn_delete_selected)

        self.Show()

    def OnListProcesses(self,event):
        self.process_listview.DeleteAllItems()
        for proc in psutil.process_iter(['pid', 'name', 'cpu_percent', 'memory_percent']):
            index = self.process_listview.InsertItem(self.process_listview.GetItemCount(), '')
            self.process_listview.SetItem(index, 1, proc.info['name'])
            self.process_listview.SetItem(index, 2, str(proc.info['pid']))
            self.process_listview.SetItem(index, 3, f"{proc.info['cpu_percent']:.1f}")
            self.process_listview.SetItem(index, 4, f"{proc.info['memory_percent']:.1f}")

    def OnSearchProcess(self,event):
        search_query = self.search_box.GetValue().lower()
        self.process_listview.DeleteAllItems()
        for proc in psutil.process_iter(['pid', 'name', 'cpu_percent', 'memory_percent']):
            if search_query in proc.info['name'].lower():
                index = self.process_listview.InsertItem(self.process_listview.GetItemCount(), '')
                self.process_listview.SetItem(index, 1, proc.info['name'])
                self.process_listview.SetItem(index, 2, str(proc.info['pid']))
                self.process_listview.SetItem(index, 3, f"{proc.info['cpu_percent']:.1f}")
                self.process_listview.SetItem(index, 4, f"{proc.info['memory_percent']:.1f}")

    def OnKillProcesses(self,event):
        count = self.process_listview.GetItemCount()
        for i in range(count):
            if self.process_listview.GetItemState(i, wx.LIST_STATE_SELECTED):
                pid = int(self.process_listview.GetItemText(i, 2))
                try:
                    os.kill(pid, signal.SIGTERM)
                except Exception as e:
                    wx.MessageBox(f"Error killing process {pid}: {str(e)}", "Error", wx.OK | wx.ICON_ERROR)
        self.OnListProcesses(event)

    def OnKillProcessesByName(self,event):
        process_names = [self.selected_listview.GetItemText(i) for i in range(self.selected_listview.GetItemCount())]
        for proc in psutil.process_iter(['name', 'pid']):
            if proc.info['name'] in process_names:
                try:
                    os.kill(proc.info['pid'], signal.SIGTERM)
                except Exception as e:
                    wx.MessageBox(f"Error killing process {proc.info['pid']}: {str(e)}", "Error", wx.OK | wx.ICON_ERROR)

    def OnSaveProcesses(self,event):
        with open("processes.txt","w") as file:
            count = self.selected_listview.GetItemCount()
            for i in range(count):
                process_name = self.selected_listview.GetItemText(i)
                process_pid = self.selected_listview.GetItemText(i, 1)
                file.write(f"{process_name},{process_pid}\n")

    def OnLoadProcesses(self,event):
        self.selected_listview.DeleteAllItems()
        if os.path.exists("processes.txt"):
            with open("processes.txt","r") as file:
                for line in file:
                    process_name, process_pid = line.strip().split(',')
                    index = self.selected_listview.InsertItem(self.selected_listview.GetItemCount(), process_name)
                    self.selected_listview.SetItem(index, 1, process_pid)

    def OnSelectAll(self,event): 
        count = self.process_listview.GetItemCount()
        for i in range(count):
            self.process_listview.SetItemState(i, wx.LIST_STATE_SELECTED, wx.LIST_STATE_SELECTED)

    def OnDeselectAll(self,event):
        count = self.process_listview.GetItemCount()
        for i in range(count):
            self.process_listview.SetItemState(i, 0, wx.LIST_STATE_SELECTED)

    def OnAddToListView2(self,event):
        count = self.process_listview.GetItemCount()
        for i in range(count):
            if self.process_listview.GetItemState(i, wx.LIST_STATE_SELECTED):
                process_name = self.process_listview.GetItemText(i, 1)
                process_pid = self.process_listview.GetItemText(i, 2)
                index = self.selected_listview.InsertItem(self.selected_listview.GetItemCount(), process_name)
                self.selected_listview.SetItem(index, 1, process_pid)

    def OnDeleteSelected(self,event):
        count = self.selected_listview.GetItemCount()
        for i in range(count - 1, -1, -1):
            if self.selected_listview.GetItemState(i, wx.LIST_STATE_SELECTED):
                self.selected_listview.DeleteItem(i)

if __name__ == "__main__":
    app = wx.App(False)
    frame = ProcessManager(None, "Process Manager")
    app.MainLoop()

项目概述

我们的目标是构建一个图形用户界面 (GUI) 应用程序,主要功能包括:

  1. 列出所有进程:列出当前系统上的所有进程,并显示进程名、PID、CPU 和内存占用情况。
  2. 搜索进程:通过输入框搜索指定进程名称,并显示匹配结果。
  3. 选择和终止进程:通过复选框选择多个进程并终止它们。
  4. 保存和加载进程列表:将选定的进程保存到文本文件中,并从文件加载这些进程。
  5. 进程管理:添加功能来按名称终止进程,并从列表中删除选中的项。

准备工作

在开始之前,确保你已经安装了 Python 和 wxPython。你可以通过以下命令安装 wxPython:

bash 复制代码
pip install wxPython

构建应用程序

下面是我们将要实现的完整代码。你可以直接复制到你的 IDE 中并运行。

python 复制代码
import wx
import psutil
import os
import signal

class ProcessManager(wx.Frame):
    def __init__(self, parent, title):
        super(ProcessManager, self).__init__(parent, title=title, size=(800, 500))

        self.panel = wx.Panel(self)

        # 搜索框
        self.search_box = wx.TextCtrl(self.panel, style=wx.TE_PROCESS_ENTER)
        self.Bind(wx.EVT_TEXT_ENTER, self.OnSearchProcess, self.search_box)

        # 列出所有进程按钮
        self.btn_list_processes = wx.Button(self.panel, label='List All Processes')

        # 创建 ListView1 并添加复选框列
        self.process_listview = wx.ListView(self.panel, style=wx.LC_REPORT | wx.LC_HRULES | wx.LC_VRULES)
        self.process_listview.InsertColumn(0, '', width=40)  # 复选框列
        self.process_listview.InsertColumn(1, 'Process Name', width=200)
        self.process_listview.InsertColumn(2, 'PID', width=100)
        self.process_listview.InsertColumn(3, 'CPU %', width=100)
        self.process_listview.InsertColumn(4, 'RAM %', width=100)

        self.selected_listview = wx.ListView(self.panel, style=wx.LC_REPORT)
        self.selected_listview.InsertColumn(0, 'Process Name', width=200)
        self.selected_listview.InsertColumn(1, 'PID', width=100)

        # 各种功能按钮
        self.btn_select_all = wx.Button(self.panel, label='Select All')
        self.btn_deselect_all = wx.Button(self.panel, label='Deselect All')
        self.btn_add_to_listview2 = wx.Button(self.panel, label='Add to ListView2')
        self.btn_kill_processes = wx.Button(self.panel, label='Kill Selected Processes')
        self.btn_kill_by_name = wx.Button(self.panel, label='Kill by Name')
        self.btn_save = wx.Button(self.panel, label='Save')
        self.btn_load = wx.Button(self.panel, label='Load')
        self.btn_delete_selected = wx.Button(self.panel, label='Delete Selected')

        # 使用 BoxSizers 组织布局
        main_sizer = wx.BoxSizer(wx.VERTICAL)
        search_sizer = wx.BoxSizer(wx.HORIZONTAL)
        listview1_sizer = wx.BoxSizer(wx.VERTICAL)
        button_sizer = wx.BoxSizer(wx.HORIZONTAL)
        listview2_sizer = wx.BoxSizer(wx.VERTICAL)

        # 将搜索框和按钮添加到布局中
        search_sizer.Add(self.search_box, 1, wx.EXPAND | wx.ALL, 5)
        search_sizer.Add(self.btn_list_processes, 0, wx.EXPAND | wx.ALL, 5)

        # 将 ListView1 和按钮添加到布局中
        listview1_sizer.Add(search_sizer, 0, wx.EXPAND | wx.ALL, 5)
        listview1_sizer.Add(self.process_listview, 1, wx.EXPAND | wx.ALL, 5)

        button_sizer.Add(self.btn_select_all, 0, wx.EXPAND | wx.ALL, 5)
        button_sizer.Add(self.btn_deselect_all, 0, wx.EXPAND | wx.ALL, 5)
        button_sizer.Add(self.btn_add_to_listview2, 0, wx.EXPAND | wx.ALL, 5)

        listview1_sizer.Add(button_sizer, 0, wx.ALIGN_CENTER | wx.ALL, 5)

        # 将 ListView2 和其他按钮添加到布局中
        listview2_sizer.Add(self.selected_listview, 1, wx.EXPAND | wx.ALL, 5)
        listview2_sizer.Add(self.btn_kill_processes, 0, wx.EXPAND | wx.ALL, 5)
        listview2_sizer.Add(self.btn_kill_by_name, 0, wx.EXPAND | wx.ALL, 5)
        listview2_sizer.Add(self.btn_save, 0, wx.EXPAND | wx.ALL, 5)
        listview2_sizer.Add(self.btn_load, 0, wx.EXPAND | wx.ALL, 5)
        listview2_sizer.Add(self.btn_delete_selected, 0, wx.EXPAND | wx.ALL, 5)

        main_sizer.Add(listview1_sizer, 1, wx.EXPAND | wx.ALL, 5)
        main_sizer.Add(listview2_sizer, 1, wx.EXPAND | wx.ALL, 5)

        self.panel.SetSizer(main_sizer)

        # 绑定事件处理
        self.Bind(wx.EVT_BUTTON, self.OnListProcesses, self.btn_list_processes)
        self.Bind(wx.EVT_BUTTON, self.OnKillProcesses, self.btn_kill_processes)
        self.Bind(wx.EVT_BUTTON, self.OnKillProcessesByName, self.btn_kill_by_name)
        self.Bind(wx.EVT_BUTTON, self.OnSaveProcesses, self.btn_save)
        self.Bind(wx.EVT_BUTTON, self.OnLoadProcesses, self.btn_load)
        self.Bind(wx.EVT_BUTTON, self.OnSelectAll, self.btn_select_all)
        self.Bind(wx.EVT_BUTTON, self.OnDeselectAll, self.btn_deselect_all)
        self.Bind(wx.EVT_BUTTON, self.OnAddToListView2, self.btn_add_to_listview2)
        self.Bind(wx.EVT_BUTTON, self.OnDeleteSelected, self.btn_delete_selected)

        self.Show()

    def OnListProcesses(self, event):
        self.process_listview.DeleteAllItems()
        for proc in psutil.process_iter(['pid', 'name', 'cpu_percent', 'memory_percent']):
            index = self.process_listview.InsertItem(self.process_listview.GetItemCount(), '')
            self.process_listview.SetItem(index, 1, proc.info['name'])
            self.process_listview.SetItem(index, 2, str(proc.info['pid']))
            self.process_listview.SetItem(index, 3, f"{proc.info['cpu_percent']:.1f}")
            self.process_listview.SetItem(index, 4, f"{proc.info['memory_percent']:.1f}")

    def OnSearchProcess(self, event):
        search_query = self.search_box.GetValue().lower()
        self.process_listview.DeleteAllItems()
        for proc in psutil.process_iter(['pid', 'name', 'cpu_percent', 'memory_percent']):
            if search_query in proc.info['name'].lower():
                index = self.process_listview.InsertItem(self.process_listview.GetItemCount(), '')
                self.process_listview.SetItem(index, 1, proc.info['name'])
                self.process_listview.SetItem(index, 2, str(proc.info['pid']))
                self.process_listview.SetItem(index, 3, f"{proc.info['cpu_percent']:.1f}")
                self.process_listview.SetItem(index, 4, f"{proc.info['memory_percent']:.1f}")

    def OnKillProcesses(self, event):
        count = self.process_listview.GetItemCount()
        for i in range(count):
            if self.process_listview.GetItemState(i, wx.LIST_STATE_SELECTED):
                pid = int(self.process_listview.GetItemText(i, 2))
                try:
                    os.kill(pid, signal.SIGTERM)
                except Exception as e:
                    wx.MessageBox(f"Error killing process {pid}: {str(e)}", "Error", wx.OK | wx.ICON_ERROR)
        self.OnListProcesses(event)

    def OnKillProcessesByName(self, event):
        process_names = [self.selected_listview.GetItemText(i) for i in range(self.selected_listview.GetItemCount())]
        for proc in psutil.process_iter(['name', 'pid']):
            if proc.info['name'] in process_names:
                try:
                    os.kill(proc.info['pid'], signal.SIGTERM)
                except Exception as e:
                    wx.MessageBox(f"Error killing process {proc.info['pid']}: {str(e)}", "Error", wx.OK | wx.ICON_ERROR)

    def OnSaveProcesses(self, event):
        with open

('saved_processes.txt', 'w') as f:
            for i in range(self.selected_listview.GetItemCount()):
                process_name = self.selected_listview.GetItemText(i)
                process_pid = self.selected_listview.GetItemText(i, 1)
                f.write(f"{process_name},{process_pid}\n")

    def OnLoadProcesses(self, event):
        self.selected_listview.DeleteAllItems()
        try:
            with open('saved_processes.txt', 'r') as f:
                for line in f.readlines():
                    process_name, process_pid = line.strip().split(',')
                    index = self.selected_listview.InsertItem(self.selected_listview.GetItemCount(), process_name)
                    self.selected_listview.SetItem(index, 1, process_pid)
        except FileNotFoundError:
            wx.MessageBox("No saved processes found.", "Error", wx.OK | wx.ICON_ERROR)

    def OnSelectAll(self, event):
        count = self.process_listview.GetItemCount()
        for i in range(count):
            self.process_listview.CheckItem(i)

    def OnDeselectAll(self, event):
        count = self.process_listview.GetItemCount()
        for i in range(count):
            self.process_listview.CheckItem(i, False)

    def OnAddToListView2(self, event):
        count = self.process_listview.GetItemCount()
        for i in range(count):
            if self.process_listview.IsItemChecked(i):
                process_name = self.process_listview.GetItemText(i, 1)
                process_pid = self.process_listview.GetItemText(i, 2)
                index = self.selected_listview.InsertItem(self.selected_listview.GetItemCount(), process_name)
                self.selected_listview.SetItem(index, 1, process_pid)

    def OnDeleteSelected(self, event):
        count = self.selected_listview.GetItemCount()
        for i in range(count - 1, -1, -1):
            if self.selected_listview.GetItemState(i, wx.LIST_STATE_SELECTED):
                self.selected_listview.DeleteItem(i)

if __name__ == "__main__":
    app = wx.App(False)
    frame = ProcessManager(None, "Process Manager")
    app.MainLoop()

代码解释

1. 初始化界面

ProcessManager 类的 __init__ 方法中,我们设置了窗口的基本布局,并添加了所有必要的控件,包括 ListView、按钮和搜索框。我们还绑定了所有按钮的事件处理方法。

2. 列出所有进程

OnListProcesses 方法中,我们使用 psutil.process_iter 获取所有正在运行的进程,并将它们显示在 ListView1 中。我们显示了进程名称、PID、CPU 使用率和内存使用率。

3. 搜索进程

OnSearchProcess 方法通过搜索框输入的内容进行过滤,并在 ListView1 中显示匹配的进程。

4. 选择和终止进程

我们可以使用复选框选择一个或多个进程,并通过 OnKillProcessesOnKillProcessesByName 方法终止它们。

5. 保存和加载进程列表

OnSaveProcesses 方法将选中的进程保存到一个文本文件中,而 OnLoadProcesses 方法则从文件加载这些进程并显示在 ListView2 中。

6. 全选和全不选

通过 OnSelectAllOnDeselectAll 方法,我们可以选择或取消选择 ListView1 中的所有项。

效果如下

总结

这个小型的进程管理器应用程序展示了如何使用 wxPython 构建一个功能强大的桌面应用。通过整合 psutil 和 wxPython,我们可以轻松地管理和监控系统进程,为用户提供了便捷的工具。

你可以进一步扩展这个应用程序,例如添加更多的进程管理功能,或者优化界面布局和用户体验。希望这篇博客对你有所帮助,并激发你在 Python 开发中的更多创意!

相关推荐
Channing Lewis13 分钟前
flask常见问答题
后端·python·flask
Channing Lewis14 分钟前
如何保护 Flask API 的安全性?
后端·python·flask
水兵没月1 小时前
钉钉群机器人设置——python版本
python·机器人·钉钉
我想学LINUX2 小时前
【2024年华为OD机试】 (A卷,100分)- 微服务的集成测试(JavaScript&Java & Python&C/C++)
java·c语言·javascript·python·华为od·微服务·集成测试
数据小爬虫@5 小时前
深入解析:使用 Python 爬虫获取苏宁商品详情
开发语言·爬虫·python
健胃消食片片片片5 小时前
Python爬虫技术:高效数据收集与深度挖掘
开发语言·爬虫·python
gxhlh6 小时前
局域网中 Windows 与 Mac 互相远程连接的最佳方案
windows·macos
ℳ₯㎕ddzོꦿ࿐8 小时前
解决Python 在 Flask 开发模式下定时任务启动两次的问题
开发语言·python·flask
CodeClimb8 小时前
【华为OD-E卷 - 第k个排列 100分(python、java、c++、js、c)】
java·javascript·c++·python·华为od
一水鉴天8 小时前
为AI聊天工具添加一个知识系统 之63 详细设计 之4:AI操作系统 之2 智能合约
开发语言·人工智能·python