int APIENTRY WinMain(HINSTANCE hInstance,
                     HINSTANCE hPrevInstance,
                     LPSTR     lpCmdLine,
                     int       nCmdShow)
{
     Init();
    dwThreadID = ::GetCurrentThreadId();
    SERVICE_TABLE_ENTRY st[] =
    {
        { szServiceName, (LPSERVICE_MAIN_FUNCTION)ServiceMain },
{ szServiceName1, (LPSERVICE_MAIN_FUNCTION)ServiceMain1 },
        { NULL, NULL }
    };
    if (stricmp(lpCmdLine, "/install") == 0)
{
Install();
}
    else if (stricmp(lpCmdLine, "/uninstall") == 0)
{
Uninstall();
}
    else
{
if (!::StartServiceCtrlDispatcher(st))//这个函数没有调用到啊
{
MessageBox(NULL, _T("StartSev"), szServiceName, MB_OK);
LogEvent(_T("Register Service Main Function Error!"));
}
} return 0;
}void Init()
{
    hServiceStatus = NULL;
    status.dwServiceType = SERVICE_WIN32_OWN_PROCESS;//SERVICE_WIN32_SHARE_PROCESS
    status.dwCurrentState = SERVICE_STOPPED;
    status.dwControlsAccepted = SERVICE_ACCEPT_STOP;
    status.dwWin32ExitCode = 0;
    status.dwServiceSpecificExitCode = 0;
    status.dwCheckPoint = 0;
    status.dwWaitHint = 0;
}void WINAPI ServiceMain()
{
    // Register the control request handler
    status.dwCurrentState = SERVICE_START_PENDING;
status.dwControlsAccepted = SERVICE_ACCEPT_STOP; //注册服务控制
    hServiceStatus = RegisterServiceCtrlHandler(szServiceName, ServiceStrl);
    if (hServiceStatus == NULL)
    {
        LogEvent(_T("Handler not installed"));
        return;
    }
    SetServiceStatus(hServiceStatus, &status);    status.dwWin32ExitCode = S_OK;
    status.dwCheckPoint = 0;
    status.dwWaitHint = 0;
    status.dwCurrentState = SERVICE_RUNNING;//
    SetServiceStatus(hServiceStatus, &status); //模拟服务的运行,10后自动退出。应用时将主要任务放于此即可
int i = 0;
while (1)//i < 30
{
MessageBox(NULL, _T("Service"), szServiceName, MB_OK);//回调函数里不能调用MessageBox?
Sleep(1000);
i++;
}
//    status.dwCurrentState = SERVICE_STOPPED;//
    SetServiceStatus(hServiceStatus, &status);
    LogEvent(_T("Service stopped"));
}
//
void WINAPI ServiceMain1()
{
    // Register the control request handler
    status.dwCurrentState = SERVICE_START_PENDING;
status.dwControlsAccepted = SERVICE_ACCEPT_STOP|SERVICE_ACCEPT_PAUSE_CONTINUE;

//注册服务控制
    hServiceStatus = RegisterServiceCtrlHandler(szServiceName1, ServiceStrl1);
    if (hServiceStatus == NULL)
    {
        LogEvent(_T("Handler not installed"));
        return;
    }
    SetServiceStatus(hServiceStatus, &status);

    status.dwWin32ExitCode = S_OK;
    status.dwCheckPoint = 0;
    status.dwWaitHint = 0;
    status.dwCurrentState = SERVICE_RUNNING;//
    SetServiceStatus(hServiceStatus, &status);

//模拟服务的运行,10后自动退出。应用时将主要任务放于此即可
int i = 0;
while (1)//i < 10
{
//MessageBox(NULL, _T("Service1"), szServiceName1, MB_OK);
Sleep(1000);
i++;
}
//

    status.dwCurrentState = SERVICE_STOPPED;//
    SetServiceStatus(hServiceStatus, &status);
    LogEvent(_T("Service stopped"));
}void WINAPI ServiceStrl(DWORD dwOpcode)
{
    switch (dwOpcode)
    {
    case SERVICE_CONTROL_STOP:
status.dwCurrentState = SERVICE_STOP_PENDING;//
        SetServiceStatus(hServiceStatus, &status);
        PostThreadMessage(dwThreadID, WM_CLOSE, 0, 0);
        break;
    case SERVICE_CONTROL_PAUSE:
        break;
    case SERVICE_CONTROL_CONTINUE:
        break;
    case SERVICE_CONTROL_INTERROGATE:
        break;
    case SERVICE_CONTROL_SHUTDOWN:
        break;
    default:
        LogEvent(_T("Bad service request"));
    }
}
//
void WINAPI ServiceStrl1(DWORD dwOpcode)
{
    switch (dwOpcode)
    {
    case SERVICE_CONTROL_STOP:
status.dwCurrentState = SERVICE_STOPPED;//SERVICE_STOP_PENDING
        SetServiceStatus(hServiceStatus, &status);
        PostThreadMessage(dwThreadID, WM_CLOSE, 0, 0);
        break;
    case SERVICE_CONTROL_PAUSE:
status.dwCurrentState = SERVICE_PAUSE_PENDING;//
        SetServiceStatus(hServiceStatus, &status);
        //PostThreadMessage(dwThreadID, WM_CLOSE, 0, 0);
        break;
    case SERVICE_CONTROL_CONTINUE:
        break;
    case SERVICE_CONTROL_INTERROGATE:
        break;
    case SERVICE_CONTROL_SHUTDOWN:
        break;
    default:
        LogEvent(_T("Bad service request"));
    }
}BOOL Install()
{
    if (IsInstalled())
        return TRUE; //打开服务控制管理器
    SC_HANDLE hSCM = ::OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
    if (hSCM == NULL)
    {
        MessageBox(NULL, _T("Couldn't open service manager"), szServiceName, MB_OK);
        return FALSE;
    }    // Get the executable file path
    TCHAR szFilePath[MAX_PATH];
    ::GetModuleFileName(NULL, szFilePath, MAX_PATH); //创建服务
    SC_HANDLE hService = ::CreateService(
        hSCM, szServiceName, szServiceName,
        SERVICE_ALL_ACCESS, SERVICE_WIN32_OWN_PROCESS,//SERVICE_WIN32_SHARE_PROCESS
        SERVICE_DEMAND_START, SERVICE_ERROR_NORMAL,//SERVICE_AUTO_START
        szFilePath, NULL, NULL, _T(""), NULL, NULL);
    SC_HANDLE hService1 = ::CreateService(
        hSCM, szServiceName1, szServiceName1,
        SERVICE_ALL_ACCESS, SERVICE_WIN32_OWN_PROCESS,//SERVICE_WIN32_SHARE_PROCESS
        SERVICE_AUTO_START, SERVICE_ERROR_NORMAL,//SERVICE_DEMAND_START
        szFilePath, NULL, NULL, _T(""), NULL, NULL);    if (hService == NULL)
    {
        ::CloseServiceHandle(hSCM);
        MessageBox(NULL, _T("Couldn't create service"), szServiceName, MB_OK);
        return FALSE;
    }
//运行立即启动
if (!StartService(hService,0,NULL))
    {
//    MessageBox(NULL, _T("Couldn't start service"), szServiceName, MB_OK);
//    return FALSE;
    }
if (!StartService(hService1,0,NULL))
    {
//    MessageBox(NULL, _T("Couldn't start service"), szServiceName, MB_OK);
//    return FALSE;
    }    ::CloseServiceHandle(hService);
    ::CloseServiceHandle(hService1);
    ::CloseServiceHandle(hSCM);
    return TRUE;
}BOOL Uninstall()
{
    if (!IsInstalled())
        return TRUE;    SC_HANDLE hSCM = ::OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);    if (hSCM == NULL)
    {
        MessageBox(NULL, _T("Couldn't open service manager"), szServiceName, MB_OK);
        return FALSE;
    }    SC_HANDLE hService = ::OpenService(hSCM, szServiceName, SERVICE_STOP | DELETE);
