Execute um arquivo .bat em uma tarefa agendada sem uma janela

143

Eu tenho uma tarefa agendada que inicia um script em lote que é executado a robocopycada hora. Toda vez que é executada, uma janela aparece na área de trabalho com a saída do robocopy, que eu realmente não quero ver.

Consegui fazer a janela parecer minimizada, executando o trabalho agendado

cmd /c start /min mybat.bat

mas isso me dá uma nova janela de comando a cada hora. Fiquei surpreso com isso, pois cmd /c"Executa o comando especificado por string e depois termina" - devo ter entendido mal os documentos.

Existe uma maneira de executar um script em lote sem ele aparecer uma janela do cmd?

Tom Dunham
fonte
Eu encontrei este um mais preferível resposta stackoverflow.com/questions/6568736/...
Efekt

Respostas:

144

Você pode executá-lo silenciosamente usando um arquivo de script do Windows. O método Run permite executar um script no modo invisível. Crie um .vbsarquivo como este

Dim WinScriptHost
Set WinScriptHost = CreateObject("WScript.Shell")
WinScriptHost.Run Chr(34) & "C:\Scheduled Jobs\mybat.bat" & Chr(34), 0
Set WinScriptHost = Nothing

e agende. O segundo argumento neste exemplo define o estilo da janela. 0 significa "ocultar a janela".

Sintaxe completa do método Run :

 object.Run(strCommand, [intWindowStyle], [bWaitOnReturn])

Argumentos:

  • objeto: objeto WshShell.
  • strCommand: valor da sequência que indica a linha de comando que você deseja executar. Você deve incluir todos os parâmetros que deseja passar para o arquivo executável.
  • intWindowStyle: Opcional. Valor inteiro indicando a aparência da janela do programa. Observe que nem todos os programas usam essas informações.
  • bWaitOnReturn: Opcional. Valor booleano que indica se o script deve aguardar a conclusão da execução do programa antes de continuar para a próxima instrução em seu script. Se definido como true, a execução do script será interrompida até a conclusão do programa e Run retornará qualquer código de erro retornado pelo programa. Se definido como false (o padrão), o método Run retornará imediatamente após o início do programa, retornando automaticamente 0 (não deve ser interpretado como um código de erro).
splattne
fonte
+1, apenas escreveu exatamente a mesma coisa
Sam Cogan
Eu o vi antes de você excluí-lo. Eu acho que nós dois somos robôs. ;-)
splattne
11
nome de usuário, sinceramente acho que Sam merece muito mais do que eu. Mas obrigada mesmo assim! E não mencione eu e Jon Skeet na mesma frase. Isso é blasfêmia! ;-)
splattne
3
Para a pergunta "Existe uma maneira de executar um script em lote sem abrir uma janela do cmd?", Fornece uma resposta muito direta: Execute-o usando um arquivo de script do Windows.
Mark Meuer
2
@ Lee Acho que aspas duplas são necessárias se o seu caminho contiver espaços.
splattne
58

Você está executando isso como uma tarefa agendada? Se assim for, defina-o para ser executado como uma conta de usuário diferente, e não ficará visível para o usuário conectado. Se o script não precisar de acesso à rede para itens que precisam de autenticação do Windows (como compartilhamentos de arquivos ou impressoras), você poderá executá-lo como "nt Authority \ system" e deixar a senha em branco. No Windows 7, defina o usuário como SYSTEM e pressione OK.

(Você provavelmente precisará usar um usuário real, se estiver usando robocopy ...)

JR

John Rennie
fonte
3
Obrigado - isso foi menos complicado para mim do que a opção .vbs.
mackenir
8
Defino o usuário "Executar como" como SYSTEM (que mais tarde foi alterado para NT AUTHORITY \ SYSTEM) e funcionou para mim. Não vejo mais a janela pop-up do CMD quando minha tarefa agendada é executada. Obrigado!
Ryan Stille
11
+1, isso é elegante. Certifique-se de inserir "system" como o nome de usuário, e o win7 fará o resto por você. Observe que você obtém acesso de rede à Internet, mas não compartilhamentos de rede e coisas que precisam de autenticação do Windows.
samsmith
11
O usuário do sistema é simples e elegante, excelente dica! +1!
Matteo Conta
11
Consulte Implementando modelos administrativos de privilégios mínimos . O uso da conta do sistema para isso viola as políticas de privilégios mínimos? Nesse caso, os administradores devem saber não fazer isso na maioria das situações.
user34660
29

Simplesmente configure a Tarefa agendada como "Executar se o usuário estiver conectado ou não".

Peter Meinl
fonte
6
Perfeito! Você pode até desativar o armazenamento de credenciais e isso acaba sendo mais seguro do que o SYSTEM executá-lo!
binki
17

Você também pode tentar o CHP (Criar processo oculto) , faz exatamente o que você pensa ...

CHP.EXE mybat.bat

É executado sem janela de comando. Perfeito! Feito pelas mesmas pessoas que o CMDOW, mas isso é mais apropriado.

rocketmonkeys
fonte
Funciona perfeitamente quando você precisa executar a tarefa no contexto do usuário conectado ( "Trigger: em conectar a sessão do usuário", "Executar tarefa como: Usuários")
Sergei
11
esta não é uma ferramenta construída em
JonnyRaa
9

O CMDOW é uma ferramenta impressionante que permite fazer muitas coisas no Windows a partir da linha de comando.

