4

I'm trying to use SCHTASKS to create a scheduled task on Windows. The parameters include single quotes. If I create my task manually, it works. In the Windows Task Scheduler GUI, the "Details" (within the action tab) show up like this:

powershell (New-Object System.Net.WebClient).DownloadString ('http://mywebserver/myscript.ps1\') | powershell.exe -noprofile -

However, when I enter my SCHTASKS command...

schtasks.exe /Create /TN "My Task" /TR "powershell (New-Object System.Net.WebClient).DownloadString ('http://mywebserver/myscript.ps1\') | powershell.exe -noprofile -" /SC MINUTE /mo 60 /RL HIGHEST

This then appears in the GUI (note the interpretation of a single quote to a double one on the first, but not the second instance:

powershell (New-Object System.Net.WebClient).DownloadString ("http://mywebserver/myscript.ps1\') | powershell.exe -noprofile -

I've tried escaping it etc. (which works fine for double quotes but not for single) but can't seem to figure it out..?!

Many thanks in advance for any suggestions.

BSUK
  • 692
  • 1
  • 12
  • 28
  • The problem will be in the `schtasks.exe` runtime library command argument parsing. There probably isn't any way to do this from the command line. Try using the [task scheduler API](http://msdn.microsoft.com/en-us/library/windows/desktop/aa383607%28v=vs.85%29.aspx) instead. – Harry Johnston Oct 16 '14 at 20:11

6 Answers6

4

I stumbled upon the same problem recently.

I needed to add an action to a task with this command:

 Powershell -NoProfile -ExecutionPolicy Bypass -Command "iex ((New-Object Net.WebClient).DownloadString('https://url/to/script.ps1'))"

It's perfectly possible to create a task with this command manually, but using the schtasks command, it's apparently impossible to render a single quote inside the arguments field of a task (at least not without a backslash in front of it, which makes it unusable).

So after some fiddling, I found a way to specify the arguments without using single quotes:

Powershell -NoProfile -ExecutionPolicy Bypass -Command "iex ((New-Object Net.WebClient).DownloadString(\"https://url/to/script.ps1\"))"

And this also works from the task manager... Yay!

It took some more fiddling, but I got this to work using the schtasks command manually (in a command prompt, not in powershell) like this:

schtasks /Create /TN "My Task Name" /RU SYSTEM /SC DAILY /ST 23:00 /TR "Powershell -NoProfile -ExecutionPolicy Bypass -Command \"iex ((New-Object Net.WebClient).DownloadString(\\\"https://url/to/script.ps1\\\""))\""

Yes, those are tripple backslashes around the url... basically, a quote needs to be escaped by a backslash, and a backslash needs to be escaped by another backslash.

Now on to get this to work from powershell... Some more fiddling later, I came to this result:

schtasks /Create /TN "My Task Name" /RU SYSTEM /SC DAILY /ST 23:00 /TR "Powershell -NoProfile -ExecutionPolicy Bypass -Command \`"iex ((New-Object Net.WebClient).DownloadString(\\\`"https://url/to/script.ps1\\\`"))\`""

Which is basically another layer of escaping: the quotes need to be escaped by a backtick.

My head starts to spin, but I'm glad I tamed the beast :)

fretje
  • 8,322
  • 2
  • 49
  • 61
1

PowerShell uses the unfortunate backtick (`) as the escape char. Backslash has no special meaning. Better yet, little known trick, use --%.

schtasks.exe --% /F /Create /TN "My Task" /TR "powershell (New-Object System.Net.WebClient).DownloadString('http://mywebserver/myscript.ps1') | powershell.exe -noprofile" /SC MINUTE /mo 60 /RL HIGHEST

Which basically means, "Dear PowerShell parser, find schtasks.exe in the path, run it and pass it whatever comes after '--%' EXACTLY as it is."

evilSnobu
  • 24,582
  • 8
  • 41
  • 71
  • Hi, neither of those methods work unfortunately. :( The back tick just gets added as though it were any other character, and the --% method simply errors: "ERROR: Invalid argument/option -'--%'. – BSUK Oct 16 '14 at 12:52
  • You're not running that in PowerShell, are you? You're running it in cmd.exe. My bad then. I'll be back ;) – evilSnobu Oct 16 '14 at 13:10
  • Yup, sorry.. adding the schtask via a batch (for use on a GPO). Thanks for your help. – BSUK Oct 16 '14 at 13:19
  • Why not use New Scheduled Task inside the policy itself? http://technet.microsoft.com/en-us/library/cc725745.aspx – evilSnobu Oct 16 '14 at 13:47
  • because our domain controllers are still stuck in 2003 mode. – BSUK Oct 16 '14 at 14:49
1

Building on the XML approach, if you truly need single quotes in the final task argument, my workaround was to create the task without the arguments needing single quotes, then export the task XML (/query /xml /tn), delete the task (/delete /tn /f), update the XML file with the args and create again (/create /xml). Definitely roundabout but the only way I could get it to work

0

Then i would suggest doing this instead:

schtasks.exe /F /Create /TN "My Task" /SC MINUTE /mo 60 /RL HIGHEST /TR "powershell.exe -ExecutionPolicy Bypass -NoProfile -File \\UNC\to\Script.ps1"

And having all execution inside the .ps1.

Note that you'll come as 'NT AUTHORITY\SYSTEM' to that UNC path, appropriate permissions are necessary.

evilSnobu
  • 24,582
  • 8
  • 41
  • 71
0

The following can get you what you need. But it will run it as a single command rather than a command with args.

schtasks.exe /Create /TN "My Task" /TR ""\""powershell (New-Object System.Net.WebClient).DownloadString ('http://mywebserver/myscript.ps1\') "|" powershell.exe -noprofile -\"" /SC MINUTE /mo 60 /RL HIGHEST
AmitE
  • 884
  • 1
  • 9
  • 13
0

Using the /XML switch of schtasks.exe is another way of working around this issue; depending on your needs you might need to create the xml file on the fly. I simply created the task manually, exported it, adapted the xml file and changed the schtasks line from using /TR to using /XML.

Daniel
  • 321
  • 3
  • 10