每个Windows服务都调用其可执行的主要功能吗?

时间:2018-11-24 20:23:19

标签: c++ windows winapi windows-services

关于Windows服务,我有一个非常基本的问题,我安装了main这个函数,可以用它来安装我的服务,并且在主函数中也加载了一些配置数据:

int 
wmain(int argc, WCHAR* argv[])
{
    // it reads config and fill a global struct.
    ReadConfig();

    // if command == 'install'
    install_service();
}

这是服务的主要功能:

void WINAPI ServiceMain(DWORD argc, WCHAR* argv[])
{
   // this method retrieves the global config object.
   auto config_data = GetConfigData();

   // service stuff
}

这是另一个wmain函数,如果它不带任何参数(argc = 0!)运行,就会被调用:

bool
ServiceRunAsService()
{
    static const SERVICE_TABLE_ENTRY table[] = {
        { SERVICE_NAME, ServiceMain },
        { NULL, NULL }
    };

    g_hStopService = CreateEvent(0, TRUE, FALSE, 0);
    return StartServiceCtrlDispatcher(table) && GetLastError() != ERROR_FAILED_SERVICE_CONTROLLER_CONNECT;
}

我的问题是,当Windows要运行我的服务时(在PC关闭并再次打开后),它是否调用我的wmain函数(因此调用了ReadConfig函数)或调用已注册的ServiceMain函数? 我想指出install_service方法,通过GetModuleFileName找到可执行文件的路径,并将其传递给CreateServiceScmManager

2 个答案:

答案 0 :(得分:2)

启动可执行文件时,无论出于何种原因,都会调用exe入口点(如果之前未崩溃或挂接进程)。因此,在您的情况下,总是wmainCRTStartup(或您的exe实际入口点的名称)调用您的wmain。因此,可以-每次启动可执行文件时,都会调用您的wamin

和系统根本不能随便调用ServiceMain。它根本不知道它的地址。并且它没有注册。当您注册exe服务时,您会注册服务的命令行,但不会在exe中注册任何导出的名称。您的可执行文件只有在ServiceMain之后才开始服务并注册StartServiceCtrlDispatcher,必须从您的wmain

中调用该可执行文件

即使使用svchost.exe的dll形式服务-您注册必须从dll调用的导出函数作为服务入口点,或者默认情况下是ServiceMain。但是无论如何,即使是在这种情况下,也将首先调用您的DllMain(dll入口点)(如果存在)。如果是exe-入口点是强制性的,并且始终会被调用

答案 1 :(得分:2)

操作系统执行EXE时,它将调用EXE的入口点,然后该入口点将调用代码的(w)main()函数。作为服务运行时,您的代码必须调用StartServiceCtrlDispatcher(),这会在处理来自服务控制器的消息时循环并调用ServiceMain()