Что нового

_ScriptRestart() - Надёжный перезапуск скрипта

Yashied

Модератор
Команда форума
Глобальный модератор
Сообщения
5,379
Репутация
2,724
Написал функцию для перезапуска скрипта. Функция может быть вызвана в любом месте кода. Работает так: создает в Temp папке VBS скрипт (изучаем это), затем запускает его и завершает программу. В свою очередь, VBS скрипт ждет завершения основной программы, после чего запускает ее снова и удаляет сам себя. Одно НО, название файла основной программы должно быть "уникальным", т.е. в списке процессов не должно быть таких же названий.


Код:
#Include <File.au3>

If MsgBox(36, 'Restarting...', 'Press OK to restart this script.') = 6 Then
	_ScriptRestart()
EndIf

Func _ScriptRestart()
	$sVbs = _TempFile(@TempDir, '~', '.vbs')
	$hFile = FileOpen($sVbs, 2)
	FileWriteLine($hFile, 'Set objService = GetObject("winmgmts:{impersonationLevel=impersonate}!\\.\root\CIMV2")')
	FileWriteLine($hFile, 'Set objRefresher = CreateObject("WbemScripting.SWbemRefresher")')
	FileWriteLine($hFile, 'Set colItems = objRefresher.AddEnum(objService, "Win32_Process").objectSet')
	FileWriteLine($hFile, 'Do Until False')
	FileWriteLine($hFile, '    WScript.Sleep 500')
	FileWriteLine($hFile, '    objRefresher.Refresh')
	FileWriteLine($hFile, '    Flag = True')
	FileWriteLine($hFile, '    For Each objItem in colItems')
	FileWriteLine($hFile, '        If objItem.ProcessID = ' & @AutoItPID & ' Then')
	FileWriteLine($hFile, '            Flag = False')
	FileWriteLine($hFile, '        End If')
	FileWriteLine($hFile, '    Next')
	FileWriteLine($hFile, '    If Flag = True Then')
	FileWriteLine($hFile, '        Exit Do')
	FileWriteLine($hFile, '    End If')
	FileWriteLine($hFile, 'Loop')
	FileWriteLine($hFile, 'Set objShell = CreateObject("WScript.Shell")')
	FileWriteLine($hFile, 'objShell.Run("' & FileGetShortName(@ScriptFullPath) & '")')
	FileWriteLine($hFile, 'Set objFSO = CreateObject("Scripting.FileSystemObject")')
	FileWriteLine($hFile, 'Set File = objFSO.GetFile("' & FileGetShortName($sVbs) & '")')
	FileWriteLine($hFile, 'File.Delete')
	FileClose($hFile)
	ShellExecute($sVbs)
	Exit
EndFunc   ;==>_ScriptRestart
 

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8,671
Репутация
2,481
Re: Перезапуск скрипта

А почему именно через vbs? Чтобы убедиться в закрытии программы?

Yashied [?]
Одно НО, название файла основной программы должно быть "уникальным", т.е. в списке процессов не должно быть таких же названий.
Это вроде можно обойти...
Добавлено:
Сообщение автоматически объединено:

Я кстати использую такой метод (пока не подводил):

Код:
;Проверяем, не запустился ли скрипт из ком. строки (чтобы скрипт не запускался вечно :) )
If Not StringInStr($CmdLineRaw, "/CmdLineRun") Then
	_Self_Restart(5) ;Через 5 секунд скрипт запустится снова
Else
	MsgBox(64, "", "Hello, this is after _Self_Restart session ;)")
EndIf

Func _Self_Restart($iTime)
	Run(@ComSpec & ' /c Ping -n ' & $iTime & ' localhost > nul & "' & @ScriptFullPath & '" /CmdLineRun', @ScriptDir, @SW_HIDE)
	Exit
EndFunc
 
Автор
Yashied

Yashied

Модератор
Команда форума
Глобальный модератор
Сообщения
5,379
Репутация
2,724
Re: Перезапуск скрипта

CreatoR сказал(а):
А почему именно через vbs? Чтобы убедиться в закрытии программы?

Да.

CreatoR сказал(а):
Это вроде можно обойти...

Буду рад услышать как это сделать?

CreatoR сказал(а):
Я кстати использую такой метод...

Тоже хорош, но смущает Ping в роли паузы.
 

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8,671
Репутация
2,481
Re: Перезапуск скрипта

[?]
Это вроде можно обойти...
Вот так:

Код:
#Include <File.au3>

If MsgBox(36, 'Restarting...', 'Press OK to restart this script.') = 6 Then
    _ScriptRestart()
