C++ 是否每个windows服务都调用其可执行的主函数?

C++ 是否每个windows服务都调用其可执行的主函数?,c++,windows,winapi,windows-services,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 ServiceM

我有一个关于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
}
以下是服务的主要功能:

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
}
这里是另一个函数,如果它在没有任何参数(argc=0!)的情况下运行,则在my
wmain
函数中调用它:

我的问题是,当windows想要运行我的服务时(在电脑关闭并再次打开后),它是调用My
wmain
函数(并因此调用
ReadConfig
函数)还是调用注册的
ServiceMain
函数?
我想指出的是,当可执行文件启动时,
install\u service
方法通过
GetModuleFileName
找到可执行文件的路径,并将其传递给
CreateService
ScmManager
,无论出于何种原因,都会调用exe入口点(如果进程以前没有崩溃或挂接)。因此,在您的情况下,总是
wmainCRTStartup
(或者exe实际入口点的名称)调用您的
wmain
。所以是的-每次启动可执行文件时都会调用您的
wamin

而且系统无论如何也不能只调用
ServiceMain
。它根本不知道它的地址。而且它没有注册。当您注册exe服务时,您注册的是服务的命令行,而不是exe中的任何导出名称。只有在
启动ServiceCtrlDispatcher
之后,您的可执行文件才成为服务并注册
ServiceMain
,必须从
wmain


即使在使用
svchost.exe
的dll表单服务的情况下,您也可以注册导出的函数,该函数必须作为服务入口点从dll调用,或者默认情况下注册为
ServiceMain
。但无论如何,即使是在这种情况下,也会首先调用
DllMain
(dll入口点)(如果存在)。如果exe-入口点是必需的,并且在可执行文件启动时总是被调用,无论出于何种原因,都会调用exe入口点(如果进程以前未崩溃或挂接)。因此,在您的情况下,总是
wmainCRTStartup
(或者exe实际入口点的名称)调用您的
wmain
。所以是的-每次启动可执行文件时都会调用您的
wamin

而且系统无论如何也不能只调用
ServiceMain
。它根本不知道它的地址。而且它没有注册。当您注册exe服务时,您注册的是服务的命令行,而不是exe中的任何导出名称。只有在
启动ServiceCtrlDispatcher
之后,您的可执行文件才成为服务并注册
ServiceMain
,必须从
wmain


即使在使用
svchost.exe
的dll表单服务的情况下,您也可以注册导出的函数,该函数必须作为服务入口点从dll调用,或者默认情况下注册为
ServiceMain
。但无论如何,即使是在这种情况下,也会首先调用
DllMain
(dll入口点)(如果存在)。如果exe-入口点是必需的,并且在操作系统执行exe时总是被调用,它将调用exe的入口点,然后调用代码的
(w)main()
函数。当作为服务运行时,您的代码必须调用
StartServiceCtrlDispatcher()
,它循环处理来自服务控制器的消息并调用您的
ServiceMain()
当操作系统执行您的EXE时,它调用您的EXE入口点,然后调用代码的
(w)main()
函数。当作为服务运行时,您的代码必须调用
StartServiceCtrlDispatcher()
,它循环处理来自服务控制器的消息,并调用您的
ServiceMain()

为什么不直接检查?输出一条日志消息。老实说,我发现很难在服务中记录消息!我不知道windows如何调用exe入口点。所以
wmain
。在您未调用
StartServiceCtrlDispatcher
之前,系统对
ServiceMain
一无所知,为什么不直接检查一下?输出一条日志消息。老实说,我发现很难在服务中记录消息!我不知道windows如何调用exe入口点。所以
wmain
。在您不调用
StartServiceCtrlDispatcher
之前,系统对
ServiceMain
一无所知,因此最终调用我的可执行文件时没有任何参数,这会导致调用
ServiceRunAsService
(当然,当argc==0时会调用)?@Rachmaninoff-这取决于您如何通过
CreateService
注册您的服务-lpBinaryPathName(或注册表中的ImagePath)中的内容-服务实际上可以有而不是空的命令行。如果将exe混合用于正常启动和作为服务工作,则需要分析命令行,检测是否作为服务运行,并调用
StartServiceCtrlDispatcher
。如果您的可执行设计仅作为服务运行(您通过另一个应用程序注册),则无条件调用
StartServiceCtrlDispatcher
。无论如何-只有在
StartServiceCtrlDispatcher
调用和
wmain
始终在start调用后,您才成为服务。我给出了
CreateService
的可执行文件路径lpBinaryPathName@Rachmaninoff-这并没有改变要点。您可以使用现在为空的命令行。或者一些特殊的,用于指示您作为服务运行。在
wmain
中,您可以基于命令行或调用
StartServiceCtrlDispatcher
或执行其他任务,如注册/取消注册。因此,最终调用我的可执行文件时没有任何参数,这会导致调用
ServiceRunAsService
(当然,当argc==0时会调用它)?@Rachmaninoff-这取决于您如何通过
CreateService
注册您的服务-lpBinaryPathName(或Imag)中的内容