Como posso saber se meu arquivo em lote está em execução?

Como posso saber se meu arquivo em lote está em execução?

Eu tenho um script em lote que é executado a partir de um comando AT e pode ser executado mais de uma vez. Quando iniciar, preciso detectar se já está em execução e, em caso afirmativo, sair (do segundo) imediatamente.

  1. Deve ser robusto e lidar com o caso de os scripts saírem inesperadamente (ou seja, não posso definir um sinalizador na entrada e limpá-lo na saída)
  2. Deve ser executado em uma sessão de Área de Trabalho Remota
  3. Estou preso no XP com Powershell v2, mas não me importo de escrever um pequeno exe se não puder fazer isso em lote/powershell ou vbs
  4. O script deve ser executado minimizado, então eu inicio com Iniciar "NAME" /MIN %COMSPEC% /C "MyScript.bat"
  5. Outras janelas cmd podem estar abertas, então preciso verificar o script em execução
  6. O script em lote é executado como usuário SYSTEM, mas não consigo usar nenhum WMI

Eu estava usando o PowerShell Get-Process para examinar MainWindowTitle, mas isso não funcionou durante a conexão remota ao computador, pois o script pode estar em execução, mas não exibido nesta instância de conexão remota. Neste caso, o processo cmd é visto pelo Get-Process, mas o MainWindowTitle está em branco.

Eu tentei Get-Process e olhei para a propriedade expandida StartInfo.EnvironmentVariables, mas não consigo ver como criar um env var para que ele apareça na propriedade.

Pensei em usar /WAIT no comando start, então o AT ficará aberto até terminar, mas o script contendo o AT não é minimizado

Alguma ideia?

Responder1

Acredito que um arquivo de bloqueio é a solução mais simples e confiável. O truque é garantir que o processo em lote em execução mantenha um bloqueio de gravação exclusivo no arquivo até que ele termine. A beleza deste sistema é que o Windows irá liberar o bloqueio independentemente do motivo do término do lote.

Depois de ter um arquivo bloqueado, você precisará detectar se o arquivo está bloqueado no momento. Eu descrevo como fazer isso emComo verificar na linha de comando se um determinado arquivo ou diretório está bloqueado (usado por algum processo)?

Usei esta técnica primitiva, mas eficaz, para realizar algumas tarefas bastante sofisticadas com o lote do Windows:

Você não está claro onde o arquivo em lote reside - na máquina remota ou na máquina local, ou se pode estar executando o script em várias máquinas simultaneamente, mas apenas em um processo ativo por máquina.

Se o script em lote estiver na máquina remota e seu processo tiver acesso de gravação ao script, você poderá usar o próprio arquivo em lote como arquivo de bloqueio! Você simplesmente precisa chamar uma :subroutine enquanto redireciona um identificador de arquivo não utilizado para o script em lote usando o modo de acréscimo. A CALL falhará se outro processo já tiver um bloqueio. O bloqueio será liberado automaticamente quando o script terminar (independentemente de como ele termina).

meuscript.bat

@echo off
:: Note - this extra call is to avoid a bug with %~f0 when the script
::        is executed with quotes around the script name.
call :getLock
exit /b

:getLock
:: The CALL will fail if another process already has a write lock on the script
call :main 9>>"%~f0"
exit /b

:main
:: Body of your script goes here. Only one process can ever get here
:: at a time. The lock will be released upon return from this routine,
:: or when the script terminates for any reason
exit /b

Se o seu script estiver em uma máquina diferente do processo, mas você só tiver o processo em execução em uma máquina por vez, acho que o procedimento acima ainda funcionará.

Talvez uma alternativa melhor seja estabelecer um arquivo de bloqueio dedicado em cada máquina remota, separado do script em lote. Então você pode executar o processo em quantas máquinas remotas desejar.

Responder2

Obrigado pela ajuda. Eu implementei o seguinte:

Before starting my script (in a wrapper script), check whether the lockfile exists:
  If it does, read the PID out of it.
    If the PID is still a running cmd process, exit my script as another version of it is already running.
    If the PID is not still a running cmd process, delete the lockfile
  Start the script, and create a new lockfile, containing the PID of the started script

When exiting my script, delete the lockfile

Isso parece funcionar bem, mais testes dirão.

  1. Para listar os processos em execução, eu uso o POWERSHELL Get-Process, pois o TASKLIST usa o WMI, que, como afirmei anteriormente, não está disponível para mim.
  2. Para determinar o PID do script iniciado, listo todos os PIDs do cmd atuais, inicio o script e listo todos os PIDs do cmd, procurando aquele que não estava lá antes.

Responder3

Criei um plugin automatizado chamado CMDS que você pode usar aqui:Como posso ver se um determinado arquivo em lote está em execução e obter o PID?No entanto, não tenho certeza se isso funcionará com o XP.

Comando de exemplo:CMDS /TS "Your Batch File Title"

Ele também possui um modo gui para ser usado sozinho.

Aqui está o arquivo de ajuda:

Mensagem de ajuda

informação relacionada