Windows ships no redial policy for its VPN client, so a connection that drops at midnight is still down at breakfast. A scheduled task that watches for the disconnect and runs rasdial closes that gap without a third-party client. Whether the task behaves like an operator or like a loop comes down to three details: which events it matches, which credential it can see, and what it does with the result. None of the three is hard, and missing any one of them is what produces a task that dials forever.

Why a timer is the wrong trigger

A timer dials on its own schedule whether or not the tunnel is down. That produces attempts nobody needed, and an attempt during a working session can interrupt it. An event trigger fires only when the connection changes state, which is cheaper and easier to reason about. The event also carries the reason, and the reason is what separates a network failure from a person disconnecting on purpose.

That distinction is the difference between a helpful task and one that fights the user every evening. It is also the part usually missing from recipes that only describe the action.

The event pair, and the one to suppress

The Remote Access Service client writes lifecycle records to the Application log under the RasClient provider. 20226 marks a connection that ended, and 20227 marks an attempt that failed, so either can justify a new dial. Everything else in the task depends on matching those two identifiers exactly. They have been stable for years, which is why recipes built on them still circulate, but a build that renames the provider or the ids makes the query return nothing. Re-run the proof step after each feature update rather than waiting for the task to stop firing.

One termination needs excluding. Error 631 means the port was disconnected by the user, and a redial at that moment fights the person who just switched networks deliberately. Put the exclusion in the trigger filter rather than in the script, so the task never starts at all. It has to apply to one event id only, because an EventData predicate matches solely when the named element exists, and a shared clause would silently drop every event of the other id. Read the element name out of a real record before writing the filter:

Get-WinEvent -LogName Application -MaxEvents 5 -FilterXPath "*[System[Provider[@Name='RasClient'] and EventID=20226]]" | Select-Object -First 1 -ExpandProperty ToXml

The XML shows the exact Data names in that record. ErrorCode is the usual spelling, and a record that uses something else needs that name substituted in the filter below.

<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>

Paste that into the trigger's custom filter, and prove it as a query before it becomes a trigger. The same XPath runs from PowerShell against the live log, which is the cheap way to see what it matches while task history is still uninvolved.

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

A trigger that silently matches nothing looks exactly like a task that runs and fails. Both present as "the automation does not work", and neither says which half is missing. Check the query output first, because it separates the two cases in one step.

The dial fails because nobody is there to type the password

The action runs rasdial with the connection name. When the profile has no cached credential, the dial fails immediately because there is nobody to answer the prompt. That is the most common reason a correctly triggered task does nothing visible, so check it before touching the trigger. Dialling by hand from a command prompt separates a credential problem from a scheduling one.

Save the credential once under the account the task will run as, and make that account part of the design. A task running as SYSTEM cannot read a credential cached by your interactive account, and neither can a task running as somebody else. The name must also match the profile exactly, including any domain prefix in the user field.

rasdial
rasdial "Office VPN"
(Start-Process rasdial -ArgumentList '"Office VPN"' -Wait -PassThru -NoNewWindow).ExitCode

The first command lists the names Windows knows about. The second dials by name using the cached credential, and the third is the form a PowerShell action should use, because it waits and returns a value the task can record.

Read the exit code instead of the window

A task that starts a process without waiting reports success as soon as the process exists. For a dial that can fail a second later, that verdict is worthless. Waiting for the exit code turns the action into a real result. Task history on its own only shows that a process started, never that a tunnel came up.

Log the value with a timestamp on every run. A single failure after an outage is normal, while three failures in a row with the same code point at the credential or the profile rather than at the network. That pattern is what makes the history worth reading at all.

Add a short repetition interval as insurance, and be explicit about how it interacts with an event trigger. A repeat of every minute for five minutes supplies the second attempt when the internet came back with the tunnel, and under Settings, "If the task is already running, then the following rule applies", the task wants Do not start a new instance so that a repeat cannot overlap a dial still in progress. Without that setting, two rasdial processes can race for the same port and the second one fails for no useful reason.

Prove the recovery path

Test both directions deliberately. Disconnect by hand and confirm that no redial happens, then disable the network adapter and confirm that the task fires when the link returns. Those two tests cover the suppression rule and the real failure case, and nothing else does.

Read the task history afterwards rather than the connection icon. The history records when the task ran, which account it used and what the action returned, and that is the evidence needed when the same machine drops again next month.

সম্পৰ্কিত প্ৰবন্ধ