#winapi
#winapi
Вопрос:
Есть ли способ определить, запускается ли Windows-процесс как служба? Существует ли какой-либо фиксированный родительский процесс всех служб, который я могу идентифицировать, чтобы гарантировать, что процесс является сервисным процессом.
Комментарии:
1. возможно, используйте EnumServicesStatusExW для получения идентификатора процесса всех служб и сравнения с известным. но какой в этом смысл?
2. Некоторые службы выполняются внутри
svchost.exe
процесса, но большинство служб выполняются как автономные процессы. Итак, еслиscm.exe
при перечислении процессов не отображается как родительский процессProcess32(First|Next)()
, все, что вы можете сделать, это перечислить установленные службы в поисках.exe
интересующего вас файла или идентификатора процесса.3. Я хочу знать, запускается ли приложение из командной строки или как служба. EnumServicesStatusExW не помогает, потому что вызов будет выполнен до того, как EXE-файл будет зарегистрирован SCM.
4. Я хочу знать, запускается ли приложение из командной строки или как служба — вам нужно установить специальный параметр тега в command ( lpBinaryPathName ) при регистрации собственного приложения в качестве службы и при запуске — просто проверьте командную строку
Ответ №1:
если приложение предназначено для запуска как как служба, так и как отдельное приложение, лучший способ узнать, как запущено приложение — использовать командную строку. когда вы регистрируете службу с помощью CreateServiceW — передайте lpBinaryPathName некоторые аргументы. а затем при запуске — проверьте строку, возвращаемую GetCommandLineW() — присутствуют ли эти аргументы. если да — вы запускаетесь как служба, если нет — как отдельное приложение.
например, добавьте n
символ к пути к двоичному файлу службы :
WCHAR BinaryPathName[MAX_PATH 3];
ULONG cch = GetModuleFileNameW(0, BinaryPathName 1, _countof(BinaryPathName) - 3);
if (GetLastError() == NOERROR)
{
BinaryPathName[0] = '"';
BinaryPathName[cch 1] = '"';
BinaryPathName[cch 2] = 'n';
BinaryPathName[cch 3] = 0;
//CreateServiceW(.., BinaryPathName, ..);
}
n
(выбрано, потому что этот символ не может быть в командной строке, если выполнить приложение вручную)
а затем в точке входа приложения выполните очень простую и быструю проверку
if (wcschr(GetCommandLineW(), 'n'))
{
const static SERVICE_TABLE_ENTRY ste[] = { { L"my_service_name", ServiceMain }, {} };
StartServiceCtrlDispatcher(ste);
}
else
{
// run as standalone application
}
я думаю, что это решение является лучшим. однако возможны и другие. например, мы можем выполнить следующую проверку:
ULONG SessionId;
if (ProcessIdToSessionId(GetCurrentProcessId(), amp;SessionId) amp;amp;
WTSGetActiveConsoleSessionId() == SessionId)
{
// we not run as service;
}