Questão Como passar um argumento para uma tarefa agendada do Windows com espaços nele


Eu preciso configurar uma tarefa agendada do Windows. Aceita 1 parâmetro / argumento que é um caminho e pode conter espaços. Minha tarefa agendada não funciona - "quebra" o parâmetro no primeiro espaço.

Se eu executá-lo no Prompt de Comando, posso apenas quebrar o argumento em "" e ele funciona bem, no entanto, isso não funciona na UI da Tarefa Agendada.

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

Eu tentei quebrar o argumento com "" '' [] () e tentei preencher os espaços com% 20, ~ 1 etc. sem sorte.

Eu sei de uma solução para criar um arquivo "" bat e usar o "" meu argumento, mas não quero adicionar mais complexidade.

Eu tentei no Windows 7 e no Windows 2008 Server e ambos falharam. Parece não haver discussões sobre isso?


13


origem


Você está colocando o argumento no Programa / roteiro seção ou o Adicionar argumentos (opcional) seção quando você edita a tarefa agendada? - William Jackson
Seria útil se você especificasse qual programa está usando exatamente, já que o encapsulamento correto de argumentos fica a critério do programa e não do Programado Taks. WinSCP, por exemplo, espera aspas duplas ("" ... "") quando você precisa aninhar aspas. - Tobias Plutat
Não está claro como 1) o que está falhando, a tarefa ou seu .exe e 2) exatamente o que você digitou e onde na UI do TaskSched. Será que onde TaskSched pede um comando (caminho completo para executável), você está tentando dar uma linha de comando (coisa muito diferente)? - kreemoweet
Por que contra arquivo em lotes? Isso torna as coisas tão simples! Ou você pode atirar para script powershell se você está se sentindo aventureiro .. - tumchaaditya


Respostas:


Eu trabalhei com tarefas agendadas e você geralmente coloca os argumentos em sua própria caixa de entrada de texto. Isso significa que você aponta a ação para o campo program / script aponta para o exe e o campo "Add Arguments" deve ter todos os parâmetros. (fonte)

Blog image

Eu acredito que este comportamento foi adicionado para evitar espaços no caminho do arquivo para o exe causando problemas.

Eu faço isso o tempo todo com scripts do PowerShell. Aqui está um exemplo:

  • Programa / script: powershell.exe
  • Adicione argumentos: -command "& 'C: \ HSD - Copiar \ logoffstudents.ps1'" -NãoInterativo
  • Começar: Em branco

5



