您的位置:首页 > 其它

windows服务程序的编写

2015-06-09 17:55 274 查看
windows服务程序可以设置为开机运行,具有特权。一个服务程序编写完成后要进行安装,然后通过本地服务的管理工具打开,当然如果设置为开机自动运行就不用手动开启了。服务程序不应该双击运行。

windows服务程序需要进行安装,,也可以在服务程序的入口函数接收传入的参数,然后进行判断是否进行安装,判断接收的参数是什么字符串,然后再程序内进行安装,这个时候,服务还没有被注册,也没有被安装,程序只能算是一个普通应用程序。安装之后就不应该双击运行了,要通过本地服务管理工具打开或者开机启动。

#define SERVER_NAME "MyTestServer"

//内部变量

bool bDebugServer=false;

SERVICE_STATUS ssStatus;

SERVICE_STATUS_HANDLE hService;

DWORD dwErr=0;

TCHAR szErr[256];

int _tmain(int argc, _TCHAR* argv[])

{

HRESULT hr = CoInitialize(NULL);

if((argc>1) && ((argv[1][0] == _T('-')) || (argv[1][0] == _T('/'))))

{

if(_tcsicmp(_T("install"), argv[1]+1)==0)

{

installService();

}

else if(_tcsicmp(_T("remove"), argv[1]+1)==0)

{

removeService();

}

else if(_tcsicmp(_T("debug"), argv[1]+1)==0)

{

//bDebugServer=true;

//debugService(argc, argv);

}

return 0;

}

SERVICE_TABLE_ENTRY st[] =

{

{ _T(SERVER_NAME), Service_Main },

{ NULL, NULL }

};

StartServiceCtrlDispatcher(st);//通过指定的Service_Main 程序会跳转到Service_Main 去执行,如果失败,可能是因为程序不是用过windows服务管理器打开的。

//安装的时候通过CreateService可以设置开机自动启动。

CoUninitialize();

return 0;

}

//安装服务程序

void installService()

{

SC_HANDLE schService;

SC_HANDLE schSCManager;

TCHAR szPath[512];

//得到程序磁盘文件的路径

GetModuleFileName(NULL,szPath,512);

AppendDbgMsg("install service \r\n");//AppendDbgMsg是我自己写的写文件操作的函数,以免在没有界面的情况下不知道具体执行情况。

//打开服务管理数据库

schSCManager=OpenSCManager(

NULL, //本地计算机

NULL, //默认的数据库

SC_MANAGER_ALL_ACCESS //要求所有的访问权

);

if(schSCManager)

{

//登记服务程序

schService=CreateService(

schSCManager, //服务管理数据库句柄

TEXT(SERVER_NAME), //服务名

TEXT(SERVER_NAME), //用于显示服务的标识

SERVICE_ALL_ACCESS, //响应所有的访问请求

SERVICE_WIN32_OWN_PROCESS, //服务类型

SERVICE_AUTO_START, //启动类型 //设置为Auto就会开机自动启动

SERVICE_ERROR_NORMAL, //错误控制类型

szPath, //服务程序磁盘文件的路径

NULL, //服务不属于任何组

NULL, //没有tag标识符

NULL, //启动服务所依赖的服务或服务组,这里仅仅是一个空字符串

NULL, //LocalSystem 帐号

NULL);

if(schService)

{

AppendDbgMsg("%s installed. \n", SERVER_NAME);

CloseServiceHandle(schService);

}

else

{

AppendDbgMsg("CreateService failed - %d \n", GetLastError());

}

CloseServiceHandle(schSCManager);

}

else

{

AppendDbgMsg("OpenSCManager failed - %d \n", GetLastError());

}

}

//停止和删除已安装的服务程序

void removeService()

{

SC_HANDLE schService;

SC_HANDLE schSCManager;

AppendDbgMsg("remove service \r\n");

//打开服务管理数据库

schSCManager=OpenSCManager(

NULL, //本地计算机

NULL, //默认的数据库

SC_MANAGER_ALL_ACCESS //要求所有的访问权

);

if(schSCManager)

{

//获取服务程序句柄

schService=OpenService(

schSCManager, //服务管理数据库句柄

TEXT(SERVER_NAME), //服务名

SERVICE_ALL_ACCESS //响应所有的访问请求

);

if(schService)

{

//试图停止服务

if(ControlService(

schService, //服务程序句柄

SERVICE_CONTROL_STOP, //停止服务请求码

&ssStatus //接收最后的服务状态信息

))

{

AppendDbgMsg("Stopping %s.", SERVER_NAME);

Sleep(1000);

//等待服务停止

//

while(QueryServiceStatus(schService,&ssStatus))

{

if(SERVICE_STOP_PENDING==ssStatus.dwCurrentState)

{

AppendDbgMsg(".");

Sleep(1000);

}

else

break;

}

if(SERVICE_STOPPED==ssStatus.dwCurrentState)

{

AppendDbgMsg("\n %s stopped. \n", SERVER_NAME);

}

else

{

AppendDbgMsg("\n %s failed to stopp. \n", SERVER_NAME);

}

}

//删除已安装的服务程序安装

if(DeleteService(schService))

{

AppendDbgMsg("%s removed. \n", SERVER_NAME);

}

else

{

AppendDbgMsg("DeleteService failed - %d. \n", GetLastError());

}

CloseServiceHandle(schService);

}

else

{

AppendDbgMsg("OpenService failed - %d \n", GetLastError());

}

CloseServiceHandle(schSCManager);

}

else

{

AppendDbgMsg("OpenSCManager failed - %d \n", GetLastError());

}

}

