使用schtasks.exe 创建的计划任务在工作目录设置为$env:windir\system32[1] 的情况下执行,因此除非您的脚本恰好位于..\Execute\execute.ps1相对于那里,您的命令将无法按预期工作。
如果您不想将脚本路径直接硬编码到命令中,动态构造命令,将相对路径解析为绝对 分配给$Argument时的一个:
$Argument = 'powershell.exe -file \"{0}\"' -f (Convert-Path ..\Execute\execute.ps1)
注意 - 不幸的是 - 需要将嵌入的 " 转义为 \",这是一个长期存在的错误,为了向后兼容而尚未修复 - 有关背景,请参阅 this GitHub docs issue。
Convert-Path 将相对路径解析为绝对路径。
请注意,相对路径必须引用现有文件(或目录)。
同样,相对路径内部你的脚本也将相对于$env:windir\system32;要使它们相对于脚本的目录,首先通过在脚本开始处执行Set-Location $PSScriptRoot 切换到脚本的目录。
可选阅读:如何引用从计划任务运行的命令:
注意:几乎相同的规则适用于从 Windows 运行对话框运行命令(按 WinKey+R),其中 您可以使用 test-drive 一个命令(传递给 schtasks /tr 的命令,没有外部引用,而不是整个 schtasks 命令行) - 但请注意工作目录将是用户的主目录,并且您将无法使用 '...'-引用 PowerShell CLI 的 -File 参数 - 见下文):
以上内容适用于命令,因为它们必须结束在计划任务中定义,正如您在任务计划程序 (taskschd.msc) 中以交互方式查看或定义它们一样。
另外,用于创建计划任务从命令行/PowerShell 脚本/批处理文件:
(如果命令只包含一个不需要转义的单个单词,例如不包含空格的可执行文件的路径或特殊字符,不传递任何参数。)
调用schtasks.exe[2]时,将/tr参数作为一个整体引用如下:
PowerShell 示例:
# Create sample script test.ps1 in the current dir. that
# echoes its arguments and then waits for a keypress.
'"Hi, $Args."; Read-Host "Press ENTER to exit"' > test.ps1
# Find the start of the next calendar minute.
$nextFullMinute = ([datetime]::Now.AddMinutes(1).TimeOfDay.ToString('hh\:mm'))
# -File example:
# Invoke test.ps1 and pass it 'foo' as an argument.
# Note the escaped embedded "..." quoting around the script path
# and that with -File you can only pass literal arguments at
# invocation time).
schtasks.exe /create /f /tn test1 /sc once /st $nextFullMinute `
/tr "powershell -File \`"$PWD/test.ps1\`" foo" #`# (dummy comment to fix broken syntax highlighting)
# -Command example:
# Invoke test.ps1 and pass it $env:USERNAME as an argument.
# Note the '...' around the script path and the need to invoke it with
# &, as well as the ` before $env:USERNAME to prevent its premature expansion.
schtasks.exe /create /f /tn test2 /sc once /st $nextFullMinute `
/tr "powershell -Command & '$PWD/test.ps1' `$env:USERNAME"
"Tasks will execute at ${nextFullMinute}:00"
[1] 请注意,任务计划程序 GUI 允许您配置工作目录,但此功能无法通过 schtasks.exe 实用程序使用。
[2] 这同样适用于传递给 New-ScheduledTaskAction PowerShell cmdlet 的 -Argument 参数的值,但请注意,可执行文件名称/路径在此处通过 -Execute 参数单独指定。
相比之下,用于创建计划 PowerShell 作业 的 Register-ScheduledJob cmdlet 接受 脚本块 作为要运行的命令,这消除了引用问题。