Qt:Windows编程—Qt实现本地服务管理
Qt實(shí)現(xiàn)本地服務(wù)管理
前言
本節(jié)將使用Windows的幾個(gè)API,使用qt實(shí)現(xiàn) 本地服務(wù) 簡(jiǎn)單管理。這里簡(jiǎn)單介紹下服務(wù)。
幾乎每一種操作系統(tǒng)都有一種在系統(tǒng)啟動(dòng)時(shí)啟動(dòng)的進(jìn)程機(jī)制,這種機(jī)制不會(huì)依賴于用戶的交互。在Windows下,類似的基礎(chǔ)稱為Windows服務(wù)。服務(wù)是一種程序類型,它在后臺(tái)運(yùn)行,服務(wù)程序通常可以在本地和通過(guò)網(wǎng)絡(luò)為用戶提供一些功能,服務(wù)在操作系統(tǒng)啟動(dòng)時(shí)就會(huì)隨之啟動(dòng)的程序。
效果
實(shí)現(xiàn)效果和Windows 服務(wù)管理類似,等會(huì)我們用我們寫的軟件進(jìn)行服務(wù)的啟動(dòng)和暫停,然后刷新windows的服務(wù)管理 和我們的操作結(jié)果應(yīng)該是一致的。
相關(guān)的Windows API
SC_HANDLE OpenSCManagerA(
LPCSTR lpMachineName, // computer name,NULL 為 本機(jī)
LPCSTR lpDatabaseName, // SCM database name,應(yīng)該為 SERVICES_ACTIVE_DATABASE,NULL默認(rèn)也為前面那個(gè)
DWORD dwDesiredAccess // 對(duì)scm數(shù)據(jù)庫(kù)的訪問(wèn)權(quán)限 SC_MANAGER_ALL_ACCESS
);
// 成功返回service control manager database的handle
// 對(duì)應(yīng)的關(guān)閉函數(shù)
BOOL CloseServiceHandle(
SC_HANDLE hSCObject
);
BOOL EnumServicesStatusExA(
SC_HANDLE hSCManager, // OpenSCManager函數(shù)返回的句柄
SC_ENUM_TYPE InfoLevel, // SC_ENUM_PROCESS_INFO
DWORD dwServiceType,// 枚舉的服務(wù)類型
DWORD dwServiceState, // 枚舉指定狀態(tài)的服務(wù)
LPBYTE lpServices, // 指向ENUM_SERVICE_STATUS_PROCESSA類型的指針
DWORD cbBufSize, // The size of the buffer pointed to by the lpServices parameter, in bytes.
LPDWORD pcbBytesNeeded, // 傳出參數(shù),當(dāng)buffer太小,返回實(shí)際需要的大小
LPDWORD lpServicesReturned,// 傳出參數(shù),返回枚舉服務(wù)的個(gè)數(shù)
LPDWORD lpResumeHandle, // 輸入輸出參數(shù),返回枚舉是否成功
LPCSTR pszGroupName // 加載 組名字
);
成功返回非0
SC_HANDLE OpenServiceA(
SC_HANDLE hSCManager,
LPCSTR lpServiceName, // 要打開的服務(wù)的名稱
DWORD dwDesiredAccess // 訪問(wèn)的權(quán)限
);
BOOL StartServiceA(
SC_HANDLE hService, // 啟動(dòng)服務(wù)的句柄,有上面獲得
DWORD dwNumServiceArgs, // 啟動(dòng)服務(wù)的參數(shù)個(gè)數(shù)
LPCSTR *lpServiceArgVectors // 啟動(dòng)服務(wù)的參數(shù)
);
BOOL ControlService(
SC_HANDLE hService,
DWORD dwControl, // 控制碼
LPSERVICE_STATUS lpServiceStatus // 傳出參數(shù),返回服務(wù)的狀態(tài)
);
核心代碼
刷新表格代碼:
void Widget::refreshTable(){int count = ui->serviceTable->rowCount();// 先清空表for(int i = 0; i < count;i++)ui->serviceTable->removeRow(0);// 清空之前申請(qǐng)的空間if(mBuf!=nullptr)delete[] mBuf;DWORD needLen,serviceNum,result,type;BOOL ret;// 刷新表格,枚舉服務(wù)if(ui->win32->isChecked()){// win32服務(wù)type = SERVICE_WIN32;}else{// 驅(qū)動(dòng)服務(wù)type = SERVICE_DRIVER;}// 第一次 獲取需要的字節(jié)長(zhǎng)度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 枚舉服務(wù)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() << "獲取服務(wù)失敗";}else{qDebug() << "獲取服務(wù)成功";// 往表格中添加數(shù)據(jù)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("運(yùn)行");break;default:item = new QTableWidgetItem("其他");break;}ui->serviceTable->setItem(i,2,item);} // delete}} }啟動(dòng)服務(wù)
void Widget::on_startBtn_clicked() {// 啟動(dòng)服務(wù)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() << "打開服務(wù)失敗";return;}// StartServiceA啟動(dòng)服務(wù)APIBOOL ret = StartServiceA(service,0,nullptr);if( ret ){qDebug() << "啟動(dòng)服務(wù)成功";ui->serviceTable->setItem(row,2,new QTableWidgetItem("運(yùn)行"));p[row].ServiceStatusProcess.dwCurrentState = SERVICE_RUNNING;}else{qDebug() << "啟動(dòng)服務(wù)失敗";} }停止服務(wù)
void Widget::on_stopBtn_clicked() {// 停止服務(wù)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() << "打開服務(wù)失敗";return;}SERVICE_STATUS status;// StartServiceA停止服務(wù)APIBOOL ret = ControlService(service,SERVICE_CONTROL_STOP,&status);if( ret ){qDebug() << "停止服務(wù)成功";ui->serviceTable->setItem(row,2,new QTableWidgetItem("停止"));p[row].ServiceStatusProcess.dwCurrentState = SERVICE_STOPPED;}else{qDebug() << "停止服務(wù)失敗";} }完整代碼
完整工程代碼可以在這里下載,也可在github下載
總結(jié)
以上是生活随笔為你收集整理的Qt:Windows编程—Qt实现本地服务管理的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 9. OD-PEID的入门及BASIC(
- 下一篇: 25. PE结构-PE详解之资源