Я балуюсь службами Windows.
Из того, что я прочитал, и из описанных мной руководств (один пример) я вижу, что вся работа должна выполняться с помощью метода службы OnStart
.
Насколько я понимаю (из единственных руководств, которые мне удалось найти, которые были полностью базовыми) после того, как метод OnStart
возвращает, служба ничего не может сделать, если вы каким-то образом не настроили ее в методе.
Я видел использование таймеров в указанном методе для запуска событий каждые X секунд, но я ищу для обнаружения изменений фокуса окна (когда программа пытается вывести свое окно на передний план). Решение в ответе это отлично работает, когда я пробую его в консольном приложении, но хочу использовать его в своей службе.
Однако простая регистрация обработчика событий в методе OnStart
не работает - он не запускается и не имеет никакого эффекта. Я попытался установить таймер только для того, чтобы метод OnStart
работал, но это тоже не помогло - таймер работал и выполнял работу каждый тик, но обработчик событий никогда не срабатывал (я ставил File.AppendText
для каждого тика таймера и каждый раз обработчик запускается, но в текстовом файле, который я использовал в качестве элемента управления, были добавлены только тики таймера).
Наконец, я попытался запустить Task
(используя Task.Run
для создания нового потока), который запускал бесконечный цикл отдельным методом от OnStart
, но из-за этого служба просто зависала по мере того, как она продолжалась и продолжалась.
Код:
protected override void OnStart(string[] args)
{
File.WriteAllText("file.txt", "START");
eventLog.WriteEntry("Entered OnStart method.");
// Update the service state to "Start Pending".
ServiceStatus serviceStatus = new ServiceStatus
{
dwCurrentState = ServiceState.SERVICE_START_PENDING,
dwWaitHint = 100000
};
SetServiceStatus(this.ServiceHandle, ref serviceStatus);
eventLog.WriteEntry("Start Pending.", EventLogEntryType.Information);
// Update the service state to "Running".
serviceStatus.dwCurrentState = ServiceState.SERVICE_RUNNING;
SetServiceStatus(this.ServiceHandle, ref serviceStatus);
eventLog.WriteEntry("Running.", EventLogEntryType.Information);
Task.Run(KeepBusy());
}
private static Action KeepBusy()
{
Automation.AddAutomationFocusChangedEventHandler(OnFocusChangedHandler);
while (true)
{
Thread.Sleep(1000);
}
}
Короче говоря, если я правильно понимаю, что сервисы могут выполнять работу только в методе OnStart
, мне противно, насколько это глупо, и я не могу понять, как сделать сервис «слушателя».
@KBO, спасибо! Я думал, что сделал именно это с помощью Task.Run
? Разрешите немного отредактировать вопрос ...
Фактически, вы должны делать как можно меньше в OnStart. Он должен вернуться как можно быстрее. В большинстве случаев вам просто нужно запустить какой-то фоновый поток и, возможно, выполнить некоторую настройку, и все. Все остальное должно обрабатываться в этом фоновом потоке. Без кода невозможно предоставить полезную помощь в том, как исправить ваш код. Так что было бы здорово, если бы вы могли предоставить минимальный воспроизводимый пример
Служба работает в изолированном сеансе (то есть со своим собственным рабочим столом) и принципиально не должна взаимодействовать с другими пользователями (то есть вашими) рабочими столами. Похоже, что все, что вы делаете, лучше подходит для приложения с автозапуском для каждого пользователя.
@Fildor, я знаю, извините, я просто подумал, раз это более принципиальный вопрос и у меня нет рабочего кода, лучше бы я обошелся без него. Постараюсь завтра добавить.
@AlexK., Да, если вы так говорите, я бы отказался от проекта и повторил попытку с приложением.
В методе
OnStart
вы можете создать фоновый поток, который выполняет необходимую работу, возможно, в цикле. Это широко используемый подход. Интерактивные сервисы могут быть опасными, см .: docs.microsoft.com/en-us/windows/desktop/services/…