使用 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 开发中的更多创意!

相关推荐
萧鼎30 分钟前
Python并发编程库:Asyncio的异步编程实战
开发语言·数据库·python·异步
弗锐土豆31 分钟前
Windows系统中Oracle VM VirtualBox的安装
windows·虚拟机·virtualbox
学地理的小胖砸31 分钟前
【一些关于Python的信息和帮助】
开发语言·python
疯一样的码农31 分钟前
Python 继承、多态、封装、抽象
开发语言·python
秋の花41 分钟前
【JAVA基础】Java集合基础
java·开发语言·windows
Python大数据分析@1 小时前
python操作CSV和excel,如何来做?
开发语言·python·excel
黑叶白树1 小时前
简单的签到程序 python笔记
笔记·python
Shy9604181 小时前
Bert完形填空
python·深度学习·bert
上海_彭彭2 小时前
【提效工具开发】Python功能模块执行和 SQL 执行 需求整理
开发语言·python·sql·测试工具·element
zhongcx012 小时前
使用Python查找大文件的实用脚本
python