分类:
2008-10-13 16:57:30
基于文档视图的NT服务程序
由于工作原因要求开发一个服务程序,需要有人机交互的界面,本想使用对话框模式来完成,但由于菜单、工具栏、分割窗口处理太麻烦,所以选择了文档视图结构,其中遇到了一些困难(其实说白了是对服务程序的理解不够详细)共享出来,以便大家再遇到这个问题时少走弯路。
先来简要说一下NT服务程序的主要几个环节:
1. 调用main方法来设置service_main方法。
2. 调用service_main方法设置ServiceCtrlHandler方法并启动工作循环(注意是工作循环)。
3. 利用ServiceCtrlHandler方法处理SCM(Service Control Manager)发给服务程序的消息。
第二步是使用工作循环,即代表着service_main方法不能返回直到服务停止,所以使用对话框实现服务程序时就自动符合了这个要求,因为DoMoudle函数直到对话框关闭后才返回,通常程序的处理流程都在对话框中处理,关闭对话框也就代表着要关闭服务程序,这时关闭对话框、DoMoudle函数返回、服务结束,很自然的一个流程就走了下来。但要使用文档视图结构上边这个流程就要做些变动了,因为文档视图结构程序初始化时是先创建文档模板,然后程序初始化完成并返回,所有工作都在MainFrame中完成,这样工作循环就没有建立起来,所以只能想一个变通的办法来实现工作循环,看下代码吧。
对话框模式:
void Service_start(DWORD dwArgc, LPTSTR *lpszArgv)
{
CxxxDlg dlg(&dlgParent);
theApp.m_pMainWnd = &dlg;
int nResponse = dlg.DoModal(); // 直到对话框关闭函数才返回
if (nResponse == IDOK)
{
}
else if (nResponse == IDCANCEL)
{
}
dlgParent.DestroyWindow();
}
文档视图模式:
void Service_start(DWORD dwArgc, LPTSTR *lpszArgv)
{
CSingleDocTemplate* pDocTemplate;
pDocTemplate = new CSingleDocTemplate(
IDR_MAINFRAME,
RUNTIME_CLASS(CPLMSPrefixServiceDoc),
RUNTIME_CLASS(CMainFrame),
RUNTIME_CLASS(CPLMSPrefixServiceView));
AddDocTemplate(pDocTemplate);
CCommandLineInfo cmdInfo;
ParseCommandLine(cmdInfo);
if (!ProcessShellCommand(cmdInfo))
return;
m_pMainWnd->ShowWindow(SW_SHOW);
m_pMainWnd->UpdateWindow();
// m_bIsRunning是服务程序控制开关,
// TRUE - 服务正在运行,
// FALSE - 服务程序关闭
// 如果服务程序在运行就一直执行循环(模拟工作循环,
// 但具体工作都在MainFrame中完成)
while (m_bIsRunning)
{
MSG msg;
while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
Sleep(50);
}
}
参考文章