在Windows中使用schtasks命令指定“start-in”目录

24

我知道这个问题已经在以下线程中被“回答”了:Specifying the running directory for Scheduled Tasks using schtasks.exe

然而,我仍然难以理解答案,也无法确定针对我的情况结果会是什么样子。

我的schtasks命令如下:

Schtasks /Create /TR "C:\Program Files\Java\jre6\bin\javaw.exe main.MoveFile input.txt" /SC WEEKLY /TN mytask

我想要指定“C:\My Library”文件夹作为启动目录。在tr部分之前加上"\"可以填充开始目录为"C:\Program Files\Java\jre6\bin"。

我尝试了很多方法,但似乎一直无法使其工作。

9个回答

16

更新:请注意,从Powershell v3开始(但仅限于Windows 2012及以上版本!),有一种新的API,我认为更加吸引人:

$taskPath = "\MyTasksFolder\"
$name = 'MyTask'
$runAt = '5:00 AM'
$exe = 'my.exe'
$params = 'command line arguments'
$location = "C:\Path\To\MyTask"

Unregister-ScheduledTask -TaskName $name -TaskPath $taskPath -Confirm:$false -ErrorAction:SilentlyContinue  

$action = New-ScheduledTaskAction –Execute "$location\$exe" -Argument "$params" -WorkingDirectory $location
$trigger = New-ScheduledTaskTrigger -Daily -At $runAt
Register-ScheduledTask –TaskName $name -TaskPath $taskPath -Action $action –Trigger $trigger –User 'someuser' -Password 'somepassword' | Out-Null

Amal使用/v1开关的解决方案很好,但不允许在自定义文件夹中创建任务(即无法创建"MyCompany\MyTask",一切都会结束在根文件夹中),因此我最终采用下面描述的PowerShell脚本。

用法:

CreateScheduledTask -computer:"hostname-or-ip" `
                    -taskName:"MyFolder\MyTask" `
                    -command:"foo.exe" `
                    -arguments:"/some:args /here" `
                    -workingFolder:"C:\path\to\the\folder" `
                    -startTime:"21:00" `
                    -enable:"false" `
                    -runAs:"DOMAIN\user" `
                    -runAsPassword:"p@$$w0rd"

