一、前言
最近有个项目需要写一个服务,如下:
二、windows服务
其实我们写windows服务的时候用命令去安装,卸载服务非常不方便,手动去启动时候也麻烦,那么用QT写个界面比较科学。
三、核心代码
1、安装服务
int SktVideoServer::install()
{
int iRet = 0;
m_schRelSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
if (NULL == m_schRelSCManager)
{
ui.showLbl->setText(QString::fromLocal8Bit("打开服务管理器失败"));
return 1;
}
char szSktCurPath[MAX_PATH] = { 0 };
iRet = SktGetPath(szSktCurPath, MAX_PATH);
if (0 != iRet)
{
ui.showLbl->setText(QString::fromLocal8Bit("获取不到当前路径"));
return 2;
}
char szPathBuf[1024];
sprintf_s(szPathBuf, 1024, "%s\\%s", szSktCurPath, SKT_REL_SVC_NAME);
m_schRelService = CreateService(
m_schRelSCManager,
SKT_REL_SVC_DISP,
"SC Skt Relay Service Engeine",
SERVICE_ALL_ACCESS,
SERVICE_WIN32_OWN_PROCESS,
SERVICE_DEMAND_START,
SERVICE_ERROR_NORMAL,
szPathBuf,
NULL, NULL, NULL, NULL, NULL);
if (NULL == m_schRelService)
{
clear();
ui.showLbl->setText(QString::fromLocal8Bit("安装服务失败"));
return 3;
}
else {
ui.showLbl->setText(QString::fromLocal8Bit("安装服务成功"));
}
clear();
return iRet;
}
2、开启服务
int SktVideoServer::SktStartMediaServer()
{
int iRet = 0;
SERVICE_STATUS status;
m_schRelSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS); // 打开服务控制管
if (NULL == m_schRelSCManager)
{
ui.showLbl->setText(QString::fromLocal8Bit("打开服务管理器失败"));
return 1;
}
m_schRelService = OpenService(m_schRelSCManager, SKT_REL_SVC_DISP, SERVICE_ALL_ACCESS | DELETE); // 获得服务句柄
if (NULL == m_schRelService)
{
ui.showLbl->setText(QString::fromLocal8Bit("获取服务句柄失败"));
return 2;
}
QueryServiceStatus(m_schRelService, &status); // 获得服务的当前状态
if (status.dwCurrentState == SERVICE_STOPPED) // 如果服务处于停止状态,则将其状态设置为启动状态
{
BOOL iRet = StartService(m_schRelService, 0, NULL); //启动服务
if (iRet == FALSE)
{
iRet = GetLastError();
char szSktVal[256] = { 0 };
sprintf_s(szSktVal, 256, "===>启动失败%d", iRet);
ui.showLbl->setText(QString::fromLocal8Bit(szSktVal));
return 3;
}
else {
ui.showLbl->setText(QString::fromLocal8Bit("启动服务成功"));
}
}else if(status.dwCurrentState == SERVICE_RUNNING){
ui.showLbl->setText(QString::fromLocal8Bit("服务已经启动"));
}else {
ui.showLbl->setText(QString::fromLocal8Bit("启动服务失败"));
return 4;
}
clear();
return iRet;
}
3、停止服务
int SktVideoServer::stop()
{
int iRet = 0;
SERVICE_STATUS status;
m_schRelSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
if (NULL == m_schRelSCManager)
{
ui.showLbl->setText(QString::fromLocal8Bit("打开服务管理器失败!"));
return iRet;
}
m_schRelService = OpenService(m_schRelSCManager, SKT_REL_SVC_DISP, SERVICE_ALL_ACCESS | DELETE); // 获得服务句柄
if (NULL == m_schRelService)
{
ui.showLbl->setText(QString::fromLocal8Bit("获取服务句柄失败!"));
return iRet;
}
while (1)
{
QueryServiceStatus(m_schRelService, &status); // 获得服务的当前状态
if (status.dwCurrentState != SERVICE_STOPPED) // 如果服务不处于停止状态,则将其状态设置为停止状态
{
BOOL bRet = ControlService(m_schRelService, SERVICE_CONTROL_STOP, &status);
if (FALSE == bRet)
{
ui.showLbl->setText(QString::fromLocal8Bit("停止服务失败!"));
clear();
return iRet;
}
}
if (status.dwCurrentState == SERVICE_STOPPED)
{
ui.showLbl->setText(QString::fromLocal8Bit("停止服务成功!"));
break;
}
}
clear();
return iRet;
}
4、卸载服务
int SktVideoServer::uninstall()
{
int iRet = 0;
SERVICE_STATUS status;
SC_HANDLE schSCManager = NULL;
SC_HANDLE schService = NULL;
m_schRelSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
if (NULL == m_schRelSCManager)
{
ui.showLbl->setText(QString::fromLocal8Bit("打开服务管理器失败"));
return iRet;
}
m_schRelService = OpenService(m_schRelSCManager, SKT_REL_SVC_DISP, SERVICE_ALL_ACCESS | DELETE); // 获得服务句柄
if (NULL == m_schRelService)
{
ui.showLbl->setText(QString::fromLocal8Bit("获得服务句柄失败"));
return iRet;
}
while (1)
{
QueryServiceStatus(m_schRelService, &status); // 获得服务的当前状态
if (status.dwCurrentState != SERVICE_STOPPED) // 如果服务不处于停止状态,则将其状态设置为停止状态
{
ControlService(schService, SERVICE_CONTROL_STOP, &status);
}
if (status.dwCurrentState == SERVICE_STOPPED)
{
break;
}
}
BOOL bRet = DeleteService(m_schRelService); // 删除服务
if (FALSE == bRet)
{
ui.showLbl->setText(QString::fromLocal8Bit("删除服务失败"));
return iRet;
}
else {
ui.showLbl->setText(QString::fromLocal8Bit("卸载服务成功"));
}
clear();
return iRet;
}
5、服务程序
void CSktMainSvc::ServiceMain(int argc, char** argv)
{
SktInitSvc();
SktSetSvc();
m_hStatus = ::RegisterServiceCtrlHandlerEx(SKT_MAIN_SVC_NAME, CtrlHandler, this);
if (m_hStatus == (SERVICE_STATUS_HANDLE)0)
{
return;
}
m_stServiceStatus.dwCurrentState = SERVICE_RUNNING;
SetServiceStatus (m_hStatus, &m_stServiceStatus);
// Sleep(15000);
StartMainEng();
DWORD dwRet = 0;
HANDLE hWaitHandle[2] = {m_hStop, m_hCheck};
DWORD dwMilliseconds = 1000 * 10;
// DWORD dwMilliseconds = 1000 * 1;//1000为1秒
while (true)
{
dwRet = WaitForMultipleObjects(2, hWaitHandle, FALSE, dwMilliseconds );
if (WAIT_OBJECT_0 == dwRet)
{
if (SERVICE_STOPPED == m_stServiceStatus.dwCurrentState)
{
ResetEvent(m_hStop);
break;
}
}
if (dwRet = (WAIT_OBJECT_0 + 1))
{
CheckSktMainEng();
ResetEvent(m_hCheck);
}
}
StopSktMainEng();
}
四、总结
以上就是windows服务核写代码编写了,其实QT就只是几个按钮,如果要写的更好可以监测服务状态等等,源码已上传,欢迎大家下载讨论交流。