Windows EXE可以作为服务或应用程序运行。如何确定它是否作为服务运行?

时间:2011-09-29 20:07:01

标签: c windows winapi windows-services

我正在寻找一个Win32 API调用来返回我的进程的运行时上下文。我希望能够以编程方式测试我是作为服务运行还是作为标准应用程序进程运行。

我想到了几个想法....因为我总是有服务DAD.exe,有​​时作为他的孩子和服务上下文运行SON.exe ---有时SON.exe不是由DAD启动,而是由用户。

SON.EXE会使用API​​ whoami()来了解他正在运行的上下文。

现在DAD可以创建一个环境var - 然后SON可以测试这个var - 如果发现他知道他是DAD的儿子并因此作为服务运行.....但这很弱..

另一个想法是查看我的SID或令牌,看看我是否可以做出这个决定....再次看起来最好比单个API检查更复杂......

5 个答案:

答案 0 :(得分:1)

简单的低技术解决方案是将您的服务注册为使用命令行参数运行,并将其标识为服务。

答案 1 :(得分:1)

另一种选择是使用Tool Help library。使用它,您可以获取所有当前正在运行的进程的快照,然后您可以使用Process32FirstProcess32Next函数遍历所有进程。它们返回一个结构(PROCESSENTRY32),如下所示:

typedef struct tagPROCESSENTRY32 {
  DWORD     dwSize;
  DWORD     cntUsage;
  DWORD     th32ProcessID;
  ULONG_PTR th32DefaultHeapID;
  DWORD     th32ModuleID;
  DWORD     cntThreads;
  DWORD     th32ParentProcessID;
  LONG      pcPriClassBase;
  DWORD     dwFlags;
  TCHAR     szExeFile[MAX_PATH];
} PROCESSENTRY32, *PPROCESSENTRY32;

当您找到th32ProcessID与SON.exe匹配的那个进程时,您将浏览所有进程(请参阅GetCurrentProcessIdGetProcessId)。如果该结构的th32ParentProcessID与DAD.exe的th32ParentProcessID匹配,则表示您已从DAD.exe启动。

修改 回答你的评论,我想你可以更进一步,然后看看DAD.exe的父母是谁,如果它是services.exe,那么你就是服务。

答案 2 :(得分:1)

阅读文档,我认为您可以通过以下方式确定您是否处于交互式会话或服务中:

然后WSF_VISIBLE应该告诉你。

如果您想区分已登录的用户会话和非活动用户会话(快速用户切换),我猜您可以使用GetThreadDesktopGetUserObjectInformation(UOI_IO)


从服务内部告知的最佳和最简单的方法是在调用ServiceMain时设置标志。但是你正在测试一个子进程,所以请参见上文。

答案 3 :(得分:1)

found以下内容:

bool WinUtil::IsServiceUser(HANDLE hToken, bool *is_service) {
  if (is_service == NULL) {
    return false;
  }

  TOKEN_STATISTICS ts;
  DWORD dwSize = 0;
  // Use token logon LUID instead of user SID, for brevity and safety
  if (!::GetTokenInformation(hToken, TokenStatistics,
                             (LPVOID)&ts, sizeof(ts), &dwSize)) {
    return false;
  }

  // Compare LUID
  const LUID SystemLuid = SYSTEM_LUID;
  const LUID LocalServiceLuid = LOCALSERVICE_LUID;
  const LUID NetworkServiceLuid = NETWORKSERVICE_LUID;
  if (EqualLuid(SystemLuid, ts.AuthenticationId) ||
      EqualLuid(LocalServiceLuid, ts.AuthenticationId) ||
      EqualLuid(NetworkServiceLuid, ts.AuthenticationId)) {
    *is_service = true;
    return true;
  }

  // Not a service account
  *is_service = false;
  return true;
}
bool WinUtil::IsServiceProcess(bool *is_service) {
  if (is_service == NULL) {
    return false;
  }

  if (Util::IsVistaOrLater()) {
    // Session 0 is dedicated to services
    DWORD dwSessionId = 0;
    if (!::ProcessIdToSessionId(::GetCurrentProcessId(), &dwSessionId) ||
        (dwSessionId == 0)) {
      *is_service = true;
      return true;
    }
  }

  // Get process token
  HANDLE hProcessToken = NULL;
  if (!::OpenProcessToken(::GetCurrentProcess(),
                          TOKEN_QUERY | TOKEN_QUERY_SOURCE,
                          &hProcessToken)) {
    return false;
  }

  ScopedHandle process_token(hProcessToken);

  // Process token is one for a service account.
  if (!IsServiceUser(process_token.get(), is_service)) {
    return false;
  }

  return true;
}

答案 4 :(得分:0)

我认为您正在寻找Topshelf http://topshelf-project.com/,它可以解决繁重问题并使其更容易作为控制台运行或作为服务安装。 Topshelf hosting application debugging in VS2010