Uma das coisas mais simples a fazer é ocultar a janela atual (geralmente como uma primeira linha no arquivo bat) com:

cmdow @ /hid

ou inicie um novo processo oculto com

cmdow /run /hid mybat.bat 
itsadok
fonte
4
Tanto a sugestão como a Rocketmonkeys envolvem o download de novas ferramentas, o que significa mais compatibilidade com os desktops de várias pessoas. O cozido, usando comandos do Windows é muito melhor.
21411 IanVaughan
Além disso cmdow é detectado como "perigosos" por alguns programas anti-vírus (que é não perigosos, mas a detecção pode-se causar alguns problemas se o arquivo cmdow está em quarentena ...).
Otiel
3
ainda existe um console pop-up, basta piscar muito rápido.
Bamboo
5

Tente chamar o script com

start /b <command>

fonte
11
Isso não funciona, a Tarefa agendada-> Status indica "Não foi possível iniciar", com: start / b C: \ file.bat: e: start / b "C: \ file.bat": mas: C: \ file.bat: funciona bem.
21411 IanVaughan
11
Porque startnão é um programa, é um comando. Você precisa especificar cmdcomo o programa a ser executado e /c start /b <file>como argumento. No entanto, isso ainda não vai funcionar porque ainda criará uma janela do console cmde exibirá uma janela preta na tela.
Synetech
11
Também é possível confirmar com o @Synetech que isso não criará uma nova janela, mas você ainda precisa abrir uma janela do console para iniciá-la. Este é realmente um comando útil, mas não pode ser usado conforme solicitado nas Tarefas agendadas.
JonathanDavidArndt
5

Você pode criar um atalho para o arquivo em lotes, definir o atalho para começar a ser minimizado (nas propriedades do atalho, guia 'Atalho') e, em seguida, definir o trabalho para iniciar o atalho.

Importante : você precisará especificar o caminho para o atalho manualmente, digitando-o no campo de texto Executar, completo com a extensão '.lnk'; se você apenas tentar navegar para ele, ele vai prestativamente redirecionar-se a qualquer que seja o atalho aponta para.

Doug Kavendek
fonte
Isso não funciona no Windows 10 x64, é exibida uma janela pop-up "Como você deseja abrir este arquivo?"
Janeiro
1

Sei que essa pergunta já foi respondida com uma resolução perfeitamente boa, nativa do Windows e, portanto, deve ser a mais compatível, e concordo completamente.

Eu também queria dizer que não concordo com o comentário de @ splattne (mas não com a resposta real) - que a resolução no outro segmento mencionado merece o crédito. Essa resposta envolve a execução do script como um usuário diferente (SYSTEM), que é praticamente o equivalente a dar acesso à raiz do script. Ele também falhará em trabalhos como ROBOCOPY(como mencionado por John Rennie), que exigem acesso à rede.

Eu nunca tentei CMDOWantes, mas gostaria de oferecer outra resolução semelhante, que [embora não esteja instalada nativamente no Windows] ainda é altamente portátil para a maioria das versões e vem nas versões de 32 e 64 bits, e isso é NirCmd .

O NirCmd é uma ferramenta muito poderosa que possui inúmeras opções, das quais a mais útil é pessoalmente a capacidade de iniciar janelas de comando ocultas, executando simplesmente o seguinte:

c:\path\to\nircmd.exe exec hide "c:\path\to\mybat.bat"

Na execseção Referência do comando NirCmd :

exec [show/hide/min/max] [application + command-line]

Executa um aplicativo e, opcionalmente, especifica um ou mais parâmetros de linha de comando para o aplicativo executado. O parâmetro [show / hide / min / max] especifica se o aplicativo em execução será visível ou não. Se 'ocultar' for especificado, o aplicativo em execução não estará visível para o usuário. Se 'max' for especificado, a janela do aplicativo em execução será maximizada. Se 'min' for especificado, a janela do aplicativo em execução será minimizada.

Edição: Eu estava tentando executar um ROBOCOPYtrabalho e tentei o método nesta resposta, e não funcionou, mesmo depois de editar os privilégios de acesso à rede. Tentei clicar duas vezes no script e não consegui fazê-lo funcionar, mas só consegui executá-lo em um prompt de comando elevado. Eu criei um atalho para o arquivo em lotes e o execute como administrador e consegui executá-lo clicando duas vezes nele, mas o método com o qual acabei indo foi executá-lo oculto como SYSTEM (eu sei, eu sei) - mas funciona ROBOCOPY, pelo que vale, desde que o arquivo em lotes tenha as permissões corretas.

EDIT 2: Por algum motivo, ele não funcionaria como SYSTEM (provavelmente o acesso à rede mencionado anteriormente) - só notei isso depois de executar ROBOCOPYsem o sinalizador / L, que é basicamente apenas uma simulação e [aparentemente] não funciona. na verdade, conecto-me ao sistema remoto, mas quando executo o arquivo em lotes com os maiores privilégios e marque a caixa oculta, ainda posso executá-lo como usuário logado em segundo plano, sem uma janela de comando, por qualquer valor que isso valha a alguém .

rubynorails
fonte
-2

Tente inserir um comando de saída no final do seu arquivo em lotes. Isso deve fechar a janela de comando quando o script for concluído.

Brian S. Wilson
fonte
-2

Para ocultar a saída (embora não seja a janela), adicione isso no início do seu arquivo em lotes:

@echo off
voidstate
fonte