Держите VPN в Windows включённым: запускайте rasdial по событию отключения
RasClient 20226 и 20227 отмечают обрыв; 631 означает, что это сделал человек. Запускайте rasdial по первым двум, сохраните одни учётные данные и читайте код выхода.
Windows не предлагает политику повторного дозвона для своего VPN-клиента, поэтому соединение, оборвавшееся в полночь, к завтраку всё ещё не работает. Плановая задача, которая следит за разрывом и запускает rasdial, закрывает эту брешь без стороннего клиента. Ведёт ли задача себя как оператор или как цикл, зависит от трёх деталей: с какими событиями она совпадает, какие учётные данные она видит и что она делает с результатом. Ни одна из трёх не сложна, и пропуск любой из них — это то, что создаёт задачу, которая звонит вечно.
Почему таймер — неправильный триггер
Таймер звонит по собственному расписанию независимо от того, оборван туннель или нет. Это порождает попытки, которые никому не были нужны, а попытка во время рабочего сеанса может его прервать. Триггер события срабатывает только когда соединение меняет состояние, что дешевле и проще для осмысления. Событие также несёт причину, и именно причина отделяет сбой сети от человека, который отключается намеренно.
Это различие — разница между полезной задачей и той, что воюет с пользователем каждый вечер. Это ещё и та часть, которой обычно не хватает в рецептах, описывающих только действие.
Пара событий и то, которое нужно подавить
Клиент службы удалённого доступа пишет записи жизненного цикла в журнал Application под поставщиком RasClient. 20226 отмечает завершённое соединение, а 20227 — неудачную попытку, поэтому любое из них может оправдать новый дозвон. Всё остальное в задаче зависит от точного совпадения этих двух идентификаторов. Они стабильны годами, поэтому рецепты, построенные на них, до сих пор ходят, но сборка, которая переименовывает поставщика или идентификаторы, приводит к тому, что запрос ничего не возвращает. Повторяйте шаг доказательства после каждого обновления функции, вместо того чтобы ждать, пока задача перестанет срабатывать.
Одно завершение нужно исключить. Ошибка 631 означает, что пользователь отключил порт, и повторный дозвон в этот момент воюет с человеком, который только что намеренно сменил сеть. Поместите исключение в фильтр триггера, а не в скрипт, чтобы задача вообще не запускалась. Оно должно применяться только к одному идентификатору события, потому что предикат EventData совпадает лишь тогда, когда названный элемент существует, а общее условие молча отбросило бы каждое событие другого идентификатора. Прочитайте имя элемента из реальной записи, прежде чем писать фильтр:
Get-WinEvent -LogName Application -MaxEvents 5 -FilterXPath "*[System[Provider[@Name='RasClient'] and EventID=20226]]" | Select-Object -First 1 -ExpandProperty ToXml
XML показывает точные имена Data в этой записи. ErrorCode — обычное написание, а запись, использующая что-то другое, требует подстановки этого имени в фильтре ниже.
<QueryList><Query Id="0" Path="Application"><Select Path="Application">*[System[Provider[@Name='RasClient'] and (EventID=20226 or EventID=20227)]] and (EventData[Data[@Name='ErrorCode'] != '631'] or System[EventID=20227])</Select></Query></QueryList>
Вставьте это в пользовательский фильтр триггера и докажите как запрос, прежде чем он станет триггером. Тот же XPath выполняется из PowerShell против живого журнала, что является дешёвым способом увидеть, с чем он совпадает, пока история задач ещё не задействована.
Get-WinEvent -LogName Application -MaxEvents 40 -FilterXPath "*[System[Provider[@Name='RasClient'] and (EventID=20226 or EventID=20227)]] and (EventData[Data[@Name='ErrorCode'] != '631'] or System[EventID=20227])" | Select-Object TimeCreated,Id,Message
Триггер, который молча ни с чем не совпадает, выглядит точно как задача, которая выполняется и падает. Оба выглядят как «автоматизация не работает», и ни один не говорит, какой половины не хватает. Сначала проверьте вывод запроса, потому что он разделяет два случая за один шаг.
Дозвон не удаётся, потому что некому ввести пароль
Действие запускает rasdial с именем соединения. Когда в профиле нет кэшированных учётных данных, дозвон сразу не удаётся, потому что некому ответить на запрос. Это самая частая причина, по которой правильно запущенная задача не делает ничего видимого, поэтому проверьте это, прежде чем трогать триггер. Дозвон вручную из командной строки отделяет проблему учётных данных от проблемы расписания.
Сохраните учётные данные один раз под той учётной записью, от имени которой будет работать задача, и сделайте эту запись частью проекта. Задача, работающая как SYSTEM, не может прочитать учётные данные, кэшированные вашей интерактивной записью, и задача, работающая от имени кого-то другого, тоже не может. Имя также должно точно совпадать с профилем, включая любой префикс домена в поле пользователя.
rasdial
rasdial "Office VPN"
(Start-Process rasdial -ArgumentList '"Office VPN"' -Wait -PassThru -NoNewWindow).ExitCode
Первая команда перечисляет имена, известные Windows. Вторая звонит по имени, используя кэшированные учётные данные, а третья — это форма, которую должно использовать действие PowerShell, потому что она ждёт и возвращает значение, которое задача может записать.
Читайте код выхода, а не окно
Задача, запускающая процесс без ожидания, сообщает об успехе, как только процесс существует. Для дозвона, который может отказать через секунду, этот вердикт ничего не стоит. Ожидание кода выхода превращает действие в настоящий результат. История задач сама по себе показывает лишь то, что процесс запустился, и никогда — что туннель поднялся.
Записывайте значение с отметкой времени при каждом запуске. Единичный сбой после сбоя питания — это нормально, а три сбоя подряд с одним и тем же кодом указывают на учётные данные или профиль, а не на сеть. Именно этот образец делает историю достойной чтения.
Добавьте короткий интервал повторения как страховку и чётко скажите, как он взаимодействует с триггером события. Повторение каждую минуту в течение пяти минут даёт вторую попытку, когда интернет вернулся вместе с туннелем, а в разделе «Параметры», «Если задача уже выполняется, применяется следующее правило», задача хочет «Не запускать новый экземпляр», чтобы повторение не перекрывало ещё идущий дозвон. Без этой настройки два процесса rasdial могут соревноваться за один порт, и второй терпит неудачу без полезной причины.
Докажите путь восстановления
Проверьте оба направления намеренно. Отключитесь вручную и убедитесь, что повторного дозвона не происходит, затем отключите сетевой адаптер и убедитесь, что задача срабатывает, когда связь возвращается. Эти две проверки покрывают правило подавления и реальный случай сбоя, и больше ничего этого не делает.
Затем читайте историю задач, а не значок подключения. История фиксирует, когда задача выполнялась, какую учётную запись использовала и что вернуло действие, и это и есть доказательство, нужное, когда та же машина снова оборвётся в следующем месяце.