| Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате |
| Форум программистов > Delphi: Общие вопросы > Служба и запуск программы |
| Автор: ZBugz 7.8.2014, 13:25 |
| Добрый день Никогда не писал службы... Помогайте... Задача проста, надо написать службу, установить ее, а служба должна следить, запущена ли моя програма. Если нет, то запустить, если да, то ничего не делать... |
| Автор: kami 7.8.2014, 22:41 |
| Ох, и нажили же вы проблем себе http://www.cromis.net/blog/2010/01/how-to-start-a-gui-process-from-service-under-windows-vista7/ P.S. Ссылка любезно предоставлена kirillkr |
| Автор: drkot 8.8.2014, 01:42 |
первые вопросы на которые надо дать ответ, это: Под кем запущена программа? Где запущена программа? только после этого можно определиться с тем, Как? решить задачу |
| Автор: ZBugz 8.8.2014, 06:19 | ||||
1. По текущем пользователем. Хотя, если есть варианты указать другого пользователя, я не против это тоже написать. 2. В той же папке где и сервис. Задача у меня простая... Я написал программу, она в автозапуске на сервере... Но иногда выключается питание и APC не хватает, после подачи питания, сервер загружается, но программа то не запускается, если не войти под юзером... А надо что бы запускалась. Вот и хочу написать сервис, который стартанет мою программу... Добавлено через 48 секунд
Спасибо, гляну. Я и сервис то сам еще не писал даже |
| Автор: Delvish 8.8.2014, 10:38 |
начиная с Vista сервисы умеют запускаться вне зависимости от регистрации пользователя. так что вполне себе решение проблемы с автозапуском |
| Автор: kami 8.8.2014, 11:34 | ||
вообще-то нет. Сервис в любом случае работает из-под пользователя, и пошло это с момента их появления. В большинстве своем этот "изподпользователь" - LOCALSYSTEM. А начиная с Висты просто запретили интерактивность сервисов. Но даже интерактивному сервису совершенно необязателен был активный рабочий стол. В любом случае - чтобы запустить приложение в оконной станции, сессии и рабочем столе пользователя - надо, чтобы этот пользователь был залогиненю |
| Автор: Delvish 8.8.2014, 13:54 | ||
Извиняюсь, спутал с приложениями, запускаемыми планировщиком с возможностью выбора варианта запуска "вне зависимости от регистрации пользователя". Кстати, не так давно я поднимал схожую тему и реализовал почти так, как это предлагается в статье, приведенной Вами в первом посте этой темы, только реализовал несколько проще:
|
| Автор: kami 8.8.2014, 15:10 | ||
Delvish, увы, но этого кода мало, о чем явно говорится в ремарках MSDN, самое главное -
Отсюда - запускаемое приложение не получит нужные данные из реестра и доступ к сетевым ресурсам. Добавлено через 58 секунд Причем - совершенно не обязательно, что приложение само будет пытаться лезть в реестр, вполне возможно туда полезут используемые dll... |
| Автор: drkot 8.8.2014, 16:01 | ||
Текущий это какой? Тот кто владеет терминальной сессией? или RDP сессией? Речь не о местоположении файла, речь о пространстве имен. Под какой сессией, на каком рабочем столе? Вам наверно надо перенести функционал в сервис и всех то делов... Или просто из сервиса выполнить shellExec и пусть себе работает может, но смысла в этом особого нет. если только конкретный пользователь не обладает "ценными" правами (например это аккаунт на сервере баз данных MSSQL).
да ну что Вы говорите? а в nt4 они что ждали пока админ протрезвеет и залогинется? не запретили, а привели к "безопасному" виду. Показать окно на любом рабочем столе возможно, но окна создаваемые сервисом по умолчанию привязаны его рабочему столу. нет не надо. процесс от имени любого пользователя может работать в пределах любого пространства если это не запрещено политикой. изначально это не запрещено. в частности планировщик задач так и работает. ZBugz, в вашем случае лучший и простейший вариант создать задачу в планировщике, указать там нужного пользователя и все. Подходящий триггер "При запуске". Пока пользователь не залогинется программа будет висеть на десктопе default пользователя system, как только появится пользователь, программа перескочит на его рабочий стол. |
| Автор: kami 8.8.2014, 16:26 | ||
Окна от интерактивных сервисов в Висте показывались на отдельном рабочем столе, переключение на который происходит с использованием службы "Обнаружения интерактивных служб". В Win7 эта служба по умолчанию не в автозапуске. Сам сервис не может получить доступ к рабочему столу пользователя.
Пример/ссылку возможности этого можно? помнится, сие для меня была очень большая проблема (которую я не решил, а до сих пор хочется) - отобразить окно, созданное сервисом на десктопе пользователя, сессию которого можно получить через WTSGetActiveConsoleSessionID. |
| Автор: drkot 8.8.2014, 17:32 | ||
Да что вы говорите? и кто же ему помешает? Создавать окна с правами системы на рабочем столе терминального пользователя потенциально не безопасно, это да... так пусть разработчик думает... его предупредили... А вот то что окна сервиса автоматически не выкидывает на терминальный рабочий стол, это да... и это правильно. ну... в висте много странностей было... переходный период, у всех бывает... наверно обратная совместимость требовалась, потом как основные игроки перестроились службу отключили. у Rouse_ есть пример... там как раз сервис с окнами, не помню только насколько он соответствует этой теме... а в целом делается примерно так:
этот параметр и определяет на какой рабочий стол будет подцеплен поток. Создаем поток привязываем его к нужному столу Создаем окно в контексте потока. Оно отобразилось на нужном рабочем столе... Единственное рабочий тол типа "logon" не принимает потоки от кого попало... |
| Автор: kami 8.8.2014, 17:46 | ||
Вы утверждали, что сервис может отобразить окно на рабочем столе пользователя. StartupInfo относится к запуску отдельного процесса. Даже если не брать это в расчет, сей параметр всего лишь определяет, какой рабочий стол будет использован. При этом рабочий стол http://msdn.microsoft.com/en-us/library/windows/desktop/ms684303(v=vs.85).aspx. Для справки - у каждой Window Station свой набор столов, по умолчанию - default. Да, Window Station можно переключать, но увы - http://msdn.microsoft.com/en-us/library/windows/desktop/ms684339(v=vs.85).aspx. Вы не в состоянии открыть десктоп пользователя. Итого - указание WinSta0\Default приведет к тому, что отдельный процесс будет использовать дефолтный десктоп, принадлежащий сессии родительского процесса, т.е. - сервису. А у сервисов - отдельный, не-интерактивный десктоп. Пример в студию. Что угодно - нарисовать линию, показать окно - любое действие из сервиса в Vista|Win7, воздействующее на рабочий стол пользователя. Выше я дал пруфлинки, почему считаю это невозможным. На всякий случай - подчеркну: непосредственно из сервиса, а не отдельного приложения, запущенного им. |
| Автор: Delvish 8.8.2014, 19:08 | ||
На счет раздела HKCU я не проверял, но вот сеть работает исправно. Или под сетевыми ресурсами имеется ввиду доступ к шарам? В общем, как это описал выше drkot, в моем случае одна программа запускается от имени Системы, ждет входа пользователя, после чего приведенным выше кодом запускает основную программу, которая работает безо всяких проблем. Если же топикстартеру не нужно ждать логина пользователя, то планировщик, как я писал выше, позволяет запускать задачи вне зависимости от регистрации. Ему просто нужно определиться с самой задачей |
| Автор: drkot 8.8.2014, 22:54 |
Во первых Вы правы в своих суждениях. Но Вы движетесь по пути, который не предполагает решения. Конечно можно углубиться в права и привилегии и переключить окно с одной станции на другую, но это не тот путь... Никто не мешает создать процесс под в нужной станции/столе, и выполнить то что нужно, при этом задав процессу права пользователя ... в этом вопросе не могу с Вами согласится... я же говорю скачайте пример с сайта Rouse и не создавайте панику... Функциональный пример для этой задачи в три строчки не поместишь... http://rouse.drkb.ru/winapi.php#servicenotifyer Тотя могли и сами скачать, чай не дети малые. а в чем разница? а... да... Вместо того чтобы пройти в дверь, мы по старинке пытаемся пробить стену головой... ну тут каждый выбирает по себе... извольте... |
| Автор: ZBugz 9.8.2014, 06:48 |
| Так, погодите... У меня уже голова кругом пошла, пока Вас читал, 95% информации не понял И так по порядку.... Есть windows 2008R2 Там есть моя программка, она в атозапуске. Пользователи: Администратор и гость. Когда выключают свет, к примеру, и комп перезагружается, и некому зайти под любым из пользователей, то программа не запускается. Вот мне и надо, что бы ее запустил сервис. Ну как в антивирусе или файрволе... GUI в сервис конечно я не перенесу, там программа большая. Мне старта моей хватит и остлеживание ее на наличие запущенности... Желательно (начитался Ваших диcскусий), мне бы пример, с сервисом, в котором можно указат пользователя и пароль из под которого он запустится и если их не указывать, то что бы по умолчанию он запускался из под LOCALSYSTEM З.Ы. Никаких там RDP или для Sql или использовать планировщик или еще чего либо, мне не надо, чисто локальный пользователь... |
| Автор: drkot 9.8.2014, 17:02 | ||
но если есть желание приобрести мешочек геморроя, то ссылка на пример выше |
| Автор: kami 9.8.2014, 20:48 | ||||||||
Пардон, но этот путь задали Вы. Изначально меня смутило Ваше заявление о возможности доступа к десктопу из сервиса. Еще раз подчеркну - из сервиса, о чем Вы неоднократно (в том числе в ехидных фразах) утверждали. Именно поэтому я и пытался расставить все точки над i - по прежнему ли нельзя (так было, когда пытался заниматься этим вопросом), то ли ситуация поменялась, а я не в курсе.
О том, что есть свет в конце тоннеля - с чувством полного превосходства сказали Вы. Печально, что в конечном итоге это оказалось не так. Я бы с огромной радостью посыпал голову пеплом и пошел перечитывать мануалы.
Углубиться можно. Но это не поможет - WinSta останется в той же сессии, о чем я уже говорил. А зря. Смысл не в упоминании десктопа в lpDesktop, а именно в манипуляциях с hToken. http://msdn.microsoft.com/en-us/library/windows/desktop/ms686744(v=vs.85).aspx
Так именно об этом речь и шла изначально, и проблем с этим по большому счету нет. Пример Rouse я посмотрел практически сразу после его упоминания, но там так же используется запуск отдельного процесса. Ни о каком SetThreadDesktop для потока сервиса речи не идет. Возвращаясь к исходному вопросу: ZBugz, что мешает обойтись не программерскими, а административными методами решения? Например, http://technet.microsoft.com/en-us/sysinternals/bb963905. При включении компьютера сразу будет залогинен пользователь и будет запущено то, что указано в его автозапуске. quod erat demonstrandum
Ну, а если все равно нужен сервис, да и в добавок логин/пароль известны - воспользуйтесь CreateProcessWithLogonW. Вы попробуйте, там нечему не-получаться |
| Автор: kami 9.8.2014, 21:18 | ||
Да никто не переключится. НЕВОЗМОЖНО это. Программа так и останется висеть на десктопе сервисов. Сейчас для подтверждения своего мнения провел несколько экспериментов - да, приложения запускаются через планировщик. Да, они есть в процессах, НО ProcessExplorer говорит, что запущен от имени нужного пользователя... вот только в сесии 0 (LocalSystem) и WindowStations\Service-0x0-24012. Планировщик - не выход. |
| Автор: drkot 9.8.2014, 22:41 |
| kami, у нас как-то диалог глухого с немым получился... ну да ладно, не суть Вы останетесь при своём, и я при своем, так что не о чем спорить... А то, что Вы хотите сделать можно, но это не тривиально и для большинства задач не есть рациональное решение. ню-ню |
| Автор: ZBugz 10.8.2014, 07:15 | ||||
Не, люблю все сам
Вот пример бы |
| Автор: kami 10.8.2014, 14:14 | ||
Честно говоря - даже не знаю, как построить пример, чтобы он не стал непосредственным решением задачи В общем и целом: нужно создать новый проект - сервис, а в OnExecute выполнить единственное мероприятие - CreateProcessWthLogon. А если программа продолжает оставаться в автозагрузке - то LogonUser. Вы попробуйте, а с тем что не получится (хотя я не понимаю, что там может не получиться) - сюда. drkot, все-таки я настоятельно прошу доказательств Вашей точки зрения, раз уж Вы продолжаете настаивать на том, что это возможно.
Какие бы ни были извращения при "стыковке" своего потока с интерактивным рабочим столом - оно в любом случае окупится тем, что не будет необходимости использовать IPC. Механизмы синхронизации "своих" потоков гораздо проще в применении. Пусть это будет нетривиально, пусть с извращениями - главное чтобы было. Повторно прошу: пример, ссылку - что угодно, реализующее взаимодействие с рабочим столом пользователя из потока, принадлежащего сервису. Опять это бездоказательное "я знаю и умею, а вы, серые, продолжайте упорствовать в своем невежестве". Я дождусь подтверждения ваших слов, или это так и останется на уровне ОБС? |
| Автор: drkot 10.8.2014, 15:33 | ||||
Данные извращения сводятся к переписыванию системной области процесса требует отключения защитных механизмов системы. К делфи не имеет никакого отношени. После прикрытия "интерактивных" сервисов копал именно в этом направлении. Выяснилось, что для нормальной работы на произвольной машине добиться не получится. Насколько понимаю делает что-то очень подобное, но ей "разрешено", а другим нет. Какие конкретно права и привилегии имеет эта служба не изучал. Для себя решил, что "интерактивных" сервисов быть не должно и точка. Если сервисом надо управлять, то делается десктопное приложение через которое управляется (настройки, телеметрия). Но никаких диалоговых окон из сервиса быть не должно, никаких ожиданий ответа от пользователя и прочего. Если хочется развлечься, то это Ваше право. Есть еще два варианта: 1) регистрируется COM сервер (или расширение оболочки) и через него открываются окна; 2) запустить сервис в контексте текущего пользователя Проверять не пробовал, это заметки с того времени.
нет, это скорее "чем Вам планировщик не угодил?". ZBugz, лучшее решение то, которое самое простое... |
| Автор: ZBugz 10.8.2014, 19:13 | ||||
А вот , к прмеру, касперский или outpost firewall, они работают даже, когда компьютер ен залогинен. Или бэкапер cobian backup, тот же, там в нем прописываешь под авторизироватся и все, он сам шурует, даже если не залогинишься в windows... Мне как раз как у них надо...
Согласен, поэтому и хочу сам написать, я считаю это самым простым |
| Автор: kami 11.8.2014, 07:26 | ||
Ага. Пока не залогинен - "шурует" сервис. Когда залогинен - сервис запускает GUI процесс под "залогиненным" пользователем, но "шуровать" продолжает все равно сервис. А гуй - всего-навсего представляет собой прослойку между пользователем и сервисом. Эта прослойка показывает информацию от сервиса - пользователю и отправляет в сервис команды, отданные пользователем. Вы уверены, что теперь надо именно это? |
| Автор: ZBugz 11.8.2014, 18:36 | ||
Неверно Хочу как у других... Пока не залогиен, запускается сервис, который стартует мою программу. Как юзер залогинился, программа уже и так запущена, тогда два варианта (не знаю что лучше и как реализовать хотя бы один): 1. Так что ее не трогаем... Но все равно каждые 5 секунд проверяет ее запущенность, елси не запущенная, то запускает ее. Если я закрываю комманду, то посылаю комманду сервису, который выключает таймер проверки запуска программы... 2. Выгружаем программу и срабатывает обычный автозапуск, который уже написан. |
| Автор: Delvish 12.8.2014, 10:26 |
| Раз уж так хочется именно через сервис, то у Rouse_ есть http://rouse.drkb.ru/winapi.php#servicenotifyer взаимодействия сервиса с рабочим столом пользователя |
| Автор: kami 12.8.2014, 11:40 |
Вы мне напоминаете 90+% заказчиков - они все хотят "чтобы было красиво", но вот что означает это "красиво" - никто объяснить не может. И когда пытаешься отдать им решение, начинается "ну, да, это конечно классно, но совсем не то что мне надо" (да, еще достаточно много народа признает только waterfall). Давайте полностью проговорим алгоритм работы. "После загрузки компьютера запускается наша служба, которая..." А дальше всё зависит от первой части. Но я не понимаю, чем плох авто-логон юзера, пусть даже сделанный из своего сервиса. |
| Автор: kami 12.8.2014, 13:24 | ||||||
Update:
Ок, программа стартанула. Но если ручками не залогинить пользователя до запуска приложения - вы не увидите его GUI. Хотя... у меня не было необходимости в использовании CreateProcessWithLogonW, посему - может и "прокатит".
Это - 2 под-задачи - а)получение списка процессов б)запуск своего от имени пользователя. Первая более чем широко описана, решение по второй предлагалось здесь во многих постах, включая пример Rouse, упомянутый drkot и Delvish.
Реализовывать можно по разному, смотря кто будет проверять на второй запуск. В любом случае - потребуется взаимодействие двух приложений. Так чего же вам не хватает, чтобы начать решать эту задачу? |
| Автор: Delvish 12.8.2014, 13:50 |
| Оу, что-то я проглядел что drkot уже давал ссылку на Багеля. Зато я припомнил старую очень похожую тему, которую некогда встречал... kami, ваш же http://forum.vingrad.ru/index.php?showtopic=311445&view=findpost&p=2223868 |
| Автор: ZBugz 13.8.2014, 06:29 | ||||||||||
Ну я просто считаю, что так правильно написать
Мне никаких GUI не надо видить, тем более это невозможно, раз не залогинен
Эта не проблема.
Мне нужен сам код сервиса, где мне подскажут, куда прописать от чьего имени его запустить, при установке и где (в какой процедуре), мне прописать запуск и мониторинг запуска моей програмы. Впринципе это меня и беспокоит, остальное я знаю как написать, ну разве что никогда не писал запуск процесса от имени пользователя, я писал только прорсто запуск http://forum.sources.ru/index.php?showtopic=349249&hl= |
| Автор: kami 13.8.2014, 07:24 | ||
C этим проблем быть не должно - при создании нового проекта всего лишь выбрать Service Application, все остальное Delphi сделает за вас. Оставить по умолчанию.
Например, запуск можно в OnCreate сервиса, а мониторинг... ну бросьте таймер на этот сервис, к примеру. |
| Автор: drkot 13.8.2014, 14:51 |
не стоит использовать это событие для запуска, так как оно возникает всегда, когда исполняется файл. Для организации сервиса можно использовать либо OnStart OnStop либо OnExecute. Единственно нужно не забывать, что при запуске сервиса еще не все работает в системе, и по хорошему нужно бы подождать, пока нужные для работы системы запустятся. если это самостоятельный процесс, то правильнее в виде сервиса. но если эта реализация будет "кривая" то вряд ли такой подход можно считать правильным. |
| Автор: ZBugz 14.8.2014, 06:29 |
| Ну хорошо. Я все посмотрю, выложу тут, что я написал, будем проверять |