最近需求要写个服务程序,部分功能用MFC类库实现将非常方便,因此就没打算使用win32的服务程序,虽然那样对于服务很简单。
首先写好mfc的对话框程序,调试什么的,功能也都完成好。这一部分和平常的mfc对话框程序没有差别,之后的服务启动后打开的就是现在所完成的。
重点是服务部分。这里我找了很多文章,后来在
http://www.vckbase.com/document/viewdoc/?id=1095
一文中找到了解决办法。
服务部分大致和win32服务一样,打开SCM管理器,创建服务等,这样的代码也很多,就不细说了。
主要说说跟MFC相衔接以及遇到的一些问题。
衔接部分主要是在工程CPP的InitInstance函数中将对话框部分的代码注释掉,在这里调用服务的main函数,这里要注意main函数的参数了,其参数跟当前工程的编码环境有关。如果是Ansi的就使用main( __argc, __argv ); 而如果是Unicode环境就要使用main( __argc, __wargv );了。我也调试了好一会才发现这个问题,对应还要修改服务代码中的相关部分。
然后在工程cpp中添加两个全局函数,这两个函数主要用来控制服务的启动(即要显示对话框或者执行功能)和服务的停止(释放资源等)。
代码如下
VOID ServiceStart (DWORD dwArgc, LPTSTR *lpszArgv)
{
ReportStatusToSCMgr( SERVICE_RUNNING, NO_ERROR, 0 );
CMyDlg dlg;
theApp.m_pMainWnd = &dlg;
int nResponse = dlg.DoModal();
if (nResponse == IDOK)
{
}
else if (nResponse == IDCANCEL)
{
}
}
VOID ServiceStop()
{
((CMyDlg*)theApp.m_pMainWnd)->EndDialog(0);
theApp.m_pMainWnd = NULL;
}
注意上面,服务停止的函数中,theApp.m_pMainWnd = NULL;这句很重要,由于之前m_pMainWnd赋值为对话框的指针,但在对话框结束后,并没有将其置空,这样在停止服务后会有个报错,具体指向winmain.cpp的AfxWinMain函数中
if (pThread->m_pMainWnd != NULL)
{
TRACE(traceAppMsg, 0, "Warning: Destroying non-NULL m_pMainWnd\n");
pThread->m_pMainWnd->DestroyWindow();
}
销毁窗口处。就是由于野指针所引起的。
这两个函数主要用在服务对应的主函数中以及控制函数的退出相关部分。
这样基本就完成了。