首先 我们还是在QT编译器下进行
我们在widget窗口下创建这样一个界面
是一个TableWidget表格 包含了进程名称 进程id 线程数这几个数据
我们初始设置为300行
同时 我们设置了一个按钮 来控制结束进程的操作
首先 我们在Widget的构造函数中
为这个表格设置单行选择的行为 ui->tableWidget->setSelectionBehavior(QTableWidget::SelectRows);
同时又不想让他支持Ctrl、Shift、 Ctrl+A等操作方法
tableWidget->setSelectionMode(QAbstractItemView::SingleSelection);
然后我们设置一个接口
showProess()用来将我门的进程显示在表格中
我们如果想或渠道系统的进程 需要先引入头文件
#include <windows.h>
#include <tlhelp32.h>
然后再接口函数void showProess();中进行操作
先定义一个PROCESSENTRY32 类型的结构体pe
然后对结构体的大小进行设置
pe.dwSize = sizeof(pe);
之后我们用到了CreateToolhelp32Snapshot函数来获取进程信息的链表
这里介绍一下
CreateToolhelp32Snapshot函数
原型:
HANDLE WINAPI CreateToolhelp32Snapshot(
_In_ DWORD dwFlags, //用来指定“快照”中需要返回的对象,可以是TH32CS_SNAPPROCESS等
_In_ DWORD th32ProcessID //一个进程ID号,用来指定要获取哪一个进程的快照,当获取系统进程列表或获取 当前进程快照时可以设为0
参数1:
要包含在快照中的系统部分。此参数可以是以下一个或多个值。
价值 | 意义 |
---|---|
TH32CS_INHERIT 0x80000000 | 指示快照句柄是可继承的。 |
TH32CS_SNAPALL | 包括系统中的所有进程和线程,以及 th32ProcessID 中指定的进程的堆和模块。等效于指定使用 OR 运算组合的TH32CS_SNAPHEAPLIST、TH32CS_SNAPMODULE、TH32CS_SNAPPROCESS和TH32CS_SNAPTHREAD值(“|”)。 |
TH32CS_SNAPHEAPLIST 0x00000001 | 包括快照中 th32ProcessID 中指定的进程的所有堆。若要枚举堆,请参阅 Heap32ListFirst。 |
TH32CS_SNAPMODULE 0x00000008 | 包括快照中 th32ProcessID 中指定的进程的所有模块。要枚举模块,请参阅 Module32First。如果函数失败并ERROR_BAD_LENGTH,请重试该函数,直到成功为止。 64 位窗口: 在 32 位进程中使用此标志包括 th32ProcessID 中指定的进程的 32 位模块,而在 64 位进程中使用此标志包括 64 位模块。要从 64 位进程中包括 th32ProcessID 中指定的进程的 32 位模块,请使用 TH32CS_SNAPMODULE32 标志。 |
TH32CS_SNAPMODULE32 0x00000010 | 从 64 位进程调用时,在快照中包括 th32ProcessID 中指定的进程的所有 32 位模块。此标志可以与TH32CS_SNAPMODULE或TH32CS_SNAPALL结合使用。如果函数失败并ERROR_BAD_LENGTH,请重试该函数,直到成功为止。 |
TH32CS_SNAPPROCESS 0x00000002 | 在快照中包括系统中的所有进程。若要枚举进程,请参阅进程 32First。 |
TH32CS_SNAPTHREAD 0x00000004 | 在快照中包括系统中的所有线程。要枚举线程,请参阅 Thread32First。 要标识属于特定进程的线程,请在枚举线程时将其进程标识符与 THREADENTRY32 结构的 th32OwnerProcessID 成员进行比较。 |
);
参数2:
[in] th32ProcessID
要包含在快照中的进程的进程标识符。此参数可以为零,以指示当前进程。当指定了TH32CS_SNAPHEAPLIST、TH32CS_SNAPMODULE、TH32CS_SNAPMODULE32或TH32CS_SNAPALL值时,将使用此参数。否则,将忽略它,并将所有进程都包含在快照中。
如果指定的进程是空闲进程或 CSRSS 进程之一,则此函数将失败,并且ERROR_ACCESS_DENIED最后一个错误代码,因为它们的访问限制会阻止用户级代码打开它们。
如果指定的进程是 64 位进程,而调用方是 32 位进程,则此函数将失败,并且最后一个错误代码为 ERROR_PARTIAL_COPY (299)。
返回值
如果函数成功,它将返回指定快照的打开句柄。
如果函数失败,它将返回INVALID_HANDLE_VALUE。若要获取扩展的错误信息,请调用 GetLastError。可能的错误代码包括ERROR_BAD_LENGTH。
在介绍一下
process32First()
是一个进程获取函数,当我们利用函数CreateToolhelp32Snapshot()获得当前运行进程的快照后,我们可以利用process32First函数来获得第一个进程的句柄.
这里我们添加了一个
HANDLE hSnopShot=CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0);
用hSnopShot来记录句柄
在定义一个bFlag来记录bool bFlag= Process32First(hSnopShot,&pe);
判断我们获取到的链表的头是否为空
process32Next()
判断我们获取到的链表的节点的下一个是否为空
之后遍历
往表格上写:
pe.szExeFile:进程名称
pe.th32ProcessID:进程ID
pe.cntThreads:线程数
while(bFlag)
{
//name
str=QString::fromWCharArray(pe.szExeFile);
ui->tableWidget->setItem(i,0,new QTableWidgetItem(str));
//process
str=QString::number(pe.th32ProcessID);
ui->tableWidget->setItem(i,1,new QTableWidgetItem(str));
str=QString::number(pe.cntThreads);
ui->tableWidget->setItem(i,2,new QTableWidgetItem(str));
bFlag=Process32Next(hSnopShot,&pe);
i++;
}
void Widget::showProess()
{
PROCESSENTRY32 pe;
//在使用这个结构前,先设置它的大小
pe.dwSize = sizeof(pe);
//获取进程信息的链表
HANDLE hSnopShot=CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0);
if(hSnopShot==INVALID_HANDLE_VALUE)
return ;
//获取链表的头
bool bFlag= Process32First(hSnopShot,&pe);
int i=0;
QString str;
//遍历链表
while(bFlag)
{
//name
str=QString::fromWCharArray(pe.szExeFile);
ui->tableWidget->setItem(i,0,new QTableWidgetItem(str));
//process
str=QString::number(pe.th32ProcessID);
ui->tableWidget->setItem(i,1,new QTableWidgetItem(str));
str=QString::number(pe.cntThreads);
ui->tableWidget->setItem(i,2,new QTableWidgetItem(str));
bFlag=Process32Next(hSnopShot,&pe);
i++;
}
}
这样一来 我们就获取到了系统的进程 并写到了表格中
之后 我们开始对杀死进程这一功能进行编写
具体步骤:
点击想要删除的行 点击杀死进程 进程结束 表格中该进程消失
首先对按钮"杀死进程"添加一个槽函数
void on_pushButton_clicked()
在槽函数中
我们要先获得当前选中的进程的id
//获取当前进程id
QList<QTableWidgetItem*>listitem=ui->tableWidget->selectedItems();
//定义一个QList<QTableWidgetItem*>类型的列表来存我们当前在表格中选中的一行的数据;
QTableWidgetItem*pitem=listitem.front();
int nrow=ui->tableWidget->row(pitem);
//定义一个nrow记录当前选中的行
listitem.pop_front();
pitem=listitem.front();
//在定义一个 QTableWidgetItem*类型的节点用来寻找进程ID 我们这里的ID是第二列
所以pitem记录了第二列
listitem.pop_front();
QString strid=pitem->text();
strid记录了第二列的字符串;
if(strid.isEmpty())
return ;
//获取句柄
HANDLE hProcess= OpenProcess(PROCESS_TERMINATE,0,strid.toInt());
//杀死进程
if(hProcess)
{
TerminateProcess(hProcess,-1);
ui->tableWidget->removeRow(nrow);
}
Widget类的完整代码如下
#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
#include <windows.h>
#include <tlhelp32.h>
QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE
class Widget : public QWidget
{
Q_OBJECT
public:
Widget(QWidget *parent = nullptr);
~Widget();
void showProess();
private slots:
void on_pushButton_clicked();
private:
Ui::Widget *ui;
};
#endif // WIDGET_H
#include "widget.h"
#include "ui_widget.h"
#include "QTableWidget"
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
ui->tableWidget->setSelectionMode(QTableWidget::SingleSelection);
ui->tableWidget->setSelectionBehavior(QTableWidget::SelectRows);
showProess();
}
Widget::~Widget()
{
delete ui;
}
void Widget::showProess()
{
PROCESSENTRY32 pe;
//在使用这个结构前,先设置它的大小
pe.dwSize = sizeof(pe);
//获取进程信息的链表
HANDLE hSnopShot=CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0);
if(hSnopShot==INVALID_HANDLE_VALUE)
return ;
//获取链表的头
bool bFlag= Process32First(hSnopShot,&pe);
int i=0;
QString str;
//遍历链表
while(bFlag)
{
//name
str=QString::fromWCharArray(pe.szExeFile);
ui->tableWidget->setItem(i,0,new QTableWidgetItem(str));
//process
str=QString::number(pe.th32ProcessID);
ui->tableWidget->setItem(i,1,new QTableWidgetItem(str));
str=QString::number(pe.cntThreads);
ui->tableWidget->setItem(i,2,new QTableWidgetItem(str));
bFlag=Process32Next(hSnopShot,&pe);
i++;
}
}
void Widget::on_pushButton_clicked()
{
//获取当前进程id
QList<QTableWidgetItem*>listitem=ui->tableWidget->selectedItems();
QTableWidgetItem*pitem=listitem.front();
int nrow=ui->tableWidget->row(pitem);
listitem.pop_front();
pitem=listitem.front();
listitem.pop_front();
QString strid=pitem->text();
if(strid.isEmpty())
return ;
//获取句柄
HANDLE hProcess= OpenProcess(PROCESS_TERMINATE,0,strid.toInt());
//杀死进程
if(hProcess)
{
TerminateProcess(hProcess,-1);
ui->tableWidget->removeRow(nrow);
}
}