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

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

全部代码

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:

pip install wxPython

构建应用程序

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

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

  • 7
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值