24

I realize that this question is "answered" at the following thread: Specifying the running directory for Scheduled Tasks using schtasks.exe

However, I'm still having trouble understanding the answer and seeing exactly what the result would look like for my situation.

My schtasks command looks like this:

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

I want to specify the start in directory of "C:\My Library". Putting a "\" before the tr section fills in a start-in directory of "C:\Program Files\Java\jre6\bin".

I've messed around with it a lot, but I just can't seem to make it work.

Community
  • 1
  • 1
Benny
  • 1,508
  • 3
  • 18
  • 34

9 Answers9

16

If all else fails, you can redirect to a batch file that sets it's own CD, then calls your program.
for example:

Schtasks /Create /TR "C:\example\batch.bat" /SC WEEKLY /TN mytask

As the schtask, and

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

as "C:\example\batch.bat". That should keep the current directory as whatever you change it to in the batch file and keep all references relative to that.

Evan
  • 566
  • 1
  • 6
  • 15
  • 1
    This is the best solution, and should be upvoted. Unlike the other solutions, it doesn't require Windows 2012, or an XML solution, and doesn't have issues with Windows 2008 R2. – twasbrillig Jan 24 '15 at 08:04
  • 1
    +1 for reminding me that you can specify the .bat file directly in /TR, don't need to invoke cmd.exe, etc. – BobHy Jan 27 '16 at 14:07
  • this solution is nice and I used it, but it won't allow me to schedule a second task to kill a win32 console application with taskkill /t, which instead IS possible if I don't start via .bat file. The only way to kill such an application is taskkill /f which will not allow the program to clean up before forced kill. – Micka Jul 26 '17 at 08:30
  • You should probably use cd /d "x:\path\to\dir" because cd won't work when changing the drive letter, without /d – Michi Sep 28 '22 at 08:47
15

UPDATE: Note that starting from Powershell v3 (but only under Windows 2012 and higher!) there's new API which I find much more attractive:

$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's solution with /v1 switch is great but doesn't allow to create tasks in custom folders (ie you can't create "MyCompany\MyTask" and everything ends up in the root folder), so I finally ended up with a PowerShell script described below.

Usage:

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 must be lowercase - for a boolean you'd need $value.ToString().ToLower())

Implementation:

The function uses XML task definition and "Schedule.Service" COM object.

#####################################################
#
#  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 
}
andreister
  • 13,693
  • 2
  • 44
  • 45
  • 2
    Unfortunately this is only available for Powershell 3 under Windows 2012 and higher. Windows 2008R2 does not have this, even with Powershell 3. – Brain2000 Jan 21 '15 at 22:50
  • XML seems to be the way to go, at least if you want to write a script that can be be used across different servers, especially pre-Windows Server 2012. – David Keaveny Aug 27 '15 at 23:37
14

Not sure what version of Windows you are on, but from reading the other question it looks like schtasks on Vista / Server 2008 does not provide a command option that would allow you to specify a "start-in" directory directly. The workarounds people provided were:

  1. Use the /v1 flag to create a XP / 2003 compatible task, in which case the "start-in" directory is automatically set. Not sure what it is set to but I suspect it may be the same directory as your task executable, which won't work for you.
  2. Create your task from an XML file (using the /XML option) which does allow you to specify a "start-in" directory. Sorry I don't know the syntax / structure for this XML file.
  3. Create your task using the Task Scheduler UI instead.
Amal Sirisena
  • 1,479
  • 10
  • 10
  • Good solution but doesn't seem to allow task names with folders - ie you can't create "MyCompany\MyTask" with /v1 switch (works without the switch though) – andreister Nov 22 '11 at 15:24
  • The /V1 flag works, but you need to make sure your /TR path uses back slashes in the path. When I used forward slashes in the path, the task does not run successfully. – panofish Dec 18 '14 at 15:07
  • 2
    where does the `/v1` flag go in the command? does it require any arguments? – HattrickNZ Jan 26 '15 at 21:40
3

As you note, the trick of using the extra quotes in the /TR parameter only allows you to use the same directory as where the executable resides. If you want to specify a different working directory, you should use the /XML option and specify an XML file that lists the working directory. The command would be something like this:

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

The XML file would look something like this:

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

There's more information about the XML schema here: http://msdn.microsoft.com/en-us/library/windows/desktop/aa383609(v=VS.85).aspx

Bernard Chen
  • 6,437
  • 5
  • 23
  • 27
2

The need

To schedule a task that will run from an specific directory. If we call this directory c:\x whenever the pwd command is executed it will print c:\x. Every path from there is relative to that directory.

Another example: running java -jar myapp.jar will execute the JAR file located in c:\x\myapp.jar

The problem

It is impossible to set that specific parameter using the command schtasks /create

The solution

Is a bit steppy (like in too many steps):

  1. Create the task as specific as you can using the schtasks /create command. Try to set every parameter to the desired value: start time, repetition, duration, etc...

    In this case the /tn argument is mandatory, so set it: \tn mytask

  2. Export the newly created task to XML using schtasks /query /tn mytask /xml > mytask.xml

  3. Open mytasks.xml in your favorite editor. You should see something like this (I've hidden the not interesting parts):

<?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>
  1. Inside the <Exec> section, below to the <Argument> field introduce a new field:
<WorkingDirectory>c:\x\</WorkingDirectory>

And save the file. This field is defined in the xml schema definition here https://learn.microsoft.com/en-us/windows/desktop/taskschd/task-scheduler-schema

  1. Delete the previously created task (to recreate it using the modified xml): schtasks /delete /tn mytask

  2. Create the task again using /xml argument: schtasks \tn mytask \xml mytask.xml

Just to see if it works

Execute it using schtasks /run /tn mytask.

halfer
  • 19,824
  • 17
  • 99
  • 186
2

Try

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

Change working directory and then run schtasks.

Kevin
  • 53,822
  • 15
  • 101
  • 132
0

I have found that if you use the 8.3 naming convention in the SCHTASKS command line for the path and file names the "Start In" field is polulated with the file path -

e.g. "C:\Progra~1\NBVCl~1\nbv_up~1.exe" will result in "C:\Progra~1\NBVCl~1" appearing in the "start In" area

0

Note: Here is the issue that I just saw with this..

Note: You have to have two lines:

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"

One of the things that I have noticed with Windows 2008, is that it handles batch scripts much better than 2003, for example. I don't think the "run in" Folder is as important as I just ran the server restart on a test machine manually from Task Scheduler and it runs just fine..

For the folks that maybe running into issues with escaping characters and such, consider the following:

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

or, another example:

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

Note: The extra Quoting and the extra backslashes.

Hope this helps!

Leptonator
  • 3,379
  • 2
  • 38
  • 51
0

The only way would be to use an XML Flle, use the following command: schtasks /Create /XML C:\file.xml /TN TaskName /RU domain\username /RP password

Sample XML File that will run every day at 23:00, the C:\taskfolder will set the run in directory:

<?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>
Bob
  • 1