关于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
找到可执行文件的路径,并将其传递给CreateService
和ScmManager
答案 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()
。