Qt实现本地服务管理

前言

本节将使用Windows的几个API,使用qt实现 本地服务 简单管理。这里简单介绍下服务。
几乎每一种操作系统都有一种在系统启动时启动的进程机制,这种机制不会依赖于用户的交互。在Windows下,类似的基础称为Windows服务服务是一种程序类型,它在后台运行,服务程序通常可以在本地和通过网络为用户提供一些功能,服务在操作系统启动时就会随之启动的程序

效果

实现效果和Windows 服务管理类似,等会我们用我们写的软件进行服务的启动和暂停,然后刷新windows的服务管理 和我们的操作结果应该是一致的。

相关的Windows API

  1. 打开服务管理句柄

SC_HANDLE OpenSCManagerA(
LPCSTR lpMachineName, // computer name,NULL 为 本机
LPCSTR lpDatabaseName, // SCM database name,应该为 SERVICES_ACTIVE_DATABASE,NULL默认也为前面那个
DWORD dwDesiredAccess // 对scm数据库的访问权限 SC_MANAGER_ALL_ACCESS
);
// 成功返回service control manager database的handle
// 对应的关闭函数
BOOL CloseServiceHandle(
SC_HANDLE hSCObject
);

  1. 枚举服务

BOOL EnumServicesStatusExA(
SC_HANDLE hSCManager, // OpenSCManager函数返回的句柄
SC_ENUM_TYPE InfoLevel, // SC_ENUM_PROCESS_INFO
DWORD dwServiceType,// 枚举的服务类型
DWORD dwServiceState, // 枚举指定状态的服务
LPBYTE lpServices, // 指向ENUM_SERVICE_STATUS_PROCESSA类型的指针
DWORD cbBufSize, // The size of the buffer pointed to by the lpServices parameter, in bytes.
LPDWORD pcbBytesNeeded, // 传出参数,当buffer太小,返回实际需要的大小
LPDWORD lpServicesReturned,// 传出参数,返回枚举服务的个数
LPDWORD lpResumeHandle, // 输入输出参数,返回枚举是否成功
LPCSTR pszGroupName // 加载 组名字
);
成功返回非0

  1. 打开服务

SC_HANDLE OpenServiceA(
SC_HANDLE hSCManager,
LPCSTR lpServiceName, // 要打开的服务的名称
DWORD dwDesiredAccess // 访问的权限
);

  1. 启动服务

BOOL StartServiceA(
SC_HANDLE hService, // 启动服务的句柄,有上面获得
DWORD dwNumServiceArgs, // 启动服务的参数个数
LPCSTR *lpServiceArgVectors // 启动服务的参数
);

  1. 停止服务

BOOL ControlService(
SC_HANDLE hService,
DWORD dwControl, // 控制码
LPSERVICE_STATUS lpServiceStatus // 传出参数,返回服务的状态
);

核心代码

刷新表格代码:

