概要
この Win32_Process より自分自身のスクリプト名を実行しているプロセスを取得することで、多重起動を禁止できる。
コードサンプル
以下は自身と同じスクリプト名を実行しているプロセスを取得し、結果が複数だった場合にそのプロセス情報を出力するコード。
Option Explicit '自分自身が wscript.exe または cscript.exe で実行されているか確認するクエリ Dim query query = " SELECT *" & _ " FROM Win32_Process" & _ " WHERE (Caption = 'wscript.exe' OR Caption = 'cscript.exe') " & _ " AND CommandLine LIKE '%" & WScript.ScriptName & "%'" 'SWbemLocator オブジェクトを生成 With CreateObject("WbemScripting.SWbemLocator") 'ローカルPCに接続 With .ConnectServer 'クエリを実行 Dim processes Set processes = .ExecQuery(query) 'クエリの結果が2件以上あれば、同一スクリプトが実行されていると判断できる If processes.Count > 1 Then WScript.Echo "多重起動しています" 'プロセス情報を出力 Dim proc For Each proc In processes WScript.Echo "----------------------------------------" WScript.Echo "Name: " & proc.Name WScript.Echo "Caption: " & proc.Caption WScript.Echo "CommandLine: " & proc.CommandLine WScript.Echo "ProcessID: " & proc.ProcessID Next End If Set processes = Nothing End With End With
多重起動を検知した場合、次のような出力結果となる。
(上記のスクリプトを prohibition_multiple_startup_.vbs という名前で保存した。それをダブルクリックで実行後、CScript でも実行した場合)
C:\tmp\wsh>CScript prohibition_multiple_startup_.vbs 多重起動しています ---------------------------------------- Name: wscript.exe Caption: wscript.exe CommandLine: "C:\WINDOWS\System32\WScript.exe" "C:\tmp\wsh\prohibition_multiple_startup_.vbs" ProcessID: 36048 ---------------------------------------- Name: cscript.exe Caption: cscript.exe CommandLine: CScript prohibition_multiple_startup_.vbs ProcessID: 16796
多重起動を禁止するには、クエリの実行結果が2件以上だったときに、メッセージを表示してスクリプトを終了させれば良いだろう。
'クエリの結果が2件以上あれば、同一スクリプトが実行されていると判断できる If processes.Count > 1 Then WScript.Echo "すでに実行されているため終了します。" WScript.Quit 1 End If
関数化
汎用的に使えるよう関数化しておく。
引数 piScriptName には自分自身のスクリプト名を指定する。
すでに実行されているなら True が、そうでないなら False が返ります。
''' ''' 指定されたスクリプト名が実行されているか判定します。 ''' 実行中なら True を、そうでないなら False を返します。 ''' Function IsRunning (ByVal piScriptName) '戻り値初期化 IsRunning = False '自分自身が wscript.exe または cscript.exe で実行されているか確認するクエリ Dim query query = " SELECT *" & _ " FROM Win32_Process" & _ " WHERE (Caption = 'wscript.exe' OR Caption = 'cscript.exe') " & _ " AND CommandLine LIKE '%" & piScriptName & "%'" 'SWbemLocator オブジェクトを生成 With CreateObject("WbemScripting.SWbemLocator") 'ローカルPCに接続 With .ConnectServer 'クエリを実行 Dim processes Set processes = .ExecQuery(query) 'クエリの結果が2件以上あれば、同一スクリプトが実行されていると判断できる If processes.Count > 1 Then IsRunning = True End If Set processes = Nothing End With End With End Function
課題
短時間に複数実行したら、すべて「実行中」と検知されてしまった。
(今回はエクスプローラからEnterキーを連続して叩いた)
ExecQuery でプロセス情報を取得する前に複数起動してしまうと、このようになるらしい。
両方実行されるよりはマシだが、いずれ改善したい。