(Note, enable 必须小写 - 对于布尔值,您需要使用 $value.ToString().ToLower())
实现:
该函数使用 XML 任务定义和 "Schedule.Service" COM 对象。
#####################################################
#
#  Creates a Windows scheduled task triggered DAILY.
#  Assumes TODAY start date, puts "run-as" user as task author.
#
#####################################################
function CreateScheduledTask($computer, $taskName, $command, $arguments, $workingFolder, $startTime, $enable, $runAs, $runAsPassword)
{    
    $xmlTemplate = "<?xml version='1.0' encoding='UTF-16'?>
        <Task version='1.2' xmlns='http://schemas.microsoft.com/windows/2004/02/mit/task'>
          <RegistrationInfo>
            <Date>{0}</Date>
            <Author>{1}</Author>
          </RegistrationInfo>
          <Triggers>
            <CalendarTrigger>
              <StartBoundary>{2}</StartBoundary>
              <Enabled>true</Enabled>
              <ScheduleByDay>
                <DaysInterval>1</DaysInterval>
              </ScheduleByDay>
            </CalendarTrigger>
          </Triggers>
          <Principals>
            <Principal id='Author'>
              <UserId>{1}</UserId>
              <LogonType>Password</LogonType>
              <RunLevel>LeastPrivilege</RunLevel>
            </Principal>
          </Principals>
          <Settings>
            <IdleSettings>
              <Duration>PT10M</Duration>
              <WaitTimeout>PT1H</WaitTimeout>
              <StopOnIdleEnd>true</StopOnIdleEnd>
              <RestartOnIdle>false</RestartOnIdle>
            </IdleSettings>
            <MultipleInstancesPolicy>IgnoreNew</MultipleInstancesPolicy>
            <DisallowStartIfOnBatteries>true</DisallowStartIfOnBatteries>
            <StopIfGoingOnBatteries>true</StopIfGoingOnBatteries>
            <AllowHardTerminate>true</AllowHardTerminate>
            <StartWhenAvailable>false</StartWhenAvailable>
            <RunOnlyIfNetworkAvailable>false</RunOnlyIfNetworkAvailable>
            <AllowStartOnDemand>true</AllowStartOnDemand>
            <Enabled>{3}</Enabled>
            <Hidden>false</Hidden>
            <RunOnlyIfIdle>false</RunOnlyIfIdle>
            <WakeToRun>false</WakeToRun>
            <ExecutionTimeLimit>P3D</ExecutionTimeLimit>
            <Priority>7</Priority>
          </Settings>
          <Actions Context='Author'>
            <Exec>
              <Command>{4}</Command>
              <Arguments>{5}</Arguments>
              <WorkingDirectory>{6}</WorkingDirectory>
            </Exec>
          </Actions>
        </Task>"
    $registrationDateTime = [DateTime]::Now.ToString("yyyy-MM-dd") + "T" + [DateTime]::Now.ToString("HH:mm:ss")
    $startDateTime = [DateTime]::Now.ToString("yyyy-MM-dd") + "T" + $startTime + ":00"
    $xml = $xmlTemplate -f $registrationDateTime, $runAs, $startDateTime, $enable, $command, $arguments, $workingFolder

    $sch = new-object -ComObject("Schedule.Service")
    $sch.Connect($computer)
    $task = $sch.NewTask($null)
    $task.XmlText = $xml

    $createOrUpdateFlag = 6
    $sch.GetFolder("\").RegisterTaskDefinition($taskName, $task, $createOrUpdateFlag, $runAs, $runAsPassword, $null, $null) | out-null 
}

2
不幸的是,这仅适用于 Windows 2012 及更高版本的 Powershell 3。即使使用 Powershell 3,Windows 2008R2 也没有此功能。 - Brain2000
好的,已更新答案。 - andreister
XML似乎是一个不错的选择,至少如果你想编写一个可以在不同服务器上使用的脚本,特别是在Windows Server 2012之前。 - David Keaveny

16
如果其他方法都失败了,您可以重定向到一个批处理文件,该文件设置自己的CD,然后调用您的程序。
例如:
Schtasks /Create /TR "C:\example\batch.bat" /SC WEEKLY /TN mytask

作为 schtask,并且

cd "%temp%\"
"C:\Program Files\Java\jre6\bin\javaw.exe main.MoveFile input.txt"

将路径写为"C:\example\batch.bat"。这样可以保持当前目录为批处理文件中更改的任何目录,并使所有引用相对于该目录。


1
这是最佳解决方案,应该得到点赞。与其他解决方案不同,它不需要Windows 2012或XML解决方案,并且不会在Windows 2008 R2上出现问题。 - twasbrillig
1
谢谢你提醒我可以直接在/TR中指定.bat文件,无需调用cmd.exe等。 - BobHy
这个解决方案很好,我用过它,但是它不允许我安排第二个任务来使用taskkill /t杀死win32控制台应用程序,如果我不通过.bat文件启动,则可以实现。唯一的方法是使用taskkill /f来终止此类应用程序,这将在强制终止之前不允许程序清理。 - Micka
你应该使用 cd /d "x:\path\to\dir" 因为在更改驱动器字母时,没有 /d,cd 将无法工作 - Michi

14

不确定你所用的Windows版本,但从阅读其他问题来看,似乎Vista / Server 2008上的schtasks并没有提供一个命令选项,允许您直接指定“启动时”目录。人们提供的解决方案是:

  1. 使用/v1标志创建与XP / 2003兼容的任务,在这种情况下,“启动时”目录会自动设置。不确定它设置为什么,但我怀疑它可能是与您的任务可执行文件相同的目录,这对您没用。
  2. 使用XML文件(使用/XML选项)创建您的任务,XML文件允许您指定“启动时”目录。抱歉,我不知道这个XML文件的语法/结构。
  3. 改用任务计划程序UI创建您的任务。

好的解决方案,但似乎不允许带文件夹的任务名称——即您无法使用/v1开关创建"MyCompany\MyTask"(但在没有开关的情况下可以工作)。 - andreister
/V1标志有效,但您需要确保/TR路径在路径中使用反斜杠。当我在路径中使用正斜杠时,任务无法成功运行。 - panofish
2
在命令中,“/v1”标志放在哪里?它需要任何参数吗? - HattrickNZ

3

正如你所指出的,使用/TR参数中的额外引号技巧只允许你使用与可执行文件位于同一目录中的目录。如果你想指定不同的工作目录,应该使用/XML选项并指定一个列出工作目录的XML文件。命令应该类似于这样:

SchTasks /Create /TN "Foo" /XML task.xml

XML文件可能长这样:
<?xml version="1.0" ?>
<Task xmlns="http://schemas.microsoft.com/windows/2004/02/mit/task">
    <RegistrationInfo>
        <Date>2006-05-02T13:21:17</Date>
        <Author>AuthorName</Author>
        <Version>1.0.0</Version>
        <Description>Call MoveFile</Description>
    </RegistrationInfo>
    <Triggers>
        <CalendarTrigger>
            <StartBoundary>2011-11-02T00:00:00</StartBoundary>
            <ScheduleByDay>
                <DaysInterval>1</DaysInterval>
            </ScheduleByDay>
        </CalendarTrigger>
    </Triggers>
    <Principals>
        <Principal>
            <UserId>Administrator</UserId>
            <LogonType>InteractiveToken</LogonType>
        </Principal>
    </Principals>
    <Settings>
        <Enabled>true</Enabled>
        <AllowStartOnDemand>true</AllowStartOnDemand>
        <AllowHardTerminate>true</AllowHardTerminate>
    </Settings>
    <Actions>
        <Exec>
            <Command>C:\Program Files\Java\jre6\bin\javaw.exe</Command>
            <Arguments>main.MoveFile input.txt</Arguments>
            <WorkingDirectory>C:\My Library</WorkingDirectory>
        </Exec>
    </Actions>
</Task>

这里有关于XML模式的更多信息:http://msdn.microsoft.com/en-us/library/windows/desktop/aa383609(v=VS.85).aspx


2

需求

安排一个从指定目录运行的任务。如果我们将此目录称为c:\x,则无论何时执行pwd命令,它都将打印c:\x。从那里到每个路径都是相对于该目录的。

另一个例子:运行java -jar myapp.jar将执行位于c:\x\myapp.jarJAR文件。

问题

使用schtasks /create命令设置该特定参数是不可能的。

解决方法

有点麻烦(就像太多步骤一样):

  1. 使用schtasks /create命令尽可能具体地创建任务。尝试将每个参数设置为所需值:开始时间、重复、持续时间等...

    在这种情况下,/tn参数是强制性的,因此请设置它:\tn mytask

  2. 使用schtasks /query /tn mytask /xml > mytask.xml将新创建的任务导出为XML。

  3. 在您喜欢的编辑器中打开mytasks.xml。您应该看到类似于此的内容(我隐藏了不感兴趣的部分):


最初的回答:需要安排一个从指定目录运行的任务,但使用命令schtasks /create无法设置该特定参数。解决方法是先尽可能具体地使用schtasks /create命令创建任务,并导出任务为XML文件,然后在编辑器中打开并修改XML文件以满足需求。
<?xml version="1.0" encoding="UTF-16"?>

<Task version="1.2" xmlns="http://schemas.microsoft.com/windows/2004/02/mit/task">

 <RegistrationInfo>...
 </RegistrationInfo>

 <Triggers>...
 </Triggers>

 <Settings>...
 </Settings>

 <Actions Context="Author">

   <Exec>

     <Command>java</Command>

     <Arguments>-jar c:\x\myapp.jar</Arguments>

   </Exec>

 </Actions>

 <Principals>...
 </Principals>

</Task>

<Exec>部分中,在<Argument>字段下方引入一个新字段:
<WorkingDirectory>c:\x\</WorkingDirectory>
保存文件。 此字段在xml模式定义中定义,链接如下:https://learn.microsoft.com/en-us/windows/desktop/taskschd/task-scheduler-schema
  1. 删除先前创建的任务(以便使用修改后的xml重新创建):schtasks /delete /tn mytask

  2. 使用/xml参数重新创建任务:schtasks \tn mytask \xml mytask.xml

仅为了检查是否有效

使用schtasks /run /tn mytask执行它。


注:Original Answer翻译成“最初的回答”。

2

请尝试

cd /d "C:\Program Files\Java\jre6\bin" & schtasks /create /tr "C:\Program Files\Java\jre6\bin\javaw.exe main.MoveFile input.txt" /sc WEEKLY /tn mytask

切换工作目录,然后运行schtasks。


1
这种方法适用于Windows Server 2008,但不适用于Windows Server 2008 R2。:( - Yuh-Rong Leu
该方法不适用于Windows 8.1和Windows 2008 R2标准版。 - Marcel Piquet

0

唯一的方法是使用XML文件,使用以下命令:schtasks /Create /XML C:\file.xml /TN TaskName /RU domain\username /RP password

示例XML文件,每天在23:00运行,C:\taskfolder将设置运行目录:

<?xml version="1.0" encoding="UTF-16"?>
<Task version="1.2" xmlns="http://schemas.microsoft.com/windows/2004/02/mit/task">
  <RegistrationInfo>
    <Date>2016-07-13T07:56:56</Date>
    <Author>Administrator</Author>
  </RegistrationInfo>
  <Triggers>
    <CalendarTrigger>
      <StartBoundary>2016-07-13T23:00:00</StartBoundary>
      <Enabled>true</Enabled>
      <ScheduleByDay>
        <DaysInterval>1</DaysInterval>
      </ScheduleByDay>
    </CalendarTrigger>
  </Triggers>
  <Principals>
    <Principal id="Author">
      <UserId>domain\Administrator</UserId>
      <LogonType>Password</LogonType>
      <RunLevel>HighestAvailable</RunLevel>
    </Principal>
  </Principals>
  <Settings>
    <MultipleInstancesPolicy>IgnoreNew</MultipleInstancesPolicy>
    <DisallowStartIfOnBatteries>true</DisallowStartIfOnBatteries>
    <StopIfGoingOnBatteries>true</StopIfGoingOnBatteries>
    <AllowHardTerminate>true</AllowHardTerminate>
    <StartWhenAvailable>false</StartWhenAvailable>
    <RunOnlyIfNetworkAvailable>false</RunOnlyIfNetworkAvailable>
    <IdleSettings>
      <StopOnIdleEnd>true</StopOnIdleEnd>
      <RestartOnIdle>false</RestartOnIdle>
    </IdleSettings>
    <AllowStartOnDemand>true</AllowStartOnDemand>
    <Enabled>true</Enabled>
    <Hidden>false</Hidden>
    <RunOnlyIfIdle>false</RunOnlyIfIdle>
    <WakeToRun>false</WakeToRun>
    <ExecutionTimeLimit>P3D</ExecutionTimeLimit>
    <Priority>7</Priority>
  </Settings>
  <Actions Context="Author">
    <Exec>
      <Command>C:\taskfolder\task.bat</Command>
      <WorkingDirectory>C:\taskfolder</WorkingDirectory>
    </Exec>
  </Actions>
</Task>

0

注意:这里是我刚刚发现的问题。

注意:你必须有两行:

REM NOTE:You have to create the schedule first
SCHTASKS /S SERVER /CREATE /TN "SERVER_RESTART" /RU "" /TR "D:\WORK\scripts\__server_restart.bat 1" /SC MONTHLY /MO FIRST /D SUN /ST:02:10
REM The next line is run to set the run in folder as well as set the: run as: NT AUTHORITY\SYSTEM
SCHTASKS /S SERVER /CHANGE /TN "SERVER_RESTART" /RU "" /TR "D:\WORK\scripts\__server_restart.bat 1"

我注意到Windows 2008比2003更好地处理批处理脚本。例如,我认为“运行于”文件夹并不像我刚刚从任务计划程序手动在测试机器上运行服务器重启那样重要,它可以正常运行。

对于可能遇到转义字符等问题的人,请考虑以下内容:

SCHTASKS /CHANGE /S SERVER /RU "" /TR "powershell -file "\"D:\WORK\ps\zip_up_files\zip_up_files.ps1"\"" /TN "PowerShell - New Archive"

或者,另一个例子:

SCHTASKS /CREATE /S SERVER /RU "" /TR "powershell -file "\"D:\WORK\ps\page_test.ps1"\"" /TN "PowerShell - Page Test" /SC MINUTE /MO 3 /ST:23:00

注意:额外的引用和额外的反斜杠。

希望这可以帮助!


0

我发现,如果在SCHTASKS命令行中使用8.3命名约定来指定路径和文件名,则“启动位置”字段将自动填充为文件路径 -

例如,“C:\Progra~1\NBVCl~1\nbv_up~1.exe”将导致“C:\Progra~1\NBVCl~1”出现在“启动位置”区域。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接