Obrigado, mas o problema é que um dos meus paramaters é um caminho de arquivo (e tem um espaço nele). Portanto, no seu exemplo 100 funcionará, mas e se você quiser passar "C: \ Start Folder"? - Rodney
Eu apenas uso citações em meus programas e isso funciona. O e comercial só é exigido com o powershell. Esse símbolo é o operador CALL e permite que eu exiba um comando do powershell. Na maioria dos casos, as cotações são tudo o que você precisa. Neste ponto, você pode querer entrar em contato com o criador do exe para ver se eles suportam tarefas agendadas. Eu corri em alguns programas raros que apenas se recusam a executar como uma tarefa agendada. Eu acho que existem diferenças sutis em como os parâmetros são passados, o que pode causar problemas. Desculpe eu não posso ajudar mais. - Doltknuckle
Na pior das hipóteses, você pode reestruturar a pasta para eliminar os espaços. Não é o que você quer, mas pode ser a única maneira de fazê-lo funcionar. - Doltknuckle
Obrigado Doltknuckle - Eu sei que eu também poderia fazer isso com um arquivo .bat (e usar o "" em torno do param (como você faz no script Powershell. Tenho certeza que é um bug na UI do editor de Tarefas do Windows ... sou o criador do exe;) - Ele funciona bem através de um chicote de teste e no prompt de comando, mas não através da interface do Windows ... - Rodney
Se você fez o exe, isso pode ser uma pergunta para o stackoverflow. Eu tenho a sensação de que você pode precisar modificar o seu tratamento de parâmetros quando este exe é usado com a tarefa agendada. Uma sugestão é fazer com que o seu exe registre os parâmetros recebidos em um arquivo para que você possa ver o que está sendo passado. Pelo menos permitiria que você veja se os parâmetros da tarefa agendada são os mesmos que os parâmetros da linha de comando. - Doltknuckle


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"

Observe o uso de ' no caminho de um arquivo a ser executado.


4





Nesse caso, você poderia contornar o problema passando o parâmetro path no formato 8.3.

Você pode descobrir o formato 8.3 para seu caminho abrindo um prompt de comando e emitindo o comando dir /x na raiz da sua unidade.

Você deve ver uma entrada semelhante a

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

para o seu diretório Arquivos de Programas.

Em seguida, altere o diretório para Arquivos de Programas com cd "Program Files"seguido por cd xyz e emitir dir /x novamente para encontrar o nome do formato 8.3 para "A Interface", e assim por diante.

Seu caminho final para o exemplo que você deu seria algo como:

C:\PROGRA~1\XYZ\THEINT~1\FOLDER~1

2



Obrigado, agradeço a resposta, no entanto, isso causa mais problemas. Basicamente eu estou chamando um aplicativo .net EXE que eu escrevi que usa esse caminho de pasta param para algo - não gosta do formato 8.3 e não consegue encontrar o caminho. Então, existe alguma outra maneira de fazer isso? - Rodney
ps - Então isso é bug no aplicativo Windows Scheduled Task? Espaços são muito comuns! - Rodney
Um teste rápido no windows 7 funciona para mim. Você pode nos guiar pelos passos que você deu para configurar a tarefa, assim como de várias maneiras. Obrigado pela edição lá Gareth, parece muito mais legal. - Keith
Portanto, a tarefa é executada corretamente com essa formatação, mas meu programa .NET (que aceita o caminho como uma string arg) não descompacta o caminho do formato 8.3. Então talvez seja uma questão de programação - como lidar com 8.3 caminhos? - Rodney
Eu conheço isso nos velhos, mas você tentou hífen (-)? - Chibueze Opata


Eu tive um problema semelhante com o VLC, que eu estava usando no Windows XP. O truque é inclua o argumento do cmd comando entre aspas duplas.

Aqui está um exemplo do que eu usei (agendando uma gravação às 15:00):

às 15:00 cmd / c "" C: \ Programmi \ VLAN \ VLC \ vlc.exe dvb-t: // frequency = 698000000   : programa = 4006: tempo de execução = 5 --sout "C: \ Documents and   Configurações \ Nome_do_Usuário \ Documentos \ Vídeo \ VLC \ teste.mpg "" "

Observe o uso de aspas duplas logo após /c e no final do comando (depois .mpg). O argumento com espaços neste caso é "C:\Documents and Settings\..."


1





Pode ajudar a entender o problema de uma perspectiva diferente. Digamos que você seja o programador encarregado de adicionar um agendador de tarefas ao Windows. Como você faria? Você tem vários problemas para enfrentar: Se a tarefa for executada como alguém que não seja o usuário logado, você deve irritar o usuário logado com algum erro de pop-up? E se não houver usuário logado no momento em que a tarefa é executada? E quanto à diferença entre um programa GUI e um programa de console? GUI não tem stdin, stdout e stderr; o conceito não tem sentido neles. E quanto aos programas internos ou externos ao COMMAND.COM/CMD.EXE? Ou outros mecanismos de script? E quanto aos caminhos com espaços no nome do comando? Ou nos parâmetros (opções / argumentos)? (Como você está tentando lidar agora ..)

Embora eu não esteja 100% certo sobre os internos ou detalhes técnicos completos neste caso, as respostas parecem ser ... As tarefas são executadas em uma sessão isolada, não interativa, que não pode interagir com o usuário atualmente conectado (se houver ); É executado esperando que não haja saída do console, já que não é interativo, não pode simplesmente interromper qualquer usuário logado para mostrar a saída, de qualquer forma (e se houver saída, stdin é o bitbucket / NULL, stdout e stderr são logados para a facilidade de registro do sistema); Os espaços são manipulados ignorando o problema: o nome do comando é obtido EXATAMENTE como é, e os parâmetros são passados ​​para o comando são especificados em outra caixa de entrada nas propriedades da tarefa.

O que significa que sua tarefa deve ser executada como se fosse um daemon (no Un * x world). Tudo é estático e preciso. O nome do comando é o nome real do comando, sem nenhum parâmetro. Isso geralmente inclui interpretadores de comandos / scripts, como o CMD.EXE! Os parâmetros, se houver, são especificados em outro lugar e devem ser conhecidos quando você configura a tarefa (ou seja, não é possível alterar os parâmetros "on-the-fly"). E assim por diante.

Então, se você quiser incluir parâmetros, você tem que usar a seção de parâmetros para especificar os parâmetros. O Agendador de Tarefas não não tente analisar o nome do comando para dividi-lo em "command" e "args" como os programas de linha de comando. Apenas o trata como um nome de comando grande e completo. Da mesma forma, se você quiser parâmetros variáveis, como usar% 1 ..% n em arquivos BATCH, não poderá fazer isso no próprio Agendador de Tarefas; Você terá que encontrar outro caminho. (Observe que você também não pode usar variáveis ​​de ambiente, pois o ambiente transmitido ao programa depende do ambiente em que a tarefa foi iniciada, NÃO do ambiente "atual".) Você pode usar um arquivo temporário para salvar os parâmetros, mas desde deve especificar um nome de arquivo estático nas propriedades da tarefa, o que acontece quando você está em uma rede com 5000 usuários e quatro deles tentam executar a mesma tarefa ao mesmo tempo? Eles vão todos se atrapalhar tentando escrever no mesmo arquivo temporário ao mesmo tempo, provavelmente não o que você queria. (Existem soluções para esse problema também, mas isso está indo longe demais do escopo desta pergunta e resposta.)

Então, resposta final: No caso simples - o caminho que você quer passar como um parâmetro é estático e não muda - você tem que especificar os parâmetros na propriedade Task apropriada (Argumentos) ao invés da caixa Program / Script. ou use um arquivo em lotes. Em um caso mais complexo - você precisará fazer a pergunta certa ou pesquisar como os daemons funcionam e como usar locking / semáforos e outros para comunicação entre processos (IPC).

Boa sorte.


1





Uma maneira de conseguir isso é usar o powershell na linha de comando.

Adicione este código a um arquivo chamado 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-*"

Então, a partir da linha de comando OU um arquivo ps1 você poderia executar:

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)

Cada item respectivo na matriz taskparameters seria passado como $ (Arg0), $ (Arg1) e $ (Arg2).


1





Definir sua tarefa agendada da seguinte forma

cmd / c C: \ Arquivos de Programas \ xyz \ Transferência de Arquivos FTP \ FTPFileTransferTask.exe "C: \ Arquivos de Programas \ xyz \ A Interface \ Caminho da Pasta"


0