Как узнать, запущен ли мой пакетный файл?

Как узнать, запущен ли мой пакетный файл?

У меня есть пакетный скрипт, который запускается из команды AT и может запускаться более одного раза. Когда он запускается, мне нужно, чтобы он определял, запущен ли он уже, и если да, немедленно завершал (второй).

  1. Он должен быть надежным и обрабатывать неожиданные завершения работы скриптов (т. е. чтобы я не мог установить флаг при входе и снять его при выходе).
  2. Он должен работать в сеансе удаленного рабочего стола.
  3. Я застрял на XP с Powershell v2, но не против написать небольшой exe-файл, если я не могу сделать это в пакетном режиме/PowerShell или VBS
  4. Скрипт должен работать в свернутом виде, поэтому я запускаю его с помощью Start "NAME" /MIN %COMSPEC% /C "MyScript.bat"
  5. Другие окна cmd могут быть открыты, поэтому мне нужно проверить запущенный скрипт.
  6. Пакетный скрипт запускается от имени пользователя SYSTEM, но я не могу использовать WMI

Я использовал PowerShell Get-Process, чтобы посмотреть MainWindowTitle, но это не сработало при удаленном подключении к компьютеру, поскольку скрипт может быть запущен, но не отображаться в этом экземпляре удаленного подключения. В этом случае процесс cmd виден Get-Process, но MainWindowTitle пуст.

Я попробовал Get-Process и посмотрел на расширенное свойство StartInfo.EnvironmentVariables, но не могу понять, как создать переменную окружения, чтобы она появилась в свойстве.

Я думал об использовании /WAIT в команде запуска, тогда AT останется открытым до завершения, но скрипт, содержащий AT, не будет свёрнут

Есть идеи?

решение1

Я считаю, что файл блокировки — это самое простое и надежное решение. Хитрость в том, чтобы убедиться, что ваш запущенный пакетный процесс поддерживает исключительную блокировку записи в файле до тех пор, пока он не завершится. Прелесть этой системы в том, что Windows снимет блокировку независимо от причины завершения пакета.

После того, как у вас есть файл блокировки, вам нужен способ определить, заблокирован ли файл в данный момент. Я описываю, как это сделать, наКак проверить в командной строке, заблокирован ли данный файл или каталог (используется ли каким-либо процессом)?

Я использовал этот примитивный, но эффективный метод для выполнения некоторых довольно сложных задач с помощью пакетной обработки Windows:

Вам не ясно, где находится пакетный файл — на удаленной машине или на локальной машине, или вы запускаете скрипт на нескольких машинах одновременно, но на каждой машине активен только один процесс.

Если пакетный скрипт находится на удаленной машине, и ваш процесс имеет доступ на запись в скрипт, то вы можете использовать сам пакетный файл в качестве файла блокировки! Вам просто нужно вызвать :subroutine, перенаправив неиспользуемый дескриптор файла в пакетный скрипт с помощью режима добавления. CALL завершится неудачей, если другой процесс уже имеет блокировку. Блокировка будет автоматически снята, когда скрипт завершится (независимо от того, как он завершится).

мойскрипт.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

Если ваш скрипт и процесс находятся на разных машинах, но процесс выполняется только на одной машине одновременно, то я думаю, что вышеизложенное все равно будет работать.

Возможно, лучшей альтернативой будет создание выделенного файла блокировки на каждой удаленной машине, отдельно от пакетного скрипта. Тогда вы сможете запустить процесс на стольких удаленных машинах, на скольких захотите.

решение2

Спасибо за помощь. Я реализовал следующее:

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

Похоже, это работает нормально, дальнейшие испытания покажут.

  1. Для получения списка запущенных процессов я использую POWERSHELL Get-Process, поскольку TASKLIST использует WMI, который, как я уже говорил ранее, мне недоступен.
  2. Чтобы определить PID запущенного скрипта, я перечисляю все текущие PID cmd, запускаю скрипт, затем перечисляю все PID cmd, ища тот, которого раньше не было.

решение3

Я создал автоматизированный плагин под названием CMDS, который вы можете использовать здесь:Как узнать, запущен ли определенный пакетный файл, и узнать его PID?Однако я не уверен, будет ли это работать с XP.

Пример команды:CMDS /TS "Your Batch File Title"

Он также имеет графический режим для самостоятельного использования.

Вот файл справки:

Помощь сообщение

Связанный контент