C++ 如何使用WinAPI函数检查当前进程是否作为Windows服务运行?

C++ 如何使用WinAPI函数检查当前进程是否作为Windows服务运行?,c++,winapi,windows-services,C++,Winapi,Windows Services,我有一个程序,可以作为一个简单的控制台应用程序运行,也可以注册为Windows服务。我想在main()函数中检测当前运行的上下文: #include <windows.h> BOOL IsWindowsService() { ??? } int main(int argc, char** argv) { if (IsWindowsService()) { // Running as Windows Service... Ru

我有一个程序,可以作为一个简单的控制台应用程序运行,也可以注册为Windows服务。我想在
main()
函数中检测当前运行的上下文:

#include <windows.h>

BOOL IsWindowsService()
{
    ???
}

int main(int argc, char** argv)
{
    if (IsWindowsService())
    {
        // Running as Windows Service...
        RunService();
        return;
    }

    // Running as console application...    
    return 0;
}
#包括
BOOL-IsWindowsService()
{
???
}
int main(int argc,字符**argv)
{
if(IsWindowsService())
{
//正在作为Windows服务运行。。。
RunService();
返回;
}
//正在作为控制台应用程序运行。。。
返回0;
}
主要用例是拥有一个exe文件,该文件可以作为Windows服务安装和运行,并带有'--install'和'--start'参数,或者在控制台模式下(例如,从VS debugger)在没有任何参数的情况下执行

您能否帮助我实现
IsWindowsService()
函数

int __stdcall wWinMain(HINSTANCE, HINSTANCE, LPWSTR, int)
    { 
    SERVICE_TABLE_ENTRY ServiceTable[] =
    {
        { SERVICE_NAME,(LPSERVICE_MAIN_FUNCTION)ServiceMain },
    { NULL,NULL }
    };
    if (StartServiceCtrlDispatcher(ServiceTable))
        //service
    else app; // last error ERROR_FAILED_SERVICE_CONTROLLER_CONNECT
}


VOID WINAPI ServiceMain(DWORD argc, LPTSTR *argv)
{...}
文档

您可以使用系统()功能。它将执行任何可以在命令提示符下运行的命令。像这样使用它:

system("tasklist > tasks.txt");
这将把所有正在运行的任务存储到tasks.txt。然后,您可以通过在文件中搜索来检查您的程序是否正在运行

有关任务列表的详细信息,请运行命令提示符,执行以下操作:

tasklist /?

似乎我找到了一个优雅的解决方案,它不需要提供特殊的命令行参数来处理(由@RbMn提供的解决方案):


此解决方案之所以有效,是因为。

当您将应用程序注册为服务时-设置一些您已知的命令行,然后检查命令行-基于此,您可以了解您是通过服务键执行此命令行还是否。最好使用像
这样的符号,
|
如果您的应用程序通过某个文件系统外壳执行,则它不能在命令行中。现在您已经添加了
--start
参数,您根本不需要
IsWindowsService()
函数,您只需要检查参数。我需要,因为
--start
使用
StartService检查参数()
仅在
IsWindowsService()之外使用
scope!您的参数就在那里--
argc
argv
,所以在您需要做出决定之前,只需移动您的参数处理。这并不表示您的应用程序是一项服务。它可以从服务派生。您能否澄清您的问题,以解释是否“从服务派生”应该算还是不算?我的用例是有一个exe文件,可以作为Windows服务安装和运行,并带有“-install”和“-start”参数,或者在控制台模式下(例如,从VS debugger)不带任何参数地执行我理解。在这两种情况下,你的方法和米迦勒都会给出正确的答案。在你的EXE文件是从另一个服务中产生的情况下,他们会给出不同的答案。在那种情况下你想要什么答案?也可以认为米迦勒的方法是“完美的”。从某种意义上说,它根本不会向服务路径添加新代码。服务路径必须调用
StartServiceCtrlDispatcher()
。因此,您可以免费获得其返回值。
BOOL IsWindowsService()
{
    DWORD sessionId = 0;
    ProcessIdToSessionId(GetCurrentProcessId(), &sessionId);
    return !sessionId;
}