日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > windows >内容正文

windows

Qt:Windows编程—Qt实现本地服务管理

發布時間:2025/3/15 windows 38 豆豆
生活随笔 收集整理的這篇文章主要介紹了 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实现本地服务管理的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。