Есть ли "документированная" возможность определить в программе как она запущена — из сервисов или как консоль? Пример — апач можно и так и эдак пускать, если консоль — весь лог на экране, если сервис — то в eventLog-e.
Недокументированная возможность есть — "NtQueryInformationProcess" из ntdll.dll позволяет получить id породившего процесса, но не подходит — начальник не позволяет.
GetStdHandle() (если запуск произошел из сервисов) возвращает 0, но не INVALID_HANDLE_VALUE — как в m s d n написано, т.е. непонятно норамльный это хендл или нет.
А где еще рыть ума не приложу.
Здравствуйте vadimus, Вы писали:
V>Есть ли "документированная" возможность определить в программе как она запущена — из сервисов или как консоль? Пример — апач можно и так и эдак пускать, если консоль — весь лог на экране, если сервис — то в eventLog-e. V>Недокументированная возможность есть — "NtQueryInformationProcess" из ntdll.dll позволяет получить id породившего процесса, но не подходит — начальник не позволяет. V>GetStdHandle() (если запуск произошел из сервисов) возвращает 0, но не INVALID_HANDLE_VALUE — как в m s d n написано, т.е. непонятно норамльный это хендл или нет. V>А где еще рыть ума не приложу.
Это уже как-то раз здесь обсуждали. Просто вызываешь StartServiceCtrlDispatcher — если облом, то работаем как обычная консоль, иначе как сервис.
Здравствуйте Lexey, Вы писали:
L>Здравствуйте vadimus, Вы писали:
V>>Есть ли "документированная" возможность определить в программе как она запущена — из сервисов или как консоль? Пример — апач можно и так и эдак пускать, если консоль — весь лог на экране, если сервис — то в eventLog-e. V>>Недокументированная возможность есть — "NtQueryInformationProcess" из ntdll.dll позволяет получить id породившего процесса, но не подходит — начальник не позволяет. V>>GetStdHandle() (если запуск произошел из сервисов) возвращает 0, но не INVALID_HANDLE_VALUE — как в m s d n написано, т.е. непонятно норамльный это хендл или нет. V>>А где еще рыть ума не приложу.
L>Это уже как-то раз здесь обсуждали. Просто вызываешь StartServiceCtrlDispatcher — если облом, то работаем как обычная консоль, иначе как сервис.
Это тоже пробовал, но там таймаут какой-то непонятный (хотя догадываюсь почему), секунд 10, вроде тоже глюкаво как-то выходит.
Здравствуйте vadimus, Вы писали:
V>Здравствуйте Lexey, Вы писали:
L>>Здравствуйте vadimus, Вы писали:
V>>>Есть ли "документированная" возможность определить в программе как она запущена — из сервисов или как консоль? Пример — апач можно и так и эдак пускать, если консоль — весь лог на экране, если сервис — то в eventLog-e. V>>>Недокументированная возможность есть — "NtQueryInformationProcess" из ntdll.dll позволяет получить id породившего процесса, но не подходит — начальник не позволяет. V>>>GetStdHandle() (если запуск произошел из сервисов) возвращает 0, но не INVALID_HANDLE_VALUE — как в m s d n написано, т.е. непонятно норамльный это хендл или нет. V>>>А где еще рыть ума не приложу.
L>>Это уже как-то раз здесь обсуждали. Просто вызываешь StartServiceCtrlDispatcher — если облом, то работаем как обычная консоль, иначе как сервис.
V>Это тоже пробовал, но там таймаут какой-то непонятный (хотя догадываюсь почему), секунд 10, вроде тоже глюкаво как-то выходит.
Какой таймаут??? Сколько не отлаживал стартап своего сервиса — этот вызов сразу выпадает с ошибкой, если программу стратует не SCM.
Здравствуйте vadimus, Вы писали:
L>>Какой таймаут??? Сколько не отлаживал стартап своего сервиса — этот вызов сразу выпадает с ошибкой, если программу стратует не SCM.
V>void main( ) V>{ V> SERVICE_TABLE_ENTRY dispatchTable[] = V> { V> { "MyService", MyServiceStart }, V> { NULL, NULL } V> }; V> V> if (!StartServiceCtrlDispatcher( dispatchTable)) V> { V>// если консоль — сюда приходим через 10 сек. V> } V>}
V>У меня так
У меня сразу вываливается. А у тебя сервис с таким именем зарегистрирован?
Здравствуйте vadimus, Вы писали:
V>Есть ли "документированная" возможность определить в программе как она запущена — из сервисов или как консоль? Пример — апач можно и так и эдак пускать, если консоль — весь лог на экране, если сервис — то в eventLog-e. V>Недокументированная возможность есть — "NtQueryInformationProcess" из ntdll.dll позволяет получить id породившего процесса, но не подходит — начальник не позволяет.
1. Можно проверять свойства window station, к которой присоединен процесс. Фокус пройдет, если заранее известно, что сервис никогда не будет интерактивным. Тогда можно просто проверять на winsta0\default. Кстати, возможно, это правильное решение для целей выдачи лога: если есть доступ к экрану — лог на экране, если нет — в eventlog.
2. Можно взять токен процесса и перечислить все его группы. Если есть группа Service Logon (S-1-5-6), то процесс запущен в логон-сессии сервиса. Это означает, что либо сам процесс является сервисом, либо запущен (возможно, опосредованно) сервисом.
3. ID родительского процесса на Win2K/XP можно получить с помощью документированных функций Toolhelp32.
Здравствуйте Alex Fedotov, Вы писали:
V>>Есть ли "документированная" возможность определить в программе как она запущена — из сервисов или как консоль? Пример — апач можно и так и эдак пускать, если консоль — весь лог на экране, если сервис — то в eventLog-e. V>>Недокументированная возможность есть — "NtQueryInformationProcess" из ntdll.dll позволяет получить id породившего процесса, но не подходит — начальник не позволяет.
AF>1. Можно проверять свойства window station, к которой присоединен процесс. Фокус пройдет, если заранее известно, что сервис никогда не будет интерактивным. Тогда можно просто проверять на winsta0\default. Кстати, возможно, это правильное решение для целей выдачи лога: если есть доступ к экрану — лог на экране, если нет — в eventlog.
AF>2. Можно взять токен процесса и перечислить все его группы. Если есть группа Service Logon (S-1-5-6), то процесс запущен в логон-сессии сервиса. Это означает, что либо сам процесс является сервисом, либо запущен (возможно, опосредованно) сервисом.
Только надо иметь в виду, что для служб, работающих в системной логон-сессии такая проверка не пройдет. Впрочем, можно явно проверять на системную логон-сессию.
AF>3. ID родительского процесса на Win2K/XP можно получить с помощью документированных функций Toolhelp32.
И, наконец, я забыл последний способ, самый очевидный:
4. При регистрации сервиса указать параметр командной строки, по которому потом определять, что процесс был запущен как служба. Это, пожалуй, единственный способ, дающий 100% результат, поскольку, скажем, тот факт, что родительским процессом службы является services.exe является не более документированным, чем функции из ntdll.dll.
AF>>1. Можно проверять свойства window station, к которой присоединен процесс. Фокус пройдет, если заранее известно, что сервис никогда не будет интерактивным. Тогда можно просто проверять на winsta0\default. Кстати, возможно, это правильное решение для целей выдачи лога: если есть доступ к экрану — лог на экране, если нет — в eventlog.
Консоль возвращает Winsta0\default, а сервис — просто default? Наверно этим и воспользуюсь
AF>И, наконец, я забыл последний способ, самый очевидный:
AF>4. При регистрации сервиса указать параметр командной строки, по которому потом определять, что процесс был запущен как служба. Это, пожалуй, единственный способ, дающий 100% результат, поскольку, скажем, тот факт, что родительским процессом службы является services.exe является не более документированным, чем функции из ntdll.dll.
Если я не понял — поправьте... С командной строкой вообще не охота связываться — тогда все просто — с таким параметром — как консоль, без него — сервис, но ведь и сервису можно параметры передать Или в CreateService можно что-нибудь эдакое сказать?
Здравствуйте vadimus, Вы писали:
V>Здравствуйте Alex Fedotov, Вы писали:
AF>>>1. Можно проверять свойства window station, к которой присоединен процесс. Фокус пройдет, если заранее известно, что сервис никогда не будет интерактивным. Тогда можно просто проверять на winsta0\default. Кстати, возможно, это правильное решение для целей выдачи лога: если есть доступ к экрану — лог на экране, если нет — в eventlog.
V>Консоль возвращает Winsta0\default, а сервис — просто default? Наверно этим и воспользуюсь
У интерактивного сервиса будет те же winsta0\default, а у неинтерактивного будет нечто вроде Service-0x0-3e7$\default
AF>>И, наконец, я забыл последний способ, самый очевидный:
AF>>4. При регистрации сервиса указать параметр командной строки, по которому потом определять, что процесс был запущен как служба. Это, пожалуй, единственный способ, дающий 100% результат, поскольку, скажем, тот факт, что родительским процессом службы является services.exe является не более документированным, чем функции из ntdll.dll.
V>Если я не понял — поправьте... С командной строкой вообще не охота связываться — тогда все просто — с таким параметром — как консоль, без него — сервис, но ведь и сервису можно параметры передать Или в CreateService можно что-нибудь эдакое сказать?
Параметры командной строки исполняемого файла службы не имеют ничего общего с параметрами службы, передаваемыми в CreateService.
При регистрации службы с помощью CreateService, соответствующий параметр задает не просто имя исполняемого файла, а командную строку, которая может содержать и параметры, например
Теперь при запуске службы эта командная строка будет использоваться для создания процесса службы. Соответственно, myservice.exe получит параметр /service в командной строке, если запущен как служба.
Здравствуйте Alex Fedotov, Вы писали:
AF>У интерактивного сервиса будет те же winsta0\default, а у неинтерактивного будет нечто вроде Service-0x0-3e7$\default
У меня почему-то сервис возвращает просто default. Создавал его так
newService = CreateService(
scm, argv[1], // name
argv[2], // display name
SERVICE_ALL_ACCESS, SERVICE_WIN32_OWN_PROCESS,
SERVICE_DEMAND_START, SERVICE_ERROR_NORMAL,
argv[3], // full path
0, 0, 0, 0, 0);
И еще вопрос. Кроме как созданием "message file-а" в eventLog ничего путного не написать выходит? Получается на Borlande ничего не выйдет?
Здравствуйте vadimus, Вы писали:
AF>>У интерактивного сервиса будет те же winsta0\default, а у неинтерактивного будет нечто вроде Service-0x0-3e7$\default
V>У меня почему-то сервис возвращает просто default. Создавал его так
Возвращает на что? Service-0x0-3e7$\default — это имя оконной станции и имя десктопа. Оконная станция здесь — Service-0x0-3e7$, десктоп — default.
V>И еще вопрос. Кроме как созданием "message file-а" в eventLog ничего путного не написать выходит?
Нет, не выходит.
V>Получается на Borlande ничего не выйдет?
Ну почему, не выйдет? У него что, mc.exe в поставке нет? Ну так можно из Platform SDK взять.
AF>Возвращает на что? Service-0x0-3e7$\default — это имя оконной станции и имя десктопа. Оконная станция здесь — Service-0x0-3e7$, десктоп — default.
С этим вроде разобрался, кстати еще прочитал про StdHandle в первоисточнике —
The value of the handles returned by GetStdHandle will not be 0, 1, and 2, so the standard predefined stream constants in the STDIO.H header file (STDIN, STDOUT, and STDERR) cannot be used in functions that require a console handle
а сервис всегда возвращает 0.
AF>Ну почему, не выйдет? У него что, mc.exe в поставке нет? Ну так можно из Platform SDK взять.
Я сомневаюсь что получится —
создам *.mc, получу *.rc,*.rh,*.bin, собиру exe-шник борландом, куда подцепплю ресурсы собранные микрософтом И все это должно работать???
Здравствуйте vadimus, Вы писали:
AF>>Возвращает на что? Service-0x0-3e7$\default — это имя оконной станции и имя десктопа. Оконная станция здесь — Service-0x0-3e7$, десктоп — default.
V>С этим вроде разобрался, кстати еще прочитал про StdHandle в первоисточнике —
V>The value of the handles returned by GetStdHandle will not be 0, 1, and 2, so the standard predefined stream constants in the STDIO.H header file (STDIN, STDOUT, and STDERR) cannot be used in functions that require a console handle
V>а сервис всегда возвращает 0.
AF>>Ну почему, не выйдет? У него что, mc.exe в поставке нет? Ну так можно из Platform SDK взять.
V>Я сомневаюсь что получится — V>создам *.mc, получу *.rc,*.rh,*.bin, собиру exe-шник борландом, куда подцепплю ресурсы собранные микрософтом И все это должно работать???
Хм, по идее формат ресурсов должен быть одинаковым. В крайнем случае можешь собрать отдельную resource-only dll с помощью VC++.
Здравствуйте Lexey, Вы писали:
V>>Это тоже пробовал, но там таймаут какой-то непонятный (хотя догадываюсь почему), секунд 10, вроде тоже глюкаво как-то выходит.
L>Какой таймаут??? Сколько не отлаживал стартап своего сервиса — этот вызов сразу выпадает с ошибкой, если программу стратует не SCM.
Здравствуйте Dront, Вы писали:
D>Здравствуйте Lexey, Вы писали:
V>>>Это тоже пробовал, но там таймаут какой-то непонятный (хотя догадываюсь почему), секунд 10, вроде тоже глюкаво как-то выходит.
L>>Какой таймаут??? Сколько не отлаживал стартап своего сервиса — этот вызов сразу выпадает с ошибкой, если программу стратует не SCM.
D>Может, у вас ОС разные? В смысле NT и W2K?