28

I need to set up a Windows Scheduled Task. It accepts 1 parameter/argument which is a path and can contain spaces. My Scheduled task does not work - it "breaks" the parameter up at the first space.

If I run it in the Command Prompt I can just wrap the argument in " " and it works fine, however, this does not work in the Scheduled Task UI.

e.g. C:\Program Files\xyz\FTP File Transfer\FTPFileTransferTask.exe "C:\Program Files\xyz\The Interface\Folder Path"

I have tried wrapping the argument with " " ' ' [ ] () and have tried filling in the spaces with %20, ~1 etc. with no luck.

I know of one solution to make a bat file and use " " around my argument but I don't want to add more complexity.

I tried it on Windows 7 and Windows 2008 Server and both failed. There seems to be no discussions on this?

Rodney
  • 431

9 Answers9

11
schtasks.exe /create /SC WEEKLY /D SUN /SD 11/12/2015 /ST 12:00:00 /TN "taskname" /TR "'c:\program files(x86)\task.exe' Arguments"

Note the use of ' in the path of a file to be run.

techraf
  • 4,952
Aman Mehra
  • 111
  • 1
  • 2
7

I've worked with scheduled tasks and you generally put the arguments in its own text input box. This means that you point the action to the program/script field points to the exe and the "Add Arguments" field should have all of the parameters. (source)

Blog image

I believe this behavior was added to prevent spaces in the file path to the exe causing problems.

I do this all of the time with PowerShell scripts. Here is an example:

  • Program/script: powershell.exe
  • Add arguments: -command "& 'C:\HSD - Copy\logoffstudents.ps1' " -NonInteractive
  • Start in: Blank
Gareth
  • 19,080
Doltknuckle
  • 6,131
5

In this case, you could work around the problem by passing your path parameter in 8.3 format.

You can discover the 8.3 format for your path by opening a command prompt and issuing the command dir /x in the root of your drive.

You should see an entry similar to

11/04/2011  12:10    <DIR>          PROGRA~1     Program Files

for your Program Files directory.

Then change directory to Program Files with cd "Program Files" followed by cd xyz and issue dir /x again to find the 8.3 format name for "The Interface", and so on.

Your final path for the example you gave would look something like:

C:\PROGRA~1\XYZ\THEINT~1\FOLDER~1
Gareth
  • 19,080
Keith
  • 588
1

One way you could accomplish this is using powershell from the command line.

Add this code to a file called MyModule.psm1.

$TASK_STATE_UNKNOWN   = 0;
$TASK_STATE_DISABLED  = 1;
$TASK_STATE_QUEUED    = 2;
$TASK_STATE_READY     = 3;
$TASK_STATE_RUNNING   = 4;
Function Run-Task(
        [ValidateNotNullOrEmpty()][string]
        [Parameter(Mandatory=$true, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true)]
        $ComputerName, 
        [ValidateNotNullOrEmpty()][string]
        [Parameter(Mandatory=$true, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true)]
        $Foldername, 
        [ValidateNotNullOrEmpty()][string]
        [Parameter(Mandatory=$true, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true)]
        $Taskname, 
        [int] $maxwait = 0, 
        [string[]]
        [Parameter(Mandatory=$false, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true)]
        $TaskParameters = $null
    ){
    $TaskScheduler = New-Object -ComObject Schedule.Service
    $TaskScheduler.Connect($ComputerName)
    $ScheduledTaskFolder = $TaskScheduler.GetFolder($Foldername)
    $ScheduledTask = $ScheduledTaskFolder.GetTask($TaskName)

    if(-not $ScheduledTask) {
        return $Null
    }

    $ScheduledTask.Enabled = $True
    $ScheduledTask.Run($TaskParameters)

    if($maxwait -gt 0){
        $seconds = 5
        $i = 0;
        Start-Sleep -Seconds $seconds
        while ($ScheduledTask.State -eq $TASK_STATE_RUNNING)
        {
            if(($i * $seconds) -gt $maxwait) { 
                break; 
            } 
            Start-Sleep -Seconds $seconds        
            $i++;
        }
    }
    return $ScheduledTask
}

Export-ModuleMember -Variable "TASK_STATE*"
Export-ModuleMember -Function "Run-*"

Then from the command line OR a ps1 file you could run:

Import-Module $(Get-Item .\MyModule.psm1 | Resolve-Path -Relative) -DisableNameChecking -Force

$task = Run-Task -ComputerName "$env:COMPUTERNAME" -Taskname "Foo" -Foldername "\" -TaskParameters "test", "Tim C", $(Get-Date -format G)

Each respective item in the taskparameters array would get passed in as $(Arg0), $(Arg1), and $(Arg2).

1

I had a similar problem with VLC, which I was using on Windows XP. The trick is to enclose the argument of the cmd command in double quotes.

Here is an example of what I used (scheduling a recording at 15:00):

at 15:00 cmd /c ""C:\Programmi\VideoLAN\VLC\vlc.exe dvb-t://frequency=698000000 :program=4006 :run-time=5 --sout "C:\Documents and Settings\UserName\Documents\Video\VLC\test.mpg"""

Note the use of double quotes just after /c and at the end of the command (after .mpg). The argument with spaces in this case is "C:\Documents and Settings\..."

tomatoma
  • 11
  • 2
0

By passing two arguments instead of one in the "Add arguments (optional)" input box. As follows :

/myArg1:"C:\Program Files\xyz\FTP File Transfer\FTPFileTransferTask.exe" 
/myArg2:"C:\Program Files\xyz\The Interface\Folder Path"

Just retrieve and process these two arguments in the invoked script. In VBS by example, use WScript.Arguments to retrieve the arguments passed.

0

Set your scheduled task as follows

cmd /c C:\Program Files\xyz\FTP File Transfer\FTPFileTransferTask.exe "C:\Program Files\xyz\The Interface\Folder Path"

0

It might help to understand the problem from a different perspective.. Let's say you're the programmer who's been charged with adding a task scheduler to Windows. How would you do it? You have several problems to contend with: If the task is run as someone other than the logged in user, should you annoy the logged in user with any error popups? What if there is no logged in user at the time the task is run? What about the difference between a GUI program and a console program? GUI's don't have stdin, stdout, and stderr; the concept is meaningless in them. What about programs internal or external to COMMAND.COM/CMD.EXE? Or other scripting engines? What about paths with spaces in the command name? Or in the parameters (options/arguments)? (As you're trying to deal with now..)

While I'm not 100% certain about the internals or full technical details in this case, the answers seem to be.. Tasks are run in an isolated, non-interactive session, which cannot interact with the currently logged in user (if any); It's run expecting there to be no console output, since it's non-interactive, it cannot just interrupt any logged in user to show the output, anyhow (and if there is output, stdin is the bitbucket/NULL, stdout and stderr get logged to the system logging facility); Spaces are handled by bypassing the issue: the command name is taken EXACTLY as is, and parameters are passed to the command are specified in another input box in the Task properties.

What all the means is that your task has to be run as if it were like a daemon (in the Un*x world). Everything is static and precise. The command name is the actual command name, without any parameters. This often includes running command/script interpreters, such as CMD.EXE! The parameters, if any, are specified elsewhere, and must be known when you set up the task (that is, you cannot change the parameters "on-the-fly"). And so on.

So, if you want to include parameters, you have to use the parameters section to specify the parameters. The Task Scheduler does not try to parse the command name to split it in to "command" and "args" like command line programs do. It just treats it as one big, full command name. Likewise, if you want variable parameters, like using %1 .. %n in BATCH files, you cannot do so from the Task Scheduler itself; You'll have to find another way. (Note that you cannot use environment variables, either, since the environment passed to the program depends on the environment the task is started with, NOT the "current" environment.) You could use a temporary file to save the parameters, but since you must specify a static filename in the Task properties, what happens when you are on a network with 5000 users and four of them try to run the same task at the same time? They'll all clobber each other trying to write to the same temp file at the same time, probably not what you wanted, either. (There are solutions to this problem, too, but that's going too far outside the scope of this question and answer..)

So final answer: In the simple case -- the path you want to pass as a parameter is static and does not change -- you either have to specify the parameters in the appropriate Task property (Arguments) rather than in the Program/Script box, or use a batch file. In a more complex case -- you'll need to ask the right question or research how daemons work and how to use locking/semaphores and such for inter-process communication (IPC).

Good luck.

C. M.
  • 777
-1

Microsoft has a bulletin on this: https://support.microsoft.com/en-us/help/823093/a-scheduled-task-does-not-run-when-you-use-schtasks-exe-to-create-it-a

Basically it says to use the sequence "\" before and after name of the batch file.

LewTwo
  • 1