EndIf

Func _ScriptRestart()
    $sVbs = _TempFile(@TempDir, '~', '.vbs')
    $hFile = FileOpen($sVbs, 2)
    
	$sRunLine = FileGetShortName(@ScriptFullPath)
	If Not @Compiled Then $sRunLine = FileGetShortName(@AutoItExe) & ' /AutoIt3ExecuteScript ' & $sRunLine
	
	FileWriteLine($hFile, 'Set objService = GetObject("winmgmts:{impersonationLevel=impersonate}!\\.\root\CIMV2")')
    FileWriteLine($hFile, 'Set objRefresher = CreateObject("WbemScripting.SWbemRefresher")')
    FileWriteLine($hFile, 'Set colItems = objRefresher.AddEnum(objService, "Win32_Process").objectSet')
    FileWriteLine($hFile, 'Do Until False')
    FileWriteLine($hFile, '    WScript.Sleep 500')
    FileWriteLine($hFile, '    objRefresher.Refresh')
    FileWriteLine($hFile, '    Flag = True')
    FileWriteLine($hFile, '    For Each objItem in colItems')
    FileWriteLine($hFile, '        If objItem.ProcessID = ' & @AutoItPID & ' Then')
    FileWriteLine($hFile, '            Flag = False')
    FileWriteLine($hFile, '            Exit For')
    FileWriteLine($hFile, '        End If')
    FileWriteLine($hFile, '    Next')
    FileWriteLine($hFile, '    If Flag = True Then Exit Do')
    FileWriteLine($hFile, 'Loop')
    FileWriteLine($hFile, 'Set objShell = CreateObject("WScript.Shell")')
    FileWriteLine($hFile, 'objShell.Run("' & $sRunLine & '")')
    FileWriteLine($hFile, 'Set objFSO = CreateObject("Scripting.FileSystemObject")')
    FileWriteLine($hFile, 'Set File = objFSO.GetFile("' & FileGetShortName($sVbs) & '")')
    FileWriteLine($hFile, 'File.Delete')
    
	FileClose($hFile)
	ShellExecute($sVbs)
    Exit
EndFunc   ;==>_ScriptRestart
 
Автор
Yashied

Yashied

Модератор
Команда форума
Глобальный модератор
Сообщения
5,379
Репутация
2,724
Re: Перезапуск скрипта

@AutoItPID - да, как же я забыл об этом! Время от времени полезно почитать справку.

:smile:

+1
 

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8,671
Репутация
2,481
Re: Перезапуск скрипта

Yashied
А почему ты не обновил часть с «If Not @Compiled Then...»? Это чтобы и нескомпилированный скрипт перезапускался, а не открывался в режиме редактирования (в SciTE) :smile:
 
Автор
Yashied

Yashied

Модератор
Команда форума
Глобальный модератор
Сообщения
5,379
Репутация
2,724
Re: Перезапуск скрипта

Обновлю, я просто изначально ставил задачу перезапускать EXE.
 

kaster

Мой Аватар, он лучший самый
Команда форума
Глобальный модератор
Сообщения
4,020
Репутация
626
Re: Перезапуск скрипта

А я вот так перезапускаю
Код:
_Restart()
Func _Restart()
	$iRestart = MsgBox(49, 'Restart?', 'If press "OK", will restart')
	If $iRestart = 1 Then
		If @Compiled Then
			Run(@ScriptFullPath)
		Else
			$hProc = @AutoItExe & ' "' & @ScriptFullpath & '"'
			Run($hProc)
		EndIf
		Exit
	EndIf
EndFunc
 

vovsla

Осваивающий
Сообщения
607
Репутация
36
Re: Перезапуск скрипта

а зачем сильно заморачиваться? можно просто вложить в онэкзит

Код:
Func OnAutoItExit()
If $Restart="True" Then
_RunDOS("start "&@ScriptName)
Return 0
EndIf

If $Restart="True" ; чтобы можно было всё таки выйти...
 

snoitaleR

AutoIT Гуру
Сообщения
855
Репутация
223
Re: Перезапуск скрипта

Скажите, а зачем вообще нужно перезагружать скрипт?
У меня ни разу такой необходимости не возникло...
 

vovsla

Осваивающий
Сообщения
607
Репутация
36
Re: Перезапуск скрипта

например остановка всех действий по горячим кнопкам, может есть метод и получше, но я что-то не смог придумать
 

kaster

Мой Аватар, он лучший самый
Команда форума
Глобальный модератор
Сообщения
4,020
Репутация
626
Re: Перезапуск скрипта