SC_HANDLE hService1 = ::OpenService(hSCM, szServiceName1, SERVICE_STOP | DELETE);//    if (hService == NULL)
    {
        ::CloseServiceHandle(hSCM);
        MessageBox(NULL, _T("Couldn't open service"), szServiceName, MB_OK);
        return FALSE;
    }
    SERVICE_STATUS status;
    ::ControlService(hService, SERVICE_CONTROL_STOP, &status);
    ::ControlService(hService1, SERVICE_CONTROL_STOP, &status);// //删除服务
    BOOL bDelete = ::DeleteService(hService);
    ::CloseServiceHandle(hService);
    BOOL bDelete1 = ::DeleteService(hService1);
     ::CloseServiceHandle(hService1);
     ::CloseServiceHandle(hSCM);    if (bDelete)
        return TRUE;    LogEvent(_T("Service could not be deleted"));
    return FALSE;
}void LogEvent(LPCTSTR pFormat, ...)
{
    TCHAR    chMsg[256];
    HANDLE  hEventSource;
    LPTSTR  lpszStrings[1];
    va_list pArg;    va_start(pArg, pFormat);
    _vstprintf(chMsg, pFormat, pArg);
    va_end(pArg);    lpszStrings[0] = chMsg;

        hEventSource = RegisterEventSource(NULL, szServiceName);
if (hEventSource != NULL)
{
ReportEvent(hEventSource, EVENTLOG_INFORMATION_TYPE, 0, 0, NULL, 1, 0, (LPCTSTR*) &lpszStrings[0], NULL);
DeregisterEventSource(hEventSource);
}
}
问题如下:
1、StartServiceCtrlDispatcher函数有什么用,在本例中貌似没有调用到啊,我是在cmd中输命令调用Install函数的
2、在管理 的 服务中 停止 ServiceTest服务的时候,时间很长大概有几十秒,如果ServiceStrl函数中    SERVICE_STOP_PENDING换成SERVICE_STOPPED此时停止服务,弹出 服务的提示框:
     在本地计算机 无法终止ServiceTest 服务
     错误 1053:服务没有即使响应启动或控制请求
