1

Тема: VBS : Предотвращение повторного выполнения скрипта

Добрый день.
Точно помню, что эта (или очень похожая) тема уже поднималась, но не помню чем закончилась, и возможно даже в ней не было представлено решение.
Я пытался найти её на форуме, но не нашёл, поэтому пишу, вдруг кому пригодится.

Задача : Не допустить повторное выполнение скрипта, если он уже запущен и работает.
Решение :


Set PsWMI=GetObject("winmgmts:")
Set PsProcesses=PsWMI.ExecQuery("Select * From Win32_Process Where CommandLine Like '%" & Replace(WScript.ScriptFullName, "\", "\\") & "%'")

i = 0

For Each PsProcess in PsProcesses

  i = i + 1

Next

If i <> 1 Then
  WScript.Quit
End If

P.s.
Возможно данный метод также пригодится тем, кто хочет получить PID процесса запущенного скрипта.

"Единство,- возвестил оракул наших дней: -
Быть может спаяно железом лишь и кровью"…
Но мы попробуем спаять его любовью,-
А там увидим, что прочней…    (Ф. Тютчев)       Тут хорошая справка по vbs.

2

Re: VBS : Предотвращение повторного выполнения скрипта

MikeSh пишет:

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

Подымалась, не раз, было предложено несколько решений.

MikeSh пишет:

Решение :

К сожалению, не годится, поскольку основано на предположении, что командная строка всегда будет содержать уникальный для скрипта путь. Это не так. Путь может быть абсолютным, может и не быть. Примеры:

"C:\WINDOWS\System32\CScript.exe" "E:\Песочница\0405\0001.vbs"
"C:\WINDOWS\system32\cscript.exe" 0001.vbs
"C:\WINDOWS\system32\cscript.exe" 0405\0001.vbs

3

Re: VBS : Предотвращение повторного выполнения скрипта

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

WScript.ScriptName

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

"Единство,- возвестил оракул наших дней: -
Быть может спаяно железом лишь и кровью"…
Но мы попробуем спаять его любовью,-
А там увидим, что прочней…    (Ф. Тютчев)       Тут хорошая справка по vbs.

4

Re: VBS : Предотвращение повторного выполнения скрипта

MikeSh пишет:

В конце концов, вы за меня или за волка? smile

Я за Истину !

5

Re: VBS : Предотвращение повторного выполнения скрипта

Не уверен, что это хорошее решение, но как вариант.


Option Explicit
Dim oScriptFileLocker
Set oScriptFileLocker = new cScriptFileLocker

'Проверяем состояние блокировки
if Not oScriptFileLocker.Locked Then 
    'Блокируем файл скрипта
    oScriptFileLocker.Lock
    MsgBox "Скрипт запущен !", vbInformation
Else
    'В ином случае сообщаем о том, что скрипт уже выполняется
    MsgBox "Скрипт уже выполняется !", vbExclamation
End if

Class cScriptFileLocker
    Private oFso, oTs
    Private Sub Class_Initialize()
        Set oFso = CreateObject("Scripting.FileSystemObject")
    End Sub
    'Блокировка файла
    Public Sub Lock()
        if Not isObject(oTs) Then Set oTs = oFso.OpenTextFile(WScript.ScriptFullName,1,False)
    End Sub
    'Разблокировка файла
    Sub Unlock()
        Set oTs = Nothing
    End Sub
    'Получение состояния блокировки
    Public Property Get Locked()
        On Error Resume Next
        oFso.MoveFile WScript.ScriptFullName, WScript.ScriptFullName
        'Если при попытке переместить файл произошла ошибка 70, значит файл уже открыт на чтение
        If Err.number = 70 Then 
            Locked = True
        Else
            Locked = False
        End if
    End Property
End Class
Передумал переделывать мир. Пашет и так, ну и ладно. Сделаю лучше свой !

6

Re: VBS : Предотвращение повторного выполнения скрипта

MikeSh пишет:

...
Задача : Не допустить повторное выполнение скрипта, если он уже запущен и работает.
...

MikeSh,

я расширил эту задачу:
- если скрипт НЕ запущен - запустить
- если скрипт УЖЕ запущен - то дать выбор пользователю: прекратить его выполнение или продолжить.


  Set WshShell = WScript.CreateObject("WScript.Shell")

' предохранение от повторного запуска
  Set objService = GetObject("winmgmts:{impersonationLevel=impersonate}!\\.\root\CIMV2")
      QueryText = "SELECT Name, CommandLine, ProcessID, CreationDate FROM Win32_Process WHERE " & _
                  "Name LIKE '%[cw]script.exe' AND " & _
                  "CommandLine LIKE '%[cw]script%" & WScript.ScriptName & "%'"
      Set colProc = objService.ExecQuery(QueryText, "WQL", 0)
      If (colProc.Count > 1) Then
         iRet = WshShell.Popup("ФотоАгент уже запущен. Закончить работу?", 10, "ФотоАгент", 4 + vbInformation)  '  4 - Yes - No
         if (iRet = -1) or (iRet = 7) then  '  timeout OR No
            iRet = WshShell.Popup("ФотоАгент продолжает работать.", 2, "ФотоАгент", vbInformation)
            Set objServices = Nothing
            Set WshShell = Nothing
            Set objShell = Nothing
            WScript.Quit 2
         end if
         if (iRet = 6) then  '  Yes
                ii = 0
            For Each currProc in colProc
                if (ii = 0) then
                    maxCreationDate = currProc.CreationDate
                else
                    if (currProc.CreationDate > maxCreationDate) then maxCreationDate = currProc.CreationDate
                end if
                ii = ii + 1
            Next
            
            For Each currProc in colProc
                if (currProc.CreationDate <> maxCreationDate) then currProc.Terminate()
            Next
            iRet = WshShell.Popup("ФотоАгент закончил работу.", 2, "ФотоАгент", vbInformation)
            Set objServices = Nothing
            Set WshShell = Nothing
            Set objShell = Nothing
            WScript.Quit 3
         end if
      End If

  Set objServices = Nothing

  iRet = WshShell.Popup("ФотоАгент стартовал", 2, "ФотоАгент", vbInformation)

7

Re: VBS : Предотвращение повторного выполнения скрипта

Slav, могу ошибаться, но кажется в Win 2K нет атрибута commandLine. Помню, что сталкивался с этим когда-то давно. Из-за этого запрос поиска процесса падал. Хотя даже если так, то Win 2K уже не актуально наверное.

Передумал переделывать мир. Пашет и так, ну и ладно. Сделаю лучше свой !

8

Re: VBS : Предотвращение повторного выполнения скрипта

Xameleon пишет:

Slav, могу ошибаться, но кажется в Win 2K нет атрибута commandLine.

Xameleon,

его там точно нет - я сам это проходил.
Приведенный мной скрипт работает начиная с Win XP.