3

The situation

In our organisation I made a GPO that creates a scheduled task. This task triggers at logon of two user accounts.

It executes a powershell script that changes the DNS servers for the network connection. (To block some websites for these users, using dnsmasq. I know this is not a bulletproof solution, but its good enough.)

The action for the scheduled task is this command:

C:\Windows\System32\WindowsPowerShell\v1.0\Powershell.exe

And these are the parameters:

-ExecutionPolicy Bypass –NoProfile –Command "& {C:\ProgramData\ORGNAME\scripts\SetDNS.ps1}" > C:\ProgramData\ORGNAME\scripts\SetDNS.log

As you can see, the output gets sent to a log file.

This is the content of the script:

$wmi = get-wmiobject Win32_NetworkAdapterConfiguration -filter "ipenabled = 'true'"
foreach($adapter in $wmi)
{
    if($adapter.description -NotLike "*VMware*")
    {
        $adapter.SetDNSServerSearchOrder("XXX.XXX.XXX.XXX")
    }
}

invoke-expression -command "c:\windows\system32\ipconfig /flushdns"

The problem

The problem is that this works fine, approximately 9 out of 10 times. When it doesn't work, the task scheduler still reports exit code 0, but it seems the script does not even begin to execute because, nothing happens and the log file is not created.

Some extra info

  • The task runs under the SYSTEM account
  • It runs with highest privilleges
  • When the task is ran on demand it works fine
  • All computers run Windows 7 enterprise (x64)

Some things i've tried

  • I thought maybe the task scheduler was triggering the script too fast and some things might not yet have initialized so i tried setting a 30s delay.

  • Re-running the task every 5 minutes for 15 minutes.

  • Restarting the task when it fails, this obviously doesn't work, since powershell.exe seems to return error code 0.

Omnomnomnom
  • 659
  • 3
  • 10
  • 22

2 Answers2

8

I think the exit code task scheduler is reporting is for running powershell.exe not your script.

Try changing it to this:

-ExecutionPolicy Bypass –NoProfile –Command "& {C:\ProgramData\ORGNAME\scripts\SetDNS.ps1; exit $LastExitCode}" > C:\ProgramData\ORGNAME\scripts\SetDNS.log

$LastExitCode has the exit code of the your script, you have to bubble it up one level to the task scheduler.

It would also be a good idea to add some error handling to your script and use Exit statements to set the actual exit codes.

Peter Hahndorf
  • 14,058
  • 3
  • 41
  • 58
  • This seems like a logical explenation. I've added error handling and $LastExitCode to the scheduled task action. It works on a test machine. At least the task now finishes with a proper exit code when something went wrong and "retry on fail" will work. We are doing a larger test at the moment. Thanks a lot so far! – Omnomnomnom Jun 09 '16 at 13:06
  • I had to use this technique to get the result of the Exit statements in my PowerShell script. It's as though the -ExecutionPolicy Cmdlet eats the results otherwise. – Mike Apr 29 '21 at 13:19
1

Remove the -Command from your script parameters and instead use -File . Command is meant to be used when you are entering powershell commands but you have a script file instead.

Details here

uSlackr
  • 6,412
  • 21
  • 37
  • This saved me today. When i use `-command` Errors thrown in a imported Exchange session were not thrown, only when started via Scheduler. – fbehrens Feb 23 '17 at 10:46
  • 3
    The reason that he suggested using -Command is because he needs a second command to return the exit code returned by the script file. Since -File will not result in the exit code being propagated, it doesn't satisfy OP's scenario. – bwerks Apr 20 '17 at 19:17