如何判斷我的批次檔是否正在運行?

如何判斷我的批次檔是否正在運行?

我有一個從 AT 命令運行的批次腳本,並且可能會運行多次。當它啟動時,我需要它來檢測它是否已經在運行,如果是,請立即退出(第二個)。

  1. 它必須是健壯的,並且能夠處理腳本意外退出的情況(即我無法在入口處設置標誌並在退出時清除它)
  2. 它必須在遠端桌面會話中運行
  3. 我被困在 XPshell v2 的 XP 上,但如果我不能在批次/powershell 或 vbs 中做到這一點,不介意寫一些 exe
  4. 腳本必須最小化運行,因此我使用 Start "NAME" /MIN %COMSPEC% /C "MyScript.bat" 啟動它
  5. 其他cmd視窗可能會打開,所以我需要檢查正在運行的腳本
  6. 批次腳本以 SYSTEM 使用者身分執行,但我無法使用任何 WMI

我使用 PowerShell Get-Process 來查看 MainWindowTitle,但是當遠端連接到電腦時這不起作用,因為腳本可能正在運行,但未顯示在此遠端連線實例中。在這種情況下,Get-Process 可以看到 cmd 進程,但 MainWindowTitle 為空。

我嘗試過 Get-Process 並查看了擴展的 StartInfo.EnvironmentVariables 屬性,但無法了解如何建立環境變數以使其出現在屬性中。

我想過在啟動命令中使用/WAIT,那麼AT將保持開啟狀態直到完成,但是包含AT的腳本沒有最小化

有任何想法嗎?

答案1

我相信鎖定檔案是最簡單可靠的解決方案。訣竅是確保正在運行的批次進程在檔案上保持獨佔寫入鎖定,直到其終止。該系統的優點在於,無論批次因何種原因終止,Windows 都會釋放鎖定。

一旦有了鎖定文件,您就需要一種方法來檢測該文件目前是否已鎖定。我描述瞭如何做到這一點如何在命令列中檢查給定檔案或目錄是否被鎖定(由任何進程使用)?

我使用了這種原始但有效的技術來透過 Windows 批次完成一些相當複雜的任務:

您不清楚批次檔駐留在何處 - 遠端計算機還是本機計算機,或者您是否可能同時在多台計算機上運行腳本,但每台計算機只有一個活動進程。

如果批次腳本位於遠端電腦上,並且您的進程具有對該腳本的寫入存取權限,那麼您可以使用批次檔本身作為鎖定檔案!您只需呼叫 :subroutine,同時使用追加模式將未使用的檔案句柄重新導向至批次腳本。如果另一個程序已經擁有鎖,則 CALL 將會失敗。當腳本終止時(無論它如何終止),鎖都會自動釋放。

腳本文件

@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,正如我之前所說,我無法使用 WMI。
  2. 為了確定已啟動腳本的 PID,我列出了所有目前的 cmd PID,啟動腳本,然後列出所有 cmd PID,尋找先前不存在的 PID。

答案3

我創建了一個名為 CMDS 的自動化插件,您可以在此處使用:我如何查看某個批次檔是否正在運行並取得 PID?不過我不確定這是否適用於 XP。

命令範例:CMDS /TS "Your Batch File Title"

它還有一個可供自己使用的 GUI 模式。

這是幫助文件:

幫助訊息

相關內容