Windows(NT/2000)下有很多服务程序(它们在系统登录前运行),它们一般都没有界面,我们可以在服务管理器(运行services.msc)中启动和关闭它们。下面我试着修改一个有界面的MFC对话框程序,使它成为一个服务程序。网上提到了一种方法就是,从建立一个COM服务程序入手,然后将一个MFC项目改造成服务程序,最后让这一程序在启动时可以显示图形界面。这种方法的优点就是,程序向导已经帮我们写好了服务程序的主要代码,我们的任务就是把它们移植到MFC程序中(这个方法很不错!)。我的方法和这种方法思想基本一致,但也不完全一样。我是直接将有些写在CUI服务程序中的代码移植过来。主要思想就是把主服务函数等定义为全局函数,这样在主对话框类中就可以访问它们了。
此程序需要注意的地方:
一次只能安装一个服务,如果已安装过一个服务,先将其卸载再安装其他服务,设置其他应用程序时,在SCM启动后,因没有相应启动请求会被kill掉。本来以为任何程序都可以被设置为服务程序,后来实验发现,一般的应用程序被设置为服务程序后,由于它不能够与SCM进行通信,所以SCM无法将其启动。错误提示如下:(下面wcdj是我的服务名字)
本地计算机无法启动wcdj服务
错误1053:服务没有及时响应启动或控制请求
这个服务程序的主要流程如下:
SERVICE_TABLE_ENTRY DispatchTable[]={
{"Service1",ServiceMain},{NULL,NULL}};
if (!StartServiceCtrlDispatcher(DispatchTable))
{
AfxMessageBox("当不是用SCM启动程序的时候,程序执行下面的代码");
...
//显示我们服务程序的对话框
CTestDlg dlg;
//m_pMainWnd = &dlg;
int nResponse = dlg.DoModal();
if (nResponse == IDOK)
{
// TODO: Place code here to handle when the dialog is
// dismissed with OK
}
else if (nResponse == IDCANCEL)
{
// TODO: Place code here to handle when the dialog is
// dismissed with Cancel
}
}
否则程序会执行回调函数:
void WINAPI ServiceMain(DWORD argc, LPTSTR *argv)
{
AfxMessageBox("当用SCM启动程序的时候,程序执行下面的代码");
//初始化
m_ServiceStatus.dwServiceType = SERVICE_WIN32;
m_ServiceStatus.dwCurrentState = SERVICE_START_PENDING;
...
while(1)
{
//Sleep(3000);
//Place Your Code for processing here....
//显示我们服务程序的对话框(当SCM启动服务程序的时候(系统重启时或手动在SCM中启动时),也让它显示主对话框界面)
CTestDlg dlg;
//m_pMainWnd = &dlg;
int nResponse = dlg.DoModal();