//服务的入口

void WINAPI Service_Main(DWORD dwArgc, LPTSTR *lpszArgv)

{

AppendDbgMsg("in server main gonna to register server control handle \r\n");

//注册服务控制处理函数

hService = RegisterServiceCtrlHandler(TEXT(SERVER_NAME), Service_Ctrl);//消息会通过Service_Ctrl传入,然后再函数中处理

//如果注册失败

if(!hService)

{

AppendDbgMsg("register failed \r\n");

goto cleanup;

return;

}

else

{

AppendDbgMsg("success to register \r\n");

}

//初始化 SERVICE_STATUS 结构中的成员

ssStatus.dwCurrentState = SERVICE_RUNNING;

ssStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;

ssStatus.dwServiceSpecificExitCode = 0;

//更新服务状态

if(!ReportStatusToSCMgr(

SERVICE_RUNNING,//服务状态,The service is starting.

NO_ERROR, //退出码

3000)) //等待时间

{

goto cleanup; //更新服务状态失败则转向 cleanup

}

ServiceStart(dwArgc, lpszArgv);/服务启动之后执行的函数,不一定要设置为函数。可以直接写代码

return;

cleanup:

//把服务状态更新为 SERVICE_STOPPED,并退出。

if(hService)

{

(void)ReportStatusToSCMgr(SERVICE_STOPPED, dwErr, 0);

}

}

//消息处理函数

void WINAPI Service_Ctrl(DWORD dwCtrlCode)

{

AppendDbgMsg("server control\r\n");

//处理控制请求码

switch(dwCtrlCode)

{

//先更新服务状态为 SERVICDE_STOP_PENDING,再停止服务。

case SERVICE_CONTROL_STOP:

{

ReportStatusToSCMgr(SERVICE_STOP_PENDING, NO_ERROR, 500);

AppendDbgMsg("SERVICE_CONTROL_STOP");

//ServiceStop(); //由具体的服务程序实现

ssStatus.dwCurrentState=SERVICE_STOPPED;

break;

}

//暂停服务

case SERVICE_CONTROL_PAUSE:

{

ReportStatusToSCMgr(SERVICE_STOP_PENDING, NO_ERROR, 500);

AppendDbgMsg("SERVICE_CONTROL_PAUSE");

// ServicePause(); //由具体的服务程序实现

ssStatus.dwCurrentState=SERVICE_PAUSED;

break;

}

//继续服务

case SERVICE_CONTROL_CONTINUE:

{

ReportStatusToSCMgr(SERVICE_STOP_PENDING, NO_ERROR, 500);

AppendDbgMsg("SERVICE_CONTROL_CONTINUE");

// ServiceContinue(); //由具体的服务程序实现

ssStatus.dwCurrentState=SERVICE_RUNNING;

break;

}

//更新服务状态

case SERVICE_CONTROL_INTERROGATE:

{

AppendDbgMsg("SERVICE_CONTROL_INTERROGATE");

break;

}

//无效控制码

default:

{

AppendDbgMsg("default");

break;

}

}

ReportStatusToSCMgr(ssStatus.dwCurrentState, NO_ERROR, 0);

}

void WINAPI ServiceStart(DWORD dwArgc,LPTSTR *lpArgv)

{

HANDLE hThread;

//创建服务线程 服务完成的功能在这里调用

hThread = CreateThread(NULL,

0,

Service,

NULL,

0,

NULL);

if(hThread == NULL)

{

AppendDbgMsg("failed to create service thread \r\n");

return;

}

return;

}

//服务线程函数,其实什么都没做

DWORD WINAPI Service(LPVOID lpvThread)

{

while(1)

{

AppendDbgMsg("service thread \r\n");//这里可以用命名管道与普通应用程序进行通信,也可以通过读写文件进行通信,然后完成自己的任务

Sleep(30000);

}

return 0;

}

//初始化SERVICE_STATUS ,为了方便设置

void InitServiceState(SERVICE_STATUS *pStatus)

{

(*pStatus).dwServiceType = SERVICE_WIN32_OWN_PROCESS;

(*pStatus).dwCurrentState = SERVICE_STOPPED;

(*pStatus).dwControlsAccepted = SERVICE_ACCEPT_STOP;

(*pStatus).dwWin32ExitCode = 0;

(*pStatus).dwServiceSpecificExitCode = 0;

(*pStatus).dwCheckPoint = 0;

(*pStatus).dwWaitHint = 0;

}

//设置状态和返回值、延时

BOOL ReportStatusToSCMgr(DWORD dwCurrentState, DWORD dwWin32ExitCode, DWORD dwWaitHint)

{

InitServiceState(&ssStatus);

ssStatus.dwCurrentState = dwCurrentState;

ssStatus.dwWin32ExitCode = dwWin32ExitCode;

ssStatus.dwWaitHint = dwWaitHint;

return SetServiceStatus(hService, &ssStatus);

}

服务程序中的主函数中有一段用来识别传入参数的模块,如果参数是install就进行安装,所以最好写一个批处理,然后用管理员权限运行,就能安装了,代码如下:

set filedir=%~dp0

set file=%filedir%MyServer

start %file% -install

pause

安装完之后就可以在本地服务管理器中看到对应的名字,按win+R,输入services.msc就可以看到,任务管理器中也可以看到,但最好通过services.msc进行开启、停止。

因为设置的是开机启动,所以立即重启会看到调试文件中的信息(调试文件的写入函数要自己提供,可以不写)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: