2011-04-14 05:24:06 +0000 2011-04-14 05:24:06 +0000
15
15

如何将一个参数传递给一个有空格的Windows计划任务?

我需要设置一个Windows的计划任务,它接受1个参数/参数,是一个路径,可以包含空格。它接受1个参数/参数是一个路径,可以包含空格。我的计划任务不工作–它在第一个空格处 “打破 "了参数。

如果我在命令提示符中运行它,我可以用”“包裹参数,它就能正常工作,然而,这在任务调度界面中却不能工作。

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

我试过用” “ 来包装参数,也试过用%20、~1等来填充空格,但没有成功。

我知道一个解决方案,就是制作一个bat文件,在参数周围使用” “,但我不想增加更多的复杂性。

我在Windows 7和Windows 2008 Server上试过,都失败了。似乎没有人讨论这个问题?

答案 (8)

6
6
6
2016-04-12 05:46:09 +0000
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"

注意在要运行的文件路径中使用'

6
6
6
2011-05-19 20:24:00 +0000

我曾在计划任务中工作过,你一般把参数放在它自己的文本输入框中。这意味着你将操作指向程序/脚本字段指向exe,"添加参数 “字段应该有所有的参数。 )

我相信添加这种行为是为了防止exe文件路径中的空格造成问题。

我在使用PowerShell脚本时经常这样做。下面是一个例子:

  • 程序/脚本: powershell.exe
  • 添加参数 : -command ”& ‘C:\HSD - Copy/logoffstudents.ps1’“ -NonInteractive
  • 开始于:空白。
3
3
3
2011-04-14 06:31:15 +0000

在这种情况下,你可以通过传递8.3格式的路径参数来解决这个问题。

你可以通过打开命令提示符,在硬盘根部发出dir /x命令来发现路径的8.3格式。

你应该会看到一个类似于

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

的条目来显示你的Program Files目录。

然后用cd "Program Files将目录改为Program Files",接着cd xyz并再次发出dir /x找到 “The Interface "的8.3格式名称,以此类推。

你给出的例子中的最终路径看起来是这样的。

C:\PROGRA~1\XYZ\THEINT~1\FOLDER~1
1
1
1
2013-10-27 22:45:45 +0000

我在Windows XP上使用的VLC也有类似的问题。诀窍是cmd命令的参数用双引号括起来。

下面是我使用的一个例子(在15:00安排录音):

在15:00 cmd /c “"C:\Programmi\VideoLAN\VLC\vlc.exe dvb-t://frequency=698000000 :program=4006 :run-time=5 –out "C:\Documents and Settings\UserNameDocuments\Video\VLC\test.mpg”“

请注意,在/c之后和命令结尾处(.mpg之后)使用双引号。在这种情况下,带空格的参数是"C:\Documents and Settings\..."

1
1
1
2017-02-15 13:27:49 +0000

有一种方法你可以通过命令行使用powerhell来实现。

将这段代码添加到一个名为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-*"

然后从命令行或ps1文件中你可以运行。

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)

taskparameters数组中的每一项都会以$(Arg0)、$(Arg1)和$(Arg2)的形式传递进来。

0
0
0
2014-04-28 13:52:02 +0000

设置你的计划任务如下

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

0
0
0
2015-04-20 19:48:47 +0000

从不同的角度来理解这个问题可能会有帮助。假设你是负责给Windows添加任务调度程序的程序员。你会怎么做呢?你有几个问题要解决。如果任务是以登录用户以外的人的身份运行的 你是否应该用任何错误的弹窗来烦扰登录用户?如果任务运行时没有登录用户怎么办?GUI程序和控制台程序的区别呢?GUI没有stdin、stdout和stderr,这个概念在他们那里是没有意义的。那COMMAND.COM/CMD.EXE内部或外部的程序呢?或者其他脚本引擎呢?命令名中带空格的路径呢?或者在参数中(选项/参数)?(就像你现在要处理的那样…)

虽然我对这个案例的内部结构或全部技术细节没有100%的把握,但答案似乎是…。任务是在一个隔离的、非交互式的会话中运行的,它不能与当前登录的用户(如果有的话)交互;它的运行期望没有控制台输出,因为它是非交互式的,它不能随便打断任何登录的用户来显示输出,无论如何(如果有输出,stdin是bitbucket/NULL,stdout和stderr会被记录到系统日志设施);空格是通过绕过问题来处理的。命令名完全按原样取,传递给命令的参数在任务属性的另一个输入框中指定。

这意味着你的任务必须像守护进程一样运行(在Un*x世界里)。所有的东西都是静态和精确的。命令名是实际的命令名,没有任何参数。这通常包括运行命令/脚本解释器,如CMD.EXE! 如果有参数的话,这些参数是在其他地方指定的,而且必须在你设置任务时就知道(也就是说,你不能 “即时 "改变参数)。以此类推。

所以,如果你想包含参数,你必须使用参数部分来指定参数。任务调度程序不会像命令行程序那样,试图解析命令名,把它分割成 "command "和 "args"。它只是把它当作一个大的,完整的命令名。同样的,如果你想要变量参数,比如在BATCH文件中使用%1 … %n,你不能从任务调度程序本身做,你必须找到其他的方法。(注意,你也不能使用环境变量,因为传递给程序的环境取决于任务启动时的环境,而不是 "当前 "环境。) 你可以使用一个临时文件来保存参数,但是由于你必须在任务属性中指定一个静态文件名,当你在一个有5000个用户的网络上,其中四个用户试图同时运行同一个任务时会发生什么?他们会在同一时间互相攻击,试图写入同一个临时文件,这可能也不是你想要的。(这个问题也有解决方法,但这已经超出了这个问题和答案的范围…)

所以最后的答案。在简单的情况下 – 你想传递的参数路径是静态的,不会改变 – 你要么在适当的任务属性(Arguments)中指定参数,而不是在程序/脚本框中,要么使用批处理文件。在更复杂的情况下–你需要提出正确的问题,或者研究守护进程是如何工作的,以及如何使用锁/信号灯等进行进程间通信(IPC)。

祝你好运。

-1
-1
-1
2019-06-27 16:39:40 +0000

微软有一个关于这个问题的公告 https://support.microsoft.com/en-us/help/823093/a-scheduled-task-does-not-run-when-you-use-schtasks-exe-to-create-it-a

基本上它说要在批处理文件的名称前后使用“/”序列。