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?
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