Specifying “start-in” directory in schtasks comman

2019-01-23 13:45发布

问题:

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.

回答1:

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.


回答2:

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 
}


回答3:

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.



回答4:

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.



回答5:

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



回答6:

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



回答7:

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!



回答8:

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>