snoitaleR сказал(а):
Скажите, а зачем вообще нужно перезагружать скрипт?
У меня ни разу такой необходимости не возникло...
мой просмотрщик например после смены языка интерфейса требует перезагрузки, чтобы отобразить соответственно ;)
 

vovsla

Осваивающий
Сообщения
607
Репутация
36
Re: Перезапуск скрипта

если нужно менять названия батонов и лэйблов, то можно использовать
GUICtrlSetData
 

snoitaleR

AutoIT Гуру
Сообщения
855
Репутация
223
Re: Перезапуск скрипта

Kaster
Если тот факт, что на долю секунды оба скрипта (родительский и дочерний) оказываются запущенными одновременно, не важен, то твой метод (ответ №7) предельно прост...
Имеет ли значение, что скрипты на долю секунды оказываются запущенными одновременно?
 

kaster

Мой Аватар, он лучший самый
Команда форума
Глобальный модератор
Сообщения
4,020
Репутация
626
Re: Перезапуск скрипта

snoitaleR
Долго вникал в твой вопрос, но все же не смог.
Постараюсь ответить исходя из предположения - не важно запущены ли два экземпляра одного и того же скрипта одновременно, т.к. "родительский" после того как запустил "дочерний" неминуемо закроется, не ожидая каких-либо действий со стороны интерпретатора или "дочернего" процесса.
 

vovsla

Осваивающий
Сообщения
607
Репутация
36
Re: Перезапуск скрипта

кстати в 7 ответе можно
Код:
If @Compiled Then
    Run(@ScriptFullPath)
Else
    $hProc = @AutoItExe & ' "' & @ScriptFullpath & '"'
    Run($hProc)
EndIf

заменить одной строчкой _RunDOS("start "&@ScriptName) :smile:
 

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8,671
Репутация
2,481
Re: Перезапуск скрипта

Vovsla [?]
а зачем сильно заморачиваться? можно просто вложить в онэкзит
Ну и кому нужен перезапуск на выходе?

[?]
заменить одной строчкой _RunDOS("start "&@ScriptName)
А зачем, тут же ещё нужно подключать библиотеку... тем более встроенными средствами надёжнее.
 

snoitaleR

AutoIT Гуру
Сообщения
855
Репутация
223
Re: Перезапуск скрипта

Kaster
А для чего тогда Yashied и CreatoR таким "навороченным" способом пытались убедиться, что "родительский" скрипт завершил работу?

Vovsla
Такой способ хорош, если зарегистрировано расширение au3...
У меня не зарегистрировано, потому что autoit не установлен стандартным способом... :smile:
 

kaster

Мой Аватар, он лучший самый
Команда форума
Глобальный модератор
Сообщения
4,020
Репутация
626
Re: Перезапуск скрипта

snoitaleR сказал(а):
Kaster
А для чего тогда Yashied и CreatoR таким "навороченным" способом пытались убедиться, что "родительский" скрипт завершил работу?
мне льстит что вопрос адресован мне, относительно действий таких гуру как Yashied и CreatoR ;D
но, к сожалению, я не знаю. лучше всего спросить у них :ok:


Добавлено:
Сообщение автоматически объединено:

Vovsla сказал(а):
кстати в 7 ответе можно
If @Compiled Then
Run(@ScriptFullPath)
Else
$hProc = @AutoItExe & ' "' & @ScriptFullpath & '"'
Run($hProc)
EndIf
заменить одной строчкой _RunDOS("start "&@ScriptName) :smile:
это можно заменить одной строкой и без привлечения дополнительной либы
Код:
Run(@AutoItExe & ' "' & @ScriptFullpath & '"')
 

vovsla

Осваивающий
Сообщения
607
Репутация
36
Re: Перезапуск скрипта

CreatoR сказал(а):
Vovsla [?]
а зачем сильно заморачиваться? можно просто вложить в онэкзит
Ну и кому нужен перезапуск на выходе?

[?]
заменить одной строчкой _RunDOS("start "&@ScriptName)
А зачем, тут же ещё нужно подключать библиотеку... тем более встроенными средствами надёжнее.

не на выходе, если хотим выйти, то $Restart="False" или переменная просто объявлена, изначально я же предлагал:
Код:
Func OnAutoItExit()
If $Restart="True" Then
_RunDOS("start "&@ScriptName)
Return 0
EndIf

If $Restart="True" ; чтобы можно было всё таки выйти...



Добавлено:
Сообщение автоматически объединено:

а почему вы так неохотно пользуетесь дополнительными библиотеками?
 
Верх