How to troubleshoot PowerShell scripts not running under a scheduled task

Situation: you have written a PowerShell script that runs fine when you launch it from PowerShell directly, but fails to start or run when you try to plug it into a schedule task.

What went wrong? This post is an outline of common reasons that your script fails to run in a scheduled task. Always check the basics first, even if you think you have it correct. Run through this list and check out the additional debugging steps at the bottom if you are still stuck.

Check User Authentication

  • If you specified a user account for the run-as context, did you provide the correct username and password?

Check User Authorization

  • If using a built-in account (local system, network service, etc) for the run-as context:
  • If using a user account for the run-as context:
    • Is the user authorized to login to the system? Local admins group, etc?
    • Does the user have NT rights to logon as a batch job?
    • Do you require the script to run elevated and you forgot to check the “Run with highest privileges” box?
    • If it used to run correctly but now fails- did the account or password expire?
  • Does the run-as context account have authorization to run PowerShell scripts?
    • Hint: re-check the execution policy for the system and that account.
    • You may need to pass the -ExecutionPolicy argument in the task arguments.
  • Is the run-as context account trying to access network resources and doesn’t have rights to do so?

Check Task Action Arguments: “Program/Script”

  • Normally this value is just: PowerShell.exe
    • Did you check for typos here?
    • Did you accidentally place additional arguments besides the program name?

Check Task Action Arguments: “Add Arguments”

  • The simplest way to launch a script is to just specify the file parameter followed by the script location.
    • Example: -File “C:\scripts\myscript.ps1”
  • Did you check to ensure that exact file on disk exists?
  • Did you check to ensure that the run-as context has permission to read/execute the script file?
  • Does your script path have spaces in it, and you forgot to wrap the path in quotes?
  • Did you wrap you script path in single quote characters, instead of double quotes?
  • Did you pass additional script arguments and mess up the quoting?

Check Task Action Arguments: “Start In”

  • Did you correctly set (or not set) this path value?
    • The start location for PowerShell.exe under the scheduled task user’s context may not be the same as your own development path.
    • If your script references relative paths, then do these paths now break if the script is executed under a different path?

Check the run-as context user profile

  • When starting PowerShell.exe, by default it loads the calling user’s Windows user profile – unless the -NoProfile argument has been passed in.
  • Why does that matter?
    • If the run-as user has never “logged on” to the system before, then no user profile will be present on disk.
      • If you then try to launch PowerShell.exe as that user without specifying the -NoProfile argument, it will fail to start.
    • So ensure that you pass in the -NoProfile argument OR that the run-as context user has logged onto the system at least one time.

Check for module loading problems

  • Does your script load any modules?
    • Are those modules installed on this system?
    • Are those modules installed in the correct scope? (Local user, vs All users scope)
    • Are those modules installed as the correct version (outdated)?
    • Are the modules present, but fail to load? See the error handling section below.

Check for interactive launched items

  • PowerShell scripts executed under a scheduled task will launch with Batch logon, not an interactive logon type.
    • Does your script mistakenly launch any interactive items?
      • For example: Login-AzureRMAccount loads an interactive prompt.
    • Does the script mistakenly launch any commands that would trigger a confirmation warning? Ensure you pass -Force switches when required.

Check for 32-bit vs 64-bit conflicts

  • PowerShell actually comes in 32-bit and 64-bit flavors.
    • Are you launching the correct version for your script?
    • Does your script rely on specific 32-bit or 64-bit actions/activity? For example the Registry is a common one.
    • Does your script rely on a PowerShell module that is only supported in one architecture?

Check Windows PowerShell versions

  • Did you write the script for PowerShell 5.0, but the system it runs on only supports PowerShell 3.0? Check that the cmdlets and syntax you used are supported on the system running the task.
  • Did you write the script on PowerShell Core, and trying to run it on a system with Windows PowerShell? Check your compatibility.

Help, it still doesn’t work!

Here are some helpful techniques to debug errors that happen inside the script:

  • Add some detailed logging.
    • Add logging messages inside your script, to log to the Windows Event log as a custom source, or even simpler- just Out-File to write stuff straight to a text file for debugging statements.
    • Sprinkle trace logging messages before/after key sections that you think might be breaking down. This can help identify where in the script that things stop working.
  • Add some error handling.
    • Set the -ErrorAction parameter on cmdlets to ‘Stop’, and/or set the $ErrorActionPreference setting to ‘Stop’, to allow errors to crash the script.
    • Add try/catch blocks to log the specific errors you are getting, via the logging you setup above.
    • This is critical- as the script may be hitting non-terminating errors and continuing through execution. Without logging and excepting handling, you are in the dark here.
  • Add your own exit codes.
    • If your script fails, having it fail with a specific non-zero exit code is helpful from the point of the task scheduler, so it knows things failed.
    • The worst thing to do is have your script exit with success (0), but really be failed.
  • Simplify the script:
    • Start by temporarily removing all of the script code in your file.
    • Slowly add back small sections, piece-by-piece, and run the partial script under the scheduled task.
    • First section works? Great, add the next section, and repeat until it breaks.
    • Same procedure applies for a complicated set of arguments passed into the script via the task scheduler. Start small, then add more.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s