void Widget::refreshTable(){int count = ui->serviceTable->rowCount();// 先清空表for(int i = 0; i < count;i++)ui->serviceTable->removeRow(0);// 清空之前申请的空间if(mBuf!=nullptr)delete[] mBuf;DWORD needLen,serviceNum,result,type;BOOL ret;// 刷新表格,枚举服务if(ui->win32->isChecked()){// win32服务type = SERVICE_WIN32;}else{// 驱动服务type = SERVICE_DRIVER;}// 第一次 获取需要的字节长度ret = EnumServicesStatusExA(mHSCM,SC_ENUM_PROCESS_INFO ,type,SERVICE_STATE_ALL,NULL,0,&needLen,&serviceNum,NULL,NULL);mBuf = new char[needLen]{0};if( ret == 0){// 下面这段switch代码要写,在qt5.9.7版本下 不写就是不行switch (GetLastError()) {case ERROR_ACCESS_DENIED:qDebug() << "ERROR_ACCESS_DENIED";break;case ERROR_MORE_DATA:qDebug() << "ERROR_MORE_DATA";break;case ERROR_INVALID_PARAMETER:qDebug() << "ERROR_INVALID_PARAMETER";break;case ERROR_INVALID_HANDLE:qDebug() << "ERROR_INVALID_HANDLE";break;case ERROR_INVALID_LEVEL:qDebug() << "ERROR_INVALID_LEVEL";break;case ERROR_SHUTDOWN_IN_PROGRESS:qDebug() << "ERROR_SHUTDOWN_IN_PROGRESS";break;default:qDebug() << "other error";break;}// EnumServicesStatusExA 枚举服务APIret = EnumServicesStatusExA(mHSCM,SC_ENUM_PROCESS_INFO ,type,SERVICE_STATE_ALL,reinterpret_cast<LPBYTE>(mBuf),needLen,&needLen,&serviceNum,&result,NULL);LPENUM_SERVICE_STATUS_PROCESSA p = reinterpret_cast<LPENUM_SERVICE_STATUS_PROCESSA>(mBuf);if(ret == 0){qDebug() << "获取服务失败";}else{qDebug() << "获取服务成功";// 往表格中添加数据for(DWORD i = 0; i < serviceNum; i++){ui->serviceTable->insertRow(i);ui->serviceTable->setItem(i,0,new QTableWidgetItem(QString(p[i].lpServiceName)));ui->serviceTable->setItem(i,1,new QTableWidgetItem(QString::fromLocal8Bit(p[i].lpDisplayName)));QTableWidgetItem* item;switch(p[i].ServiceStatusProcess.dwCurrentState){case SERVICE_PAUSED:item = new QTableWidgetItem("暂停");break;case SERVICE_STOPPED:item = new QTableWidgetItem("停止");break;case SERVICE_RUNNING:item = new QTableWidgetItem("运行");break;default:item = new QTableWidgetItem("其他");break;}ui->serviceTable->setItem(i,2,item);}
//            delete}}
}

启动服务

void Widget::on_startBtn_clicked()
{// 启动服务int row = ui->serviceTable->currentRow();LPENUM_SERVICE_STATUS_PROCESSA p =  reinterpret_cast<LPENUM_SERVICE_STATUS_PROCESSA>(mBuf);if(p[row].ServiceStatusProcess.dwCurrentState == SERVICE_RUNNING)return;const char* name = ui->serviceTable->item(row,0)->text().toStdString().c_str();SC_HANDLE service = OpenServiceA(mHSCM, name, SERVICE_ALL_ACCESS);if(service == nullptr){qDebug() << "打开服务失败";return;}// StartServiceA启动服务APIBOOL ret = StartServiceA(service,0,nullptr);if( ret ){qDebug() << "启动服务成功";ui->serviceTable->setItem(row,2,new QTableWidgetItem("运行"));p[row].ServiceStatusProcess.dwCurrentState = SERVICE_RUNNING;}else{qDebug() << "启动服务失败";}
}

停止服务

void Widget::on_stopBtn_clicked()
{// 停止服务int row = ui->serviceTable->currentRow();LPENUM_SERVICE_STATUS_PROCESSA p =  reinterpret_cast<LPENUM_SERVICE_STATUS_PROCESSA>(mBuf);if(p[row].ServiceStatusProcess.dwCurrentState == SERVICE_STOPPED)return;const char* name = ui->serviceTable->item(row,0)->text().toStdString().c_str();if( name == nullptr)return;SC_HANDLE service = OpenServiceA(mHSCM, name, SERVICE_ALL_ACCESS);if(service == nullptr){qDebug() << "打开服务失败";return;}SERVICE_STATUS status;// StartServiceA停止服务APIBOOL ret = ControlService(service,SERVICE_CONTROL_STOP,&status);if( ret ){qDebug() << "停止服务成功";ui->serviceTable->setItem(row,2,new QTableWidgetItem("停止"));p[row].ServiceStatusProcess.dwCurrentState = SERVICE_STOPPED;}else{qDebug() << "停止服务失败";}
}

完整代码

完整工程代码可以在这里下载,也可在github下载

