Search code examples
powershellscheduled-tasksquotes

Using PowerShell To Create Scheduled Task With Spaces


I have two script to use as part of an application install. The first script creates a scheduled task to run the second script after the server reboots. That portion of the script is:

$installScript = "$PSScriptRoot\Install.ps1"
schtasks.exe /CREATE /F /TN "Install Application" /RU $taskUser /SC ONLOGON /IT /TR "powershell.exe -ExecutionPolicy Bypass -File $installScript" /RL HIGHEST

This has worked really well for me, but I just discovered a hitch. When $PSScriptRoot has spaces in it, the scheduled task fails to find the Install.ps1 script. I've found if I edit the argument in the scheduled task to include "" around the path, it works without issue. But I'm not sure how to accomplish that. Anyone have a suggestion?


Solution

    • In the command that powershell.exe sees on invocation with -File, the value of $installScript must be enclosed in "..." (double quotes) for script paths that contain spaces (or other PowerShell metacharacters, such as {).

    • Since you're relying on outer "..." quoting in order to expand (interpolate) the value of $installScript, you must therefore escape the embedded " characters you need to enclose $installScript in.

      • `" (or "") must be used for escaping; e.g.:

        • "Nat `"King`" Cole" results in verbatim Nat "King" Cole
      • See the conceptual about_Quoting_Rules help topic.

    • Unfortunately, because you're calling an external program (schtasks.exe), and additional escaping requirement comes into play, due to a long-standing bug:

      • Up to PowerShell 7.2.x, you must manually \-escape " chars. that the target program should (also) see as escaped ones.

      • With selective exceptions on Windows, this problem has been fixed in PowerShell 7.3+.

      • See this answer for more information.

    Therefore, you must combine these two escaping mechanisms in your case, which requires enclosing $installScript in \`" (sic), i.e. \`"$installScript"\`":

    # Note: The \-escaping is no longer needed in PS 7.3+
    $installScript = "$PSScriptRoot\Install.ps1"
    schtasks.exe /CREATE /F /TN "Install Application" /RU $taskUser /SC ONLOGON /IT /TR "powershell.exe -ExecutionPolicy Bypass -File \`"$installScript\`"" /RL HIGHEST