Running PowerShell Scheduled Tasks – a Second Opinion

March 1, 2018


I recently published an article titled Running PowerShell Scripts As a Scheduled Task.  That article was from a reader showing how he ran one of the PowerShell scripts as a scheduled task. After that article was released, another reader, Guy Leech (@guyrleech), sent me a Word document showing how he accomplishes the same task.

What follows are Guy’s words. The only things I have changed are some of what Grammarly thought should be corrected.

Running PowerShell Scheduled Tasks


Running a PowerShell script via a scheduled task directly in PowerShell.exe rather than via a script is straightforward although there are a couple of gotchas although we also have these if we run it indirectly via a batch script.

We specify the full path to powershell.exe as the program/script and then craft the command line to our needs.

Figure 1

Figure 1

Where the command line is something like this:

-ExecutionPolicy Bypass -File "c:\scripts\solve global warming.ps1" -logfile "c:\log\warming.log" –yesreally -verbose

To test the command line works properly, so you can see any syntax or other errors, copy the arguments into the clipboard. Then, from a command prompt (do not, under any circumstances, call this a “DOS prompt”!), paste the arguments in after entering “powershell.exe “and hit enter as this is how the scheduled task will effectively run it.

Quoting Arguments

Any single argument containing spaces will need to be enclosed in quotes and therein can lie our first challenge when we have nested quotes. It’s usually easily rectified but depends on what type of quote marks you need to use since single (‘) and double (“) aren’t always interchangeable because the former means PowerShell won’t evaluate what’s inside the string, e.g., to expand variables.

To pass double quotes to a string, we can escape them thus:

-SomeArgument "This is a string \"In quotes\" argument"

Where the outer quotes aren’t escaped as this merely tells PowerShell to treat the string as a single argument.

If there’s a double quoted string which includes single quotes then nothing special is required, e.g.

-SomeArgument "This is a string 'in quotes' argument"

Also, if we need to pass a single quoted string then that is simply wrapped in double quotes thus:

-SomeArgument "'This is a string \"in quotes\" argument'"

Passing Booleans

The next challenge can be passing $true or $false to parameters because if you put something like this (where you have to say “[CmdletBinding(SupportsShouldProcess=$True,ConfirmImpact=’High’)]” in your script to cause it to prompt before taking potentially destructive actions):


Then you’ll get this error:

Cannot convert 'System.String' to the type 'System.Management.Automation.SwitchParameter' required by parameter 'Confirm'.

There are many ways around this depending on whether the parameter is one you have defined or is a built-in one like –Confirm as in the example above.

  1. Change the type of the parameter to [string] and then define a Boolean where you explicitly convert the string to a Boolean. E.g.
[bool]$mySwitch = [System.Convert]::ToBoolean($yourStringArgument)
  1. Change the type of the parameter to [switch] and then convert it thus:
[bool]$mySwitch = ! $yourSwitchArgument
  1. Change the PowerShell.exe –File argument to –Command although then you can get into more complexity trying to get quotes right since the entire argument list, including the script name, must be quoted.

My preferred workaround for –confim, since we can’t have scheduled tasks prompting for confirmation of things like file deletions as they won’t be visible, is to use a switch type parameter and then simply set the built-in $ConfirmPreference to ‘None’ if that switch parameter has been specified, so is $true. For example:


If( $forceIt )
     $ConfirmPreference = 'None'

Passing Arrays

For reasons I don’t (yet) know, when comma separated strings are passed to PowerShell array arguments, they get passed as a single string containing commas. Fortunately, it is very easy to convert these back to arrays. I use something like this where $recipients is defined as a string array (string[]):

if( $recipients -and $recipients.Count -eq 1 -and $recipients[0].IndexOf(',') -ge 0 )
     $recipients = $recipients[0] -split ','

If All Else Fails

Powershell.exe can take a –EncodedCommand parameter where that is the command line to run and is base64 encoded so you don’t hit the problems described above but it does make changing the command line in the scheduled task a little bit more difficult, but the flip side of that is that it obfuscates the command line thus disguising it from casual observers. It does not protect clear text passwords!

Run the following in PowerShell to encode your command line and put it into the clipboard– notice the use of the “&” character because my script name has spaces in it:

[Convert]::ToBase64String( [System.Text.Encoding]::Unicode.GetBytes( '& "c:\scripts\solve global warming.ps1" -logfile c:\log\warming.log –confirm:$false -subject "Hello" -verbose -recipients one,two' ) )|clip

Note that if we had single straight quotes in this command line, then we would escape them by specifying two, i.e. ” (that is not a single, double quote character!).

Then we paste that into the command line specified in the scheduled task:


[end of Guy’s Word document]

If you have another method for running any of the scripts as a scheduled task, send me an email of how you handle the process and I will create another article using your process.


Webster and Guy

About Carl Webster

Webster is a Sr. Solutions Architect for Choice Solutions, LLC and specializes in Citrix, Active Directory and Technical Documentation. Webster has been working with Citrix products for many years starting with Multi-User OS/2 in 1990.

View all posts by Carl Webster

No comments yet.

Leave a Reply