Qt:Windows编程—Qt实现本地服务管理
Qt實現本地服務管理
前言
本節將使用Windows的幾個API,使用qt實現 本地服務 簡單管理。這里簡單介紹下服務。
幾乎每一種操作系統都有一種在系統啟動時啟動的進程機制,這種機制不會依賴于用戶的交互。在Windows下,類似的基礎稱為Windows服務。服務是一種程序類型,它在后臺運行,服務程序通常可以在本地和通過網絡為用戶提供一些功能,服務在操作系統啟動時就會隨之啟動的程序。
效果
實現效果和Windows 服務管理類似,等會我們用我們寫的軟件進行服務的啟動和暫停,然后刷新windows的服務管理 和我們的操作結果應該是一致的。
相關的Windows API
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
);
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
SC_HANDLE OpenServiceA(
SC_HANDLE hSCManager,
LPCSTR lpServiceName, // 要打開的服務的名稱
DWORD dwDesiredAccess // 訪問的權限
);
BOOL StartServiceA(
SC_HANDLE hService, // 啟動服務的句柄,有上面獲得
DWORD dwNumServiceArgs, // 啟動服務的參數個數
LPCSTR *lpServiceArgVectors // 啟動服務的參數
);
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实现本地服务管理的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 9. OD-PEID的入门及BASIC(
- 下一篇: 推荐系统(Recommendation