我正在寻找一个Win32 API调用来返回我的进程的运行时上下文。 我希望能够以编程方式testing我作为服务运行,还是作为标准应用程序运行。
有几个想法想到….因为我总是有服务DAD.exe谁运行SON.exe有时作为他的孩子和服务的上下文—有时SON.exe不是由DAD和用户启动。
SON.EXE会做API whoami()来了解他正在运行的上下文。
现在,DAD可以创build一个环境variables – 然后SON可以testing这个变种 – 如果发现他知道他是DAD的一个儿子,因此作为服务运行…..但是这是微弱的…
另一个想法是看我的SID或令牌,看看我能不能做出这样的决定……再次,这看起来最好更复杂与单个API检查…
简单的低技术解决方案是注册您的服务,使用命令行参数运行,将其标识为服务。
另一种选择是使用工具帮助库 。 使用它,您可以获取当前正在运行的所有进程的快照,然后使用Process32First和Process32Next函数遍历所有进程。 这些返回一个结构( PROCESSENTRY32 ),看起来像:
typedef struct tagPROCESSENTRY32 { DWORD dwSize; DWORD cntUsage; DWORD th32ProcessID; ULONG_PTR th32DefaultHeapID; DWORD th32moduleeID; DWORD cntThreads; DWORD th32ParentProcessID; LONG pcPriClassBase; DWORD dwFlags; TCHAR szExeFile[MAX_PATH]; } PROCESSENTRY32, *PPROCESSENTRY32;
当您遍历所有进程时,只要找到th32ProcessID
与th32ProcessID
匹配的进程(请参阅GetCurrentProcessId或GetProcessId )。 如果该结构的th32ParentProcessID与DAD.exe相匹配,那么您知道您是从DAD.exe启动的。
编辑:回答你的评论,我想你可以更进一步,然后看看谁的父DAD.exe是,如果是services.exe,那么你是一个服务。
阅读文档,我想您可以通过以下方式确定您是否处于交互式会话或服务中:
GetProcessWindowStation
GetUserObjectInformation(UOI_FLAGS)
然后WSF_VISIBLE
应该告诉你。
如果你想区分登录用户会话和不活动(快速用户切换),我想你可以使用GetThreadDesktop
和GetUserObjectInformation(UOI_IO)
。
ServiceMain
被调用时,从服务内部最好和最简单的方法是设置一个标志。 但是你正在测试一个子进程,所以见上面。
我发现以下内容:
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; }
我认为你在寻找Topshelf http://topshelf-project.com/ ,它的繁重工作,使得它更容易作为控制台运行或作为服务安装。 Topshelf托管在VS2010中的应用程序调试