为什么?
3、
SERVICE_WIN32_OWN_PROCESS和参数SERVICE_WIN32_SHARE_PROCESS的区别是什么
如果用SERVICE_WIN32_SHARE_PROCESS参数的话,停止服务就会出现2中出现的问题
备注:这个是从VC知识库下的一个例子改了点,基本跟原来一样只是多加了一个服务,
      但是即使是只有一个服务的话,问题也是一样存在的望指导……
多谢了

解决方案 »

  1.   

    StartServiceCtrlDispatcher
    msdn中有说明
      

  2.   

    http://zhidao.baidu.com/question/95260733
      

  3.   

    这个我也看过了,
    都说要调用StartServiceCtrlDispatcher可是
    我的程序中没有调用啊,我输命令也只是输入:程序路径 /install  进行注册而已
    这样的话,没有调用到这个函数
      

  4.   

    窗口程序 WinMain 中 CreateWindow 没成功 不存在 release 版本调用 MessageBox 会失败,debug 版本成功MessageBox(NULL, _T("Service"), szServiceName, MB_OK);//回调函数里不能调用MessageBox?
    你的程序改为写到临时文件中去SERVICE_WIN32_OWN_PROCESS 独占一个进程的服务
    SERVICE_WIN32_SHARE_PROCESS 与其他服务共享一个进程的服务,出现2有可能其它的进程共享此服务,所以慢if (!::StartServiceCtrlDispatcher(st))//这个函数没有调用到啊,
    你可以放到前面去呀
      

  5.   

    if (!::StartServiceCtrlDispatcher(st))//这个函数没有调用到啊,
    你可以放到前面去呀
    ------------------------
    问题是这个函数究竟有什么用,我没调用也可以启动服务啊而且我放到
    SERVICE_TABLE_ENTRY st[] =
        {
            { szServiceName, (LPSERVICE_MAIN_FUNCTION)ServiceMain },
    { szServiceName1, (LPSERVICE_MAIN_FUNCTION)ServiceMain1 },
            { NULL, NULL }
        };
    在这调用//调用失败,GetLasteError返回1063错误
    这个又是怎么回事。
      

  6.   

    转的:
     服务控制管理程序启动服务程序后,等待服务程序主函数调用系统函 StartServiceCtrlDispatcher。一个SERVICE_WIN32_OWN_PROCESS 类型的服务应该立即调用 StartServiceCtrlDispatcher 函数,可以在服务启动后让服务入口点函数完成初始化工作。对于 SERVICE_WIN32_OWN_PROCESS 类型的服务和程序中所有服务共同的初始化工作可以在主函数中完成,但不要超过30秒。否则必须建立另外的线程完成这些共同的初始化工作,从而保证服务程序主函数能及时地调用 StartServiceCtrlDispatcher 函数。
    StartServiceCtrlDispatcher 函数负责把程序主线程连接到服务控制管理程序。else
    {
    if (!::StartServiceCtrlDispatcher(st))//这个函数没有调用到啊
      //如果未能和上面的如何参数匹配,则可能是服务控制管理程序来启动该程序。立即调用StartServiceCtrlDispatcher 函数。注释得很清楚 
      

  7.   

    1、StartServiceCtrlDispatcher应在服务被启动时调用,服务启动时由服务管理器加载的,不能像普通应用程序一样加载。你的程序除了服务之外,还可以作为普通应用程序来运行,通过命令行参数来执行服务的安装和移除,并非加载服务。
    2、服务在响应各种事件时,如果需要执行的时间较长,应每隔一段时间更新一次服务状态,累计时间最好不要超过20秒。
    3、一个服务程序可以同时提供多个服务(每个服务都要安装,各个服务都指定同一个EXE文件),SERVICE_WIN32_OWN_PROCESS表示每个服务独占一个进程;SERVICE_WIN32_SHARE_PROCESS表示多个服务使用同一进程,每个服务加载时都会调用相应的ServiceMain函数。
      

  8.   

    记住一个原则,服务程序必定是由服务管理器来管理的,因此你需要注册各种各样的回调函数,让服务管理器能正确控制你的服务和获取服务状态,服务进程加载也是由管理器完成的。手工启动的进程调用StartServiceCtrlDispatcher无效,因为你不是合法的启动者。如果你想在你的程序中启动自己的服务,应该调用StartService,它会通知服务管理器启动你的服务进程,服务管理器会创建另一个EXE进程,跟你现在执行的进程没有关系(即使两个进程是同一个EXE文件),因此启动服务的进程可以退出了。服务进程通常不能使用MessageBox函数,因为服务进程默认使用console桌面,不能显示任何窗口,除非你在控制面板中修改你的服务属性,允许它与桌面交互,窗口才能显示出来。但这种方式在VISTA及之后的版本也无效,还要考虑跨越SESSION的问题,这个问题更复杂。
      

  9.   

    按jameshooo说的,
    启动服务调用StartService函数就可以了
    而  手工启动的进程调用StartServiceCtrlDispatcher无效
    那什么时候调用StartServiceCtrlDispatcher才是有效的,
    否则这个函数岂不是没用了
      

  10.   

    1、StartServiceCtrlDispatcher函数有什么用,在本例中貌似没有调用到啊,我是在cmd中输命令调用Install函数的
    =====================
    你上面这段代码其实是将服务程序与服务管理程序合在一起的,当用参数时,它实际上是一个普通的,用于安装服务,删除服务的管理程序,此时,它是一个普通的console程序,不但没有执行StartServiceCtrlDispatcher,其实服务也没有启动,仅是安装服务或是删除服务.其实服务安装上去了,仅仅是在注册表中加入了服务的信息,服务本身并未启动.
    当SCM启动服务时,你后面的StartServiceCtrlspatcher才会被调用,此时,你的程序就是一个真正的服务程序了.
    2、在管理 的 服务中 停止 ServiceTest服务的时候,时间很长大概有几十秒,如果ServiceStrl函数中 SERVICE_STOP_PENDING换成SERVICE_STOPPED此时停止服务,弹出 服务的提示框:
      在本地计算机 无法终止ServiceTest 服务
      错误 1053:服务没有即使响应启动或控制请求
    为什么?
    =========================
    停止服务是要时间的,在停止时,SCM会查询状态,一个还未停止的服务,状态变了停止了,当然会出错.
    3、
    SERVICE_WIN32_OWN_PROCESS和参数SERVICE_WIN32_SHARE_PROCESS的区别是什么
    如果用SERVICE_WIN32_SHARE_PROCESS参数的话,停止服务就会出现2中出现的问题
    备注:这个是从VC知识库下的一个例子改了点,基本跟原来一样只是多加了一个服务,
      但是即使是只有一个服务的话,问题也是一样存在的
    =================================
    前者是一个EXE文件中只有一个服务,后者是一个EXE文件中有多个服务MessageBox(NULL, _T("Service"), szServiceName, MB_OK);//回调函数里不能调用MessageBox?
    ======================
    普通的服务程序是不能与桌面交互的,所以不能弹出对话框,同时,也不能用FindowWindow等函数,如果要用的话,在CreateService将dwServiceType参数加SERVICE_INTERACTIVE_PROCESS才行.
      

  11.   

    問題1   StartServiceCtrlDispatcher 這個函數的調用 
    ----------------------
      安裝或反安裝的時候,不會RUN到這裡,服務安裝好以後,你點開始服務,就會運行到這裡
    問題2   服務停止出錯
    ----------------------
    是因為你的循環是 while(1){}..這樣的循環,死循環,是停止不了的,你應該使用while(runing){}
    runing 是bool變量 ,在 ServiceStrl裡面停止的時候,把這個變量值改變,就可以停掉了關於服務中使用messagebox問題,服務所在的環境不是用戶的桌面session吧,messagebox就是彈出來了也不在你的桌面上,而是服務進程所屬於的session的桌面上面
      

  12.   

    你所说的这样的方式安装的服务,到底指的是什么呢?就楼上安装服务的代码并没有什么问题,他不过是安装部分和服务本身写在了一起而已.
    服务的安装,其实只不过是在注册表中加入一些信息而已.所以安装服务也不过是调用几个API,在注册表中加入一些服务的相关信息,写成一个单独的程序可以,像楼主这样,合关在一起的也可以.
      

  13.   

    StartServiceCtrlDispatcher 不是执行不到,而是无效,你可以自己判断当前进程的状态,判断命令行参数,好像服务启动时自动加上了一个参数,具体是哪个参数忘了。系统关闭时,所有服务都是由SCM来关闭,通常SCM向服务进程发送停止命令后会等待30秒,如果服务进程正确报告了SERVICE_STOPPED状态,SCM认为正常退出,不会再等,如果超过30秒,会强制杀死服务进程。
      

  14.   

    学习了很多,还有一些问题
    是不是可以这样理解:
    调用StartService或者选择在SCM中启动的时候
    又执行了一次程序StartService的执行过程又是怎么样的呢?跟在SCM中选择启动功能一样吗?