C++ 我们如何判断一个C++;应用程序是否作为Windows服务启动?
我们有一个控制台应用程序,可以从命令提示符下启动以进行调试,但我们也可以将其作为NT生产服务启动 现在,代码具有以下逻辑:C++ 我们如何判断一个C++;应用程序是否作为Windows服务启动?,c++,windows-services,C++,Windows Services,我们有一个控制台应用程序,可以从命令提示符下启动以进行调试,但我们也可以将其作为NT生产服务启动 现在,代码具有以下逻辑: if (__argc <= 1) { assumeService(); } else { assumeForgound(); } if(_argc您可以检查进程父进程是services.exe还是svchost.exe。或者您可以使用WinApi查询服务控制管理器您的服务是否已启动,并且当前进程id是否等于已启动的服务之一 在C++中,下面的代码会实现这一点
if (__argc <= 1) {
assumeService();
} else {
assumeForgound();
}
if(_argc您可以检查进程父进程是services.exe还是svchost.exe。或者您可以使用WinApi查询服务控制管理器您的服务是否已启动,并且当前进程id是否等于已启动的服务之一
在C++中,下面的代码会实现这一点(因为它是基于WiAPI的,这应该类似于C++,示例代码):
Windows API导入:
class WinApi
{
[DllImport("advapi32.dll", EntryPoint = "OpenSCManagerW", ExactSpelling = true, CharSet = CharSet.Unicode, SetLastError = true)]
public static extern IntPtr OpenSCManager(string machineName, string databaseName, uint dwAccess);
[DllImport("advapi32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool CloseServiceHandle(IntPtr hSCObject);
[DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Auto)]
public static extern IntPtr OpenService(IntPtr hSCManager, string lpServiceName, uint dwDesiredAccess);
[DllImport("advapi32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool ControlService(IntPtr hService, SERVICE_CONTROL dwControl, ref SERVICE_STATUS lpServiceStatus);
[DllImport("advapi32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
public static extern bool QueryServiceStatusEx(IntPtr serviceHandle, int infoLevel, byte[] buffer, int bufferSize, out int bytesNeeded);
[Flags]
public enum SCM_ACCESS : uint
{
/// <summary>
/// Required to connect to the service control manager.
/// </summary>
SC_MANAGER_CONNECT = 0x00001,
/// <summary>
/// Required to call the CreateService function to create a service
/// object and add it to the database.
/// </summary>
SC_MANAGER_CREATE_SERVICE = 0x00002,
/// <summary>
/// Required to call the EnumServicesStatusEx function to list the
/// services that are in the database.
/// </summary>
SC_MANAGER_ENUMERATE_SERVICE = 0x00004,
/// <summary>
/// Required to call the LockServiceDatabase function to acquire a
/// lock on the database.
/// </summary>
SC_MANAGER_LOCK = 0x00008,
/// <summary>
/// Required to call the QueryServiceLockStatus function to retrieve
/// the lock status information for the database.
/// </summary>
SC_MANAGER_QUERY_LOCK_STATUS = 0x00010,
/// <summary>
/// Required to call the NotifyBootConfigStatus function.
/// </summary>
SC_MANAGER_MODIFY_BOOT_CONFIG = 0x00020,
/// <summary>
/// Includes STANDARD_RIGHTS_REQUIRED, in addition to all access
/// rights in this table.
/// </summary>
SC_MANAGER_ALL_ACCESS = ACCESS_MASK.STANDARD_RIGHTS_REQUIRED |
SC_MANAGER_CONNECT |
SC_MANAGER_CREATE_SERVICE |
SC_MANAGER_ENUMERATE_SERVICE |
SC_MANAGER_LOCK |
SC_MANAGER_QUERY_LOCK_STATUS |
SC_MANAGER_MODIFY_BOOT_CONFIG,
GENERIC_READ = ACCESS_MASK.STANDARD_RIGHTS_READ |
SC_MANAGER_ENUMERATE_SERVICE |
SC_MANAGER_QUERY_LOCK_STATUS,
GENERIC_WRITE = ACCESS_MASK.STANDARD_RIGHTS_WRITE |
SC_MANAGER_CREATE_SERVICE |
SC_MANAGER_MODIFY_BOOT_CONFIG,
GENERIC_EXECUTE = ACCESS_MASK.STANDARD_RIGHTS_EXECUTE |
SC_MANAGER_CONNECT | SC_MANAGER_LOCK,
GENERIC_ALL = SC_MANAGER_ALL_ACCESS,
}
[Flags]
enum ACCESS_MASK : uint
{
DELETE = 0x00010000,
READ_CONTROL = 0x00020000,
WRITE_DAC = 0x00040000,
WRITE_OWNER = 0x00080000,
SYNCHRONIZE = 0x00100000,
STANDARD_RIGHTS_REQUIRED = 0x000f0000,
STANDARD_RIGHTS_READ = 0x00020000,
STANDARD_RIGHTS_WRITE = 0x00020000,
STANDARD_RIGHTS_EXECUTE = 0x00020000,
STANDARD_RIGHTS_ALL = 0x001f0000,
SPECIFIC_RIGHTS_ALL = 0x0000ffff,
ACCESS_SYSTEM_SECURITY = 0x01000000,
MAXIMUM_ALLOWED = 0x02000000,
GENERIC_READ = 0x80000000,
GENERIC_WRITE = 0x40000000,
GENERIC_EXECUTE = 0x20000000,
GENERIC_ALL = 0x10000000,
DESKTOP_READOBJECTS = 0x00000001,
DESKTOP_CREATEWINDOW = 0x00000002,
DESKTOP_CREATEMENU = 0x00000004,
DESKTOP_HOOKCONTROL = 0x00000008,
DESKTOP_JOURNALRECORD = 0x00000010,
DESKTOP_JOURNALPLAYBACK = 0x00000020,
DESKTOP_ENUMERATE = 0x00000040,
DESKTOP_WRITEOBJECTS = 0x00000080,
DESKTOP_SWITCHDESKTOP = 0x00000100,
WINSTA_ENUMDESKTOPS = 0x00000001,
WINSTA_READATTRIBUTES = 0x00000002,
WINSTA_ACCESSCLIPBOARD = 0x00000004,
WINSTA_CREATEDESKTOP = 0x00000008,
WINSTA_WRITEATTRIBUTES = 0x00000010,
WINSTA_ACCESSGLOBALATOMS = 0x00000020,
WINSTA_EXITWINDOWS = 0x00000040,
WINSTA_ENUMERATE = 0x00000100,
WINSTA_READSCREEN = 0x00000200,
WINSTA_ALL_ACCESS = 0x0000037f
}
[Flags]
public enum SERVICE_ACCESS : uint
{
STANDARD_RIGHTS_REQUIRED = 0xF0000,
SERVICE_QUERY_CONFIG = 0x00001,
SERVICE_CHANGE_CONFIG = 0x00002,
SERVICE_QUERY_STATUS = 0x00004,
SERVICE_ENUMERATE_DEPENDENTS = 0x00008,
SERVICE_START = 0x00010,
SERVICE_STOP = 0x00020,
SERVICE_PAUSE_CONTINUE = 0x00040,
SERVICE_INTERROGATE = 0x00080,
SERVICE_USER_DEFINED_CONTROL = 0x00100,
SERVICE_ALL_ACCESS = (STANDARD_RIGHTS_REQUIRED |
SERVICE_QUERY_CONFIG |
SERVICE_CHANGE_CONFIG |
SERVICE_QUERY_STATUS |
SERVICE_ENUMERATE_DEPENDENTS |
SERVICE_START |
SERVICE_STOP |
SERVICE_PAUSE_CONTINUE |
SERVICE_INTERROGATE |
SERVICE_USER_DEFINED_CONTROL)
}
[Flags]
public enum SERVICE_CONTROL : uint
{
STOP = 0x00000001,
PAUSE = 0x00000002,
CONTINUE = 0x00000003,
INTERROGATE = 0x00000004,
SHUTDOWN = 0x00000005,
PARAMCHANGE = 0x00000006,
NETBINDADD = 0x00000007,
NETBINDREMOVE = 0x00000008,
NETBINDENABLE = 0x00000009,
NETBINDDISABLE = 0x0000000A,
DEVICEEVENT = 0x0000000B,
HARDWAREPROFILECHANGE = 0x0000000C,
POWEREVENT = 0x0000000D,
SESSIONCHANGE = 0x0000000E
}
public enum SERVICE_STATE : uint
{
SERVICE_STOPPED = 0x00000001,
SERVICE_START_PENDING = 0x00000002,
SERVICE_STOP_PENDING = 0x00000003,
SERVICE_RUNNING = 0x00000004,
SERVICE_CONTINUE_PENDING = 0x00000005,
SERVICE_PAUSE_PENDING = 0x00000006,
SERVICE_PAUSED = 0x00000007
}
[Flags]
public enum SERVICE_ACCEPT : uint
{
STOP = 0x00000001,
PAUSE_CONTINUE = 0x00000002,
SHUTDOWN = 0x00000004,
PARAMCHANGE = 0x00000008,
NETBINDCHANGE = 0x00000010,
HARDWAREPROFILECHANGE = 0x00000020,
POWEREVENT = 0x00000040,
SESSIONCHANGE = 0x00000080,
}
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct SERVICE_STATUS
{
public static readonly int SizeOf = Marshal.SizeOf(typeof(SERVICE_STATUS));
public SERVICE_TYPES dwServiceType;
public SERVICE_STATE dwCurrentState;
public uint dwControlsAccepted;
public uint dwWin32ExitCode;
public uint dwServiceSpecificExitCode;
public uint dwCheckPoint;
public uint dwWaitHint;
}
[Flags]
public enum SERVICE_TYPES : int
{
SERVICE_KERNEL_DRIVER = 0x00000001,
SERVICE_FILE_SYSTEM_DRIVER = 0x00000002,
SERVICE_WIN32_OWN_PROCESS = 0x00000010,
SERVICE_WIN32_SHARE_PROCESS = 0x00000020,
SERVICE_INTERACTIVE_PROCESS = 0x00000100
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public class SERVICE_STATUS_PROCESS
{
public int serviceType;
public int currentState;
public int controlsAccepted;
public int win32ExitCode;
public int serviceSpecificExitCode;
public int checkPoint;
public int waitHint;
public int processID;
public int serviceFlags;
}
public const int SC_STATUS_PROCESS_INFO = 0;
}
类WinApi
{
[DllImport(“advapi32.dll”,EntryPoint=“OpenSCManagerW”,ExactSpelling=true,CharSet=CharSet.Unicode,SetLastError=true)]
公共静态外部IntPtr OpenSCManager(字符串machineName、字符串databaseName、uint dwAccess);
[DllImport(“advapi32.dll”,SetLastError=true)]
[返回:Marshallas(UnmanagedType.Bool)]
公共静态外部布尔闭合服务句柄(IntPtr hSCObject);
[DllImport(“advapi32.dll”,SetLastError=true,CharSet=CharSet.Auto)]
公共静态外部IntPtr OpenService(IntPtr hSCManager,字符串lpServiceName,uint dwDesiredAccess);
[DllImport(“advapi32.dll”,SetLastError=true)]
[返回:Marshallas(UnmanagedType.Bool)]
公共静态外部布尔控制服务(IntPtr hService、服务控制dwControl、参考服务状态lpServiceStatus);
[DllImport(“advapi32.dll”,CharSet=CharSet.Unicode,SetLastError=true)]
公共静态外部bool QueryServiceStatusEx(需要IntPtr serviceHandle、int infoLevel、byte[]缓冲区、int bufferSize、out int Bytes);
[旗帜]
公共枚举SCM_访问:uint
{
///
///需要连接到服务控制管理器。
///
SC_管理器_连接=0x00001,
///
///需要调用CreateService函数来创建服务
///对象并将其添加到数据库中。
///
SC_管理器_创建_服务=0x00002,
///
///调用EnumServicesStatusEx函数以列出
///数据库中的服务。
///
SC_管理器_枚举_服务=0x00004,
///
///调用LockServiceDatabase函数以获取
///锁定数据库。
///
SC_管理器_锁=0x00008,
///
///调用QueryServiceLockStatus函数以检索
///数据库的锁定状态信息。
///
SC_管理器_查询_锁定_状态=0x00010,
///
///需要调用NotifyBootConfigStatus函数。
///
SC_管理器_修改_引导_配置=0x00020,
///
///除所有访问权限外,还包括所需的标准权限
///此表中的权限。
///
SC_MANAGER_ALL_ACCESS=访问_MASK.STANDARD_RIGHTS_REQUIRED|
SC_管理器_连接|
SC_经理_创建_服务|
SC_经理_枚举_服务|
SC_经理_锁|
SC\U经理\u查询\u锁定\u状态|
SC_管理器_修改_引导_配置,
通用\u读取=访问\u掩码。标准\u权限\u读取|
SC_经理_枚举_服务|
SC\U经理\u查询\u锁定\u状态,
通用写入=访问掩码。标准写入权限|
SC_经理_创建_服务|
SC_管理器_修改_引导_配置,
通用\u执行=访问\u掩码。标准\u权限\u执行|
SC_管理器_连接| SC_管理器_锁,
通用\u ALL=SC\u管理器\u ALL\u访问,
}
[旗帜]
枚举访问掩码:uint
{
删除=0x00010000,
读取控制=0x00020000,
写入_DAC=0x00040000,
写入所有者=0x00080000,
同步=0x00100000,
标准权限要求=0x000f0000,
标准版权读取=0x00020000,
标准写入权限=0x00020000,
标准权限执行=0x00020000,
标准版权所有=0x001f0000,
特定权利所有=0x0000ffff,
访问系统安全性=0x01000000,
允许的最大值=0x02000000,
一般读取=0x8000000,
一般写入=0x40000000,
通用_EXECUTE=0x20000000,
通用_ALL=0x10000000,
桌面\u READOBJECTS=0x00000001,
桌面\u CREATEWINDOW=0x00000002,
桌面创建菜单=0x00000004,
桌面钩子控件=0x00000008,
桌面日志记录=0x00000010,
DESKTOP_JOURNALPLAYBACK=0x00000020,
桌面枚举=0x00000040,
桌面_WRITEOBJECTS=0x00000080,
桌面\u SWITCHDESKTOP=0x00000100,
WINSTA_ENUMDESKTOPS=0x00000001,
WINSTA_READATTRIBUTES=0x00000002,
WINSTA_ACCESSCLIPBOARD=0x00000004,
WINSTA_CREATEDESKTOP=0x00000008,
WINSTA_WRITEATTRIBUTES=0x00000010,
WINSTA_ACCESSGLOBALATOMS=0x00000020,
WINSTA_EXITWINDOWS=0x00000040,
WINSTA_ENUMERATE=0x00000100,
WINSTA_READSCREEN=0x00000200,
WINSTA_ALL_ACCESS=0x0000037f
}
[旗帜]
公共枚举服务访问:uint
{
标准权限要求=0xF0000,
服务查询配置=0x00001,
服务更改配置=0x00002,
服务查询状态=0x00004,
服务枚举依赖项=0x00008,
服务启动=0x00010,
服务站=0x00020,
服务暂停继续=0x00040,
服务查询=0x00080,
服务\用户\定义\控制=0x00100,
服务\u所有\u访问=(需要标准\u权限)|
服务查询配置|
服务更改配置|
服务查询状态|
服务\u枚举\u受抚养人|
服务启动|
class WinApi
{
[DllImport("advapi32.dll", EntryPoint = "OpenSCManagerW", ExactSpelling = true, CharSet = CharSet.Unicode, SetLastError = true)]
public static extern IntPtr OpenSCManager(string machineName, string databaseName, uint dwAccess);
[DllImport("advapi32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool CloseServiceHandle(IntPtr hSCObject);
[DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Auto)]
public static extern IntPtr OpenService(IntPtr hSCManager, string lpServiceName, uint dwDesiredAccess);
[DllImport("advapi32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool ControlService(IntPtr hService, SERVICE_CONTROL dwControl, ref SERVICE_STATUS lpServiceStatus);
[DllImport("advapi32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
public static extern bool QueryServiceStatusEx(IntPtr serviceHandle, int infoLevel, byte[] buffer, int bufferSize, out int bytesNeeded);
[Flags]
public enum SCM_ACCESS : uint
{
/// <summary>
/// Required to connect to the service control manager.
/// </summary>
SC_MANAGER_CONNECT = 0x00001,
/// <summary>
/// Required to call the CreateService function to create a service
/// object and add it to the database.
/// </summary>
SC_MANAGER_CREATE_SERVICE = 0x00002,
/// <summary>
/// Required to call the EnumServicesStatusEx function to list the
/// services that are in the database.
/// </summary>
SC_MANAGER_ENUMERATE_SERVICE = 0x00004,
/// <summary>
/// Required to call the LockServiceDatabase function to acquire a
/// lock on the database.
/// </summary>
SC_MANAGER_LOCK = 0x00008,
/// <summary>
/// Required to call the QueryServiceLockStatus function to retrieve
/// the lock status information for the database.
/// </summary>
SC_MANAGER_QUERY_LOCK_STATUS = 0x00010,
/// <summary>
/// Required to call the NotifyBootConfigStatus function.
/// </summary>
SC_MANAGER_MODIFY_BOOT_CONFIG = 0x00020,
/// <summary>
/// Includes STANDARD_RIGHTS_REQUIRED, in addition to all access
/// rights in this table.
/// </summary>
SC_MANAGER_ALL_ACCESS = ACCESS_MASK.STANDARD_RIGHTS_REQUIRED |
SC_MANAGER_CONNECT |
SC_MANAGER_CREATE_SERVICE |
SC_MANAGER_ENUMERATE_SERVICE |
SC_MANAGER_LOCK |
SC_MANAGER_QUERY_LOCK_STATUS |
SC_MANAGER_MODIFY_BOOT_CONFIG,
GENERIC_READ = ACCESS_MASK.STANDARD_RIGHTS_READ |
SC_MANAGER_ENUMERATE_SERVICE |
SC_MANAGER_QUERY_LOCK_STATUS,
GENERIC_WRITE = ACCESS_MASK.STANDARD_RIGHTS_WRITE |
SC_MANAGER_CREATE_SERVICE |
SC_MANAGER_MODIFY_BOOT_CONFIG,
GENERIC_EXECUTE = ACCESS_MASK.STANDARD_RIGHTS_EXECUTE |
SC_MANAGER_CONNECT | SC_MANAGER_LOCK,
GENERIC_ALL = SC_MANAGER_ALL_ACCESS,
}
[Flags]
enum ACCESS_MASK : uint
{
DELETE = 0x00010000,
READ_CONTROL = 0x00020000,
WRITE_DAC = 0x00040000,
WRITE_OWNER = 0x00080000,
SYNCHRONIZE = 0x00100000,
STANDARD_RIGHTS_REQUIRED = 0x000f0000,
STANDARD_RIGHTS_READ = 0x00020000,
STANDARD_RIGHTS_WRITE = 0x00020000,
STANDARD_RIGHTS_EXECUTE = 0x00020000,
STANDARD_RIGHTS_ALL = 0x001f0000,
SPECIFIC_RIGHTS_ALL = 0x0000ffff,
ACCESS_SYSTEM_SECURITY = 0x01000000,
MAXIMUM_ALLOWED = 0x02000000,
GENERIC_READ = 0x80000000,
GENERIC_WRITE = 0x40000000,
GENERIC_EXECUTE = 0x20000000,
GENERIC_ALL = 0x10000000,
DESKTOP_READOBJECTS = 0x00000001,
DESKTOP_CREATEWINDOW = 0x00000002,
DESKTOP_CREATEMENU = 0x00000004,
DESKTOP_HOOKCONTROL = 0x00000008,
DESKTOP_JOURNALRECORD = 0x00000010,
DESKTOP_JOURNALPLAYBACK = 0x00000020,
DESKTOP_ENUMERATE = 0x00000040,
DESKTOP_WRITEOBJECTS = 0x00000080,
DESKTOP_SWITCHDESKTOP = 0x00000100,
WINSTA_ENUMDESKTOPS = 0x00000001,
WINSTA_READATTRIBUTES = 0x00000002,
WINSTA_ACCESSCLIPBOARD = 0x00000004,
WINSTA_CREATEDESKTOP = 0x00000008,
WINSTA_WRITEATTRIBUTES = 0x00000010,
WINSTA_ACCESSGLOBALATOMS = 0x00000020,
WINSTA_EXITWINDOWS = 0x00000040,
WINSTA_ENUMERATE = 0x00000100,
WINSTA_READSCREEN = 0x00000200,
WINSTA_ALL_ACCESS = 0x0000037f
}
[Flags]
public enum SERVICE_ACCESS : uint
{
STANDARD_RIGHTS_REQUIRED = 0xF0000,
SERVICE_QUERY_CONFIG = 0x00001,
SERVICE_CHANGE_CONFIG = 0x00002,
SERVICE_QUERY_STATUS = 0x00004,
SERVICE_ENUMERATE_DEPENDENTS = 0x00008,
SERVICE_START = 0x00010,
SERVICE_STOP = 0x00020,
SERVICE_PAUSE_CONTINUE = 0x00040,
SERVICE_INTERROGATE = 0x00080,
SERVICE_USER_DEFINED_CONTROL = 0x00100,
SERVICE_ALL_ACCESS = (STANDARD_RIGHTS_REQUIRED |
SERVICE_QUERY_CONFIG |
SERVICE_CHANGE_CONFIG |
SERVICE_QUERY_STATUS |
SERVICE_ENUMERATE_DEPENDENTS |
SERVICE_START |
SERVICE_STOP |
SERVICE_PAUSE_CONTINUE |
SERVICE_INTERROGATE |
SERVICE_USER_DEFINED_CONTROL)
}
[Flags]
public enum SERVICE_CONTROL : uint
{
STOP = 0x00000001,
PAUSE = 0x00000002,
CONTINUE = 0x00000003,
INTERROGATE = 0x00000004,
SHUTDOWN = 0x00000005,
PARAMCHANGE = 0x00000006,
NETBINDADD = 0x00000007,
NETBINDREMOVE = 0x00000008,
NETBINDENABLE = 0x00000009,
NETBINDDISABLE = 0x0000000A,
DEVICEEVENT = 0x0000000B,
HARDWAREPROFILECHANGE = 0x0000000C,
POWEREVENT = 0x0000000D,
SESSIONCHANGE = 0x0000000E
}
public enum SERVICE_STATE : uint
{
SERVICE_STOPPED = 0x00000001,
SERVICE_START_PENDING = 0x00000002,
SERVICE_STOP_PENDING = 0x00000003,
SERVICE_RUNNING = 0x00000004,
SERVICE_CONTINUE_PENDING = 0x00000005,
SERVICE_PAUSE_PENDING = 0x00000006,
SERVICE_PAUSED = 0x00000007
}
[Flags]
public enum SERVICE_ACCEPT : uint
{
STOP = 0x00000001,
PAUSE_CONTINUE = 0x00000002,
SHUTDOWN = 0x00000004,
PARAMCHANGE = 0x00000008,
NETBINDCHANGE = 0x00000010,
HARDWAREPROFILECHANGE = 0x00000020,
POWEREVENT = 0x00000040,
SESSIONCHANGE = 0x00000080,
}
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct SERVICE_STATUS
{
public static readonly int SizeOf = Marshal.SizeOf(typeof(SERVICE_STATUS));
public SERVICE_TYPES dwServiceType;
public SERVICE_STATE dwCurrentState;
public uint dwControlsAccepted;
public uint dwWin32ExitCode;
public uint dwServiceSpecificExitCode;
public uint dwCheckPoint;
public uint dwWaitHint;
}
[Flags]
public enum SERVICE_TYPES : int
{
SERVICE_KERNEL_DRIVER = 0x00000001,
SERVICE_FILE_SYSTEM_DRIVER = 0x00000002,
SERVICE_WIN32_OWN_PROCESS = 0x00000010,
SERVICE_WIN32_SHARE_PROCESS = 0x00000020,
SERVICE_INTERACTIVE_PROCESS = 0x00000100
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public class SERVICE_STATUS_PROCESS
{
public int serviceType;
public int currentState;
public int controlsAccepted;
public int win32ExitCode;
public int serviceSpecificExitCode;
public int checkPoint;
public int waitHint;
public int processID;
public int serviceFlags;
}
public const int SC_STATUS_PROCESS_INFO = 0;
}
#include <windows.h>
#include <tchar.h>
#include <strsafe.h>
#include <aclapi.h>
#include <stdio.h>
bool IsRunningAsService(const TCHAR* szSvcName)
{
SERVICE_STATUS_PROCESS ssStatus;
DWORD dwBytesNeeded;
SC_HANDLE schSCManager = OpenSCManager(
NULL, // local computer
NULL, // servicesActive database
SC_MANAGER_ALL_ACCESS); // full access rights
if (NULL == schSCManager)
{
printf("OpenSCManager failed (%d)\n", GetLastError());
return false;
}
// Get a handle to the service.
SC_HANDLE schService = OpenService(
schSCManager, // SCM database
szSvcName, // name of service
SERVICE_ALL_ACCESS); // full access
if (schService == NULL)
{
printf("OpenService failed (%d)\n", GetLastError());
CloseServiceHandle(schSCManager);
return false;
}
// Check the status in case the service is not stopped.
if (!QueryServiceStatusEx(
schService, // handle to service
SC_STATUS_PROCESS_INFO, // information level
(LPBYTE) &ssStatus, // address of structure
sizeof(SERVICE_STATUS_PROCESS), // size of structure
&dwBytesNeeded ) ) // size needed if buffer is too small
{
printf("QueryServiceStatusEx failed (%d)\n", GetLastError());
CloseServiceHandle(schService);
CloseServiceHandle(schSCManager);
return false;
}
return GetCurrentProcessId() == ssStatus.dwProcessId;
}
bool
CArchMiscWindows::wasLaunchedAsService()
{
CString name;
if (!getParentProcessName(name)) {
LOG((CLOG_ERR "cannot determine if process was launched as service"));
return false;
}
return (name == SERVICE_LAUNCHER);
}
bool
CArchMiscWindows::getParentProcessName(CString &name)
{
PROCESSENTRY32 parentEntry;
if (!getParentProcessEntry(parentEntry)){
LOG((CLOG_ERR "could not get entry for parent process"));
return false;
}
name = parentEntry.szExeFile;
return true;
}
BOOL WINAPI
CArchMiscWindows::getSelfProcessEntry(PROCESSENTRY32& entry)
{
// get entry from current PID
return getProcessEntry(entry, GetCurrentProcessId());
}
BOOL WINAPI
CArchMiscWindows::getParentProcessEntry(PROCESSENTRY32& entry)
{
// get the current process, so we can get parent PID
PROCESSENTRY32 selfEntry;
if (!getSelfProcessEntry(selfEntry)) {
return FALSE;
}
// get entry from parent PID
return getProcessEntry(entry, selfEntry.th32ParentProcessID);
}
BOOL WINAPI
CArchMiscWindows::getProcessEntry(PROCESSENTRY32& entry, DWORD processID)
{
// first we need to take a snapshot of the running processes
HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (snapshot == INVALID_HANDLE_VALUE) {
LOG((CLOG_ERR "could not get process snapshot (error: %i)",
GetLastError()));
return FALSE;
}
entry.dwSize = sizeof(PROCESSENTRY32);
// get the first process, and if we can't do that then it's
// unlikely we can go any further
BOOL gotEntry = Process32First(snapshot, &entry);
if (!gotEntry) {
LOG((CLOG_ERR "could not get first process entry (error: %i)",
GetLastError()));
return FALSE;
}
while(gotEntry) {
if (entry.th32ProcessID == processID) {
// found current process
return TRUE;
}
// now move on to the next entry (when we reach end, loop will stop)
gotEntry = Process32Next(snapshot, &entry);
}
return FALSE;
if(GetConsoleWindow())
{
//Running as console Application
}
else
{
//Running as Service
}