其实msdn上已经有现成的例子,具体可以见以下链接:
http://msdn.microsoft.com/zh-cn/library/bb540476%28d=lightweight%29.aspx?p=2
我下面根据msdn提供的例子以及我最近改写的一个windows服务来说说
1. sample.mc
首先得先编译它,直接cmd进入到sample.mc的目录下然后根据提示
mc -U sample.mc
rc -r sample.rc
这样就在smpple.mc目录下生成了sample.h文件,后面建立服务程序要用到的,msdn上例子所要编译dll,暂时我这里用不上
2. Svc.cpp
其实这已经是个完整的服务程序了,只是这里我可以稍微做些修改
void __cdecl _tmain(int argc, TCHAR *argv[])
{
// If command-line parameter is "install", install the service.
// Otherwise, the service is probably being started by the SCM.
if( lstrcmpi( argv[1], TEXT("install")) == 0 )//安装服务
{
SvcInstall();
return;
}
//注意下面是我要更改的
else if( lstrcmpi( argv[1], TEXT("delete")) == 0 )//删除服务
{
DoDeleteSvc(); //这个接口在SvcConfig.cpp中有提供,我们可以自己拷贝过来
return;
}
else if( lstrcmpi( argv[1], TEXT("debug")) == 0 )//调试服务
{
DebugSvc(); //后面说说这个的作用
return;
}
//后面还可以从SvcConfig.cpp或者SvcControl.cpp中拷贝这个对服务的操作,我们可以通过命令行来控制就行了
// TO_DO: Add any additional services for the process to this table.
SERVICE_TABLE_ENTRY DispatchTable[] =
{
{ SVCNAME, (LPSERVICE_MAIN_FUNCTION) SvcMain },
{ NULL, NULL }
};
// This call returns when the service has stopped.
// The process should simply terminate when the call returns.
if (!StartServiceCtrlDispatcher( DispatchTable ))
{
SvcReportEvent(TEXT("StartServiceCtrlDispatcher"));
}
}
3.把以前的应用程序改成服务
其实只要把以前的所有代码移植过来,更改一下main就行了,把main中的应用代码封装到另一个函数当中,我这里举例,比如放到下面的函数中
void AppFun(const char *str)
{
FILE *pF = fopen("E:/log.txt","a+");//写文件
if( pF )
{
fputs(str,pF);
fclose(pF);
}
}
void DebugSvc()//这里有debug的实现了
{
AppFun("hello world");
}
4.修改msdn例子上的代码
找到 SvcInit 的实现代码部分
VOID SvcInit( DWORD dwArgc, LPTSTR *lpszArgv)
{
// TO_DO: Declare and set any required variables.
// Be sure to periodically call ReportSvcStatus() with
// SERVICE_START_PENDING. If initialization fails, call
// ReportSvcStatus with SERVICE_STOPPED.
//这里添加服务程序的初始化代码,比如socket初始化,数据库连接是否成功再决定服务是否启动 之类的
// Create an event. The control handler function, SvcCtrlHandler,
// signals this event when it receives the stop control code.
ghSvcStopEvent = CreateEvent(
NULL, // default security attributes
TRUE, // manual reset event
FALSE, // not signaled
NULL); // no name
if ( ghSvcStopEvent == NULL)
{
ReportSvcStatus( SERVICE_STOPPED, NO_ERROR, 0 );
return;
}
// Report running status when initialization is complete.
ReportSvcStatus( SERVICE_RUNNING, NO_ERROR, 0 );
// TO_DO: Perform work until service stops.
AppFun("hello world");//加到这里就行了 ,哈哈这样我们的应用程序基本上算是成功了
while(1)
{
// Check whether to stop the service.
WaitForSingleObject(ghSvcStopEvent, INFINITE);
ReportSvcStatus( SERVICE_STOPPED, NO_ERROR, 0 );
return;
}
}
5.剩下的就是见一个新的工程,把该加的文件都加上去,编译,基本ok了
注意:不能直接运行,必须加命令行参数,不然是运行不起来的,服务程序不能跑consle的
6.介绍调试技巧
当然可以像加个debugSvc来调试应用程序部分,加上debug参数就行了
然后由于在服务程序下神马printf之类的当然就没用了,可以借助log来打印调试
再就是例子中有提供一个接口
VOID SvcReportEvent(LPTSTR szFunction)
这个其实也是一种log调试方法,你可以看下代码(然后根据自己的需求来更改),不过这里的log是记录到了windows事件查看器当中,具体你可以通过
控制面板---》管理工具 ---》事件查看器 ---》应用程序 ,在来源一列中是你的服务程序名称,双击你就会看到具体的调试信息了,
这里只是非常简单的部分,不过一个基本的服务程序已经算是完成了,安装启动,看看E:/是不是有个log.txt文件,里面是不是打印了hello world