Qt:Windows编程—Qt实现本地服务管理相关推荐

  1. Qt windows端的蓝牙串口服务

    Qt windows端的蓝牙串口服务 环境 系统 Qt 蓝牙模块 使用步骤 蓝牙模块参数获取 配对 扫描.连接.数据收发 扫描 连接 数据收发 环境 系统 只测试过自己电脑,系统版本如下: 查看方式按 ...

  2. java linux 管理系统_用Java开发一个本地服务管理软件

    使用Java开发一个本机服务管理程序,能够控制本机Tomcat.Apache服务的开启和关闭,图形界面控制.用户可以自己扩展其他服务,用来学习图形界面编程.多线程.事件响应等都不错. 一.最终界面 先 ...

  3. Qt:Windows编程—Qt实现进程管理

    前言 继续学window编程,学呀学呀 学无止境,学到Windows进程相关API了.利用相关的API使用Qt写界面实现了一个简单的进程管理.主要用到 进程的创建.进程的枚举.线程的枚举.DLL的枚举 ...

  4. Qt界面编程-Qt简介

    一.Qt简介 Qt是什么 图形用户程序框架,是对底层应用编程接口API面向对象的封装. 是一套基于C++语言的类库,专注但不局限于图形用户界面的开发,也可以进行系统调用.网络编程.数据库.2D/3D图 ...

  5. Windows系统 services.msc命令详解,Windows命令行查看本地服务

    「作者主页」:士别三日wyx 第一步.打开cmd 按下 win 键,输入 cmd 后回车,打开「命令提示符」 第二步.查看系统版本 在打开的cmd窗口中,输入 services.msc 后回车,即可在 ...

  6. Windows Azure移动终端云服务管理(公测版)

    概览 云在远方,管理在您手中.在这个移动为先 云为先的世界,服务不再是基于请求才提供,而是主动来到身边方便您的模式了.我们最近将会陆续推出几大移动端利器帮助您随时随地管理您的云服务. 首批利器之中排名 ...

  7. windows Server 2016点击服务管理器无响应解决办法

    产生此问题原因: 把iis及相关功能全部删除了,重启系统后该服务器就打不开服务管理器了. 解决办法: cmd 执行:Dism /online /Enable-Feature /FeatureName: ...

  8. Qt:Windows编程—Qt实现注册表启动项管理

    Qt实现注册表启动项管理 前言 Windows的开机启动项在很多地方都有设置,这次我们在注册表 子键"HKEY_LOCAL_MACHINE\Software\Microsoft\Window ...

  9. C/C++:Windows编程—代码获取本地所有网卡信息(网卡描述,IP地址,子网掩码,MAC地址)

    先看效果 看代码 使用 GetAdaptersInfo 函数获取网卡的所有信息. MSDN函数说明 https://docs.microsoft.com/en-us/windows/desktop/a ...

最新文章

  1. 成员资格、授权 – ASP.NET MVC 4 系列
  2. kubernetes (k8s)的二进制部署单节点(etcd和flannel网络)
  3. Python for Data Analysis 学习心得(二) - pandas介绍
  4. G-SYNC技术是什么
  5. 从零基础入门Tensorflow2.0 ----四、17.生成tfrecords文件
  6. 张宇:【线性代数】公式汇总!
  7. android源码分析辅助工具
  8. science图表_如何利用PS制作统计图表(一些饼图的科学制作技巧)
  9. 表情识别 [传统方法 VS 深度学习方法]
  10. 【第二剑-构建活动】代码应该怎么写?
  11. Cemu模拟铁拳TT2高清设置
  12. The project description file (.project) for 'xxx' is missing.
  13. WEMOS D1 R1/R2 [ESP8266] + PCA9685 驱动舵机
  14. 开发人员不可不看的 OBD通讯协议知识
  15. Android 自定义收音机刻度
  16. 服务器压力测试_性能测试新手误区(四):一切来自录制
  17. 作为新一代网络基础设施,区块链已有了哪些应用?
  18. 关于 scrollIntoView() 锚点 元素滚动到指定位置 平滑
  19. 企业应用区块链的正确姿势
  20. string 中的maketrans和translate

热门文章

  1. linux 多路径 parted,Ubuntu存储多路径配置
  2. 第25课 成绩等级 《小学生C++趣味编程》
  3. 1.3 编程基础之算术表达式与顺序执行 10 计算并联电阻的阻值
  4. RTX5 | 事件标志组02 - 置位事件标志组,并获取事件标志组的值
  5. ThinkPHP6项目基操(14.实战部分 中间件处理登录流程)
  6. bat获取命令返回值_redis中list和hash的基本命令和使用场景
  7. Python笔记-Can’t reconnect until invalid transaction is rolled back
  8. Spring Boot文档阅读笔记-EhCache的使用
  9. Java笔记-CXF增加拦截器与自定义拦截器
  10. python列表修改函数_python 禁止函数修改列表的实现方法