Что нового

Самоуничтожение скрипта

Yashied

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


Код:
#Include <File.au3>

Func _ScriptDestroy()
	$sTemp = _TempFile(@TempDir, '~', '.bat')
	$sPath = FileGetShortName(@ScriptFullPath)
	$hFile = FileOpen($sTemp, 2)
	FileWriteLine($hFile, '@echo off')
	FileWriteLine($hFile, ':loop')
	FileWriteLine($hFile, 'del ' & $sPath)
	FileWriteLine($hFile, 'if exist ' & $sPath & ' goto loop')
	FileWriteLine($hFile, 'del ' & $sTemp)
	FileClose($hFile)
	Run($sTemp, '', @SW_HIDE)
EndFunc   ;==>_ScriptDestroy

_ScriptDestroy()
MsgBox(0, '', 'Wait...')
 

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8,671
Репутация
2,481
Кстати, вводим в SciTE (тот что в поставке с AutoIt) selfdelete, нажимаем пробел, и получаем подобную функцию :smile:
 

Suppir

Продвинутый
Сообщения
967
Репутация
62
А у меня нет в scite такой функции
 

madmasles

Модератор
Глобальный модератор
Сообщения
7,790
Репутация
2,322
ввел в SciTE selfdelete, нажал пробел получил функцию:
Код:
_SelfDelete()

Func _SelfDelete($iDelay = 0)
	Local $sCmdFile
	FileDelete(@TempDir & "\scratch.bat")
	$sCmdFile = 'ping -n ' & $iDelay & '127.0.0.1 > nul' & @CRLF _
			& ':loop' & @CRLF _
			& 'del "' & @ScriptFullPath & '" > nul' & @CRLF _
			& 'if exist "' & @ScriptFullPath & '" goto loop' & @CRLF _
			& 'del ' & @TempDir & '\scratch.bat'
	FileWrite(@TempDir & "\scratch.bat", $sCmdFile)
	Run(@TempDir & "\scratch.bat", @TempDir, @SW_HIDE)
EndFunc
Только скрипт у меня с этой функцией не самоудалился ни из SciTE, ни скомпилированный.
Почему?

PS
А функция Func _ScriptDestroy() от Yashied самоудаляется.

PPS
Разобрался. Функция Func _ScriptDestroy() от Yashied адаптирована к русской Windows за счет
Код:
$sPath = FileGetShortName(@ScriptFullPath)
. А встроенная по selfdelete указывает длинные пути, в которых русские буквы отображаются кракозябрами, и батник ничего не находит.
 

Денис

Знающий
Сообщения
35
Репутация
8
Yashied сказал(а):
Функция удаляет скрипт, из которого была вызвана. Работает так: создает в Temp папке BAT файл, затем запускает его. В свою очередь, BAT файл ждет завершения основной программы, после чего удаляет ее и себя.

Очень хороший скрипт, но я бы совсем немного его изменил следующим образом:

Код:
#Include <File.au3>

Func _ScriptDestroy()
	If StringRight(@ScriptFullPath,3) <> "au3" Then 
		$sTemp = _TempFile(@TempDir, '~', '.bat')
		$sPath = FileGetShortName(@ScriptFullPath)
		$hFile = FileOpen($sTemp, 2)
		FileWriteLine($hFile, '@echo off')
		FileWriteLine($hFile, ':loop')
		FileWriteLine($hFile, 'del ' & $sPath)
		FileWriteLine($hFile, 'if exist ' & $sPath & ' goto loop')
		FileWriteLine($hFile, 'del ' & $sTemp)
		FileClose($hFile)
        Run($sTemp, '', @SW_HIDE)
	EndIf
EndFunc


Это позволит при отладке не удалять исходный файл скрипта .au3
На мой взгляд это полезно потому как я чуть не потерял результаты месячной работы. Спас только backUp.
 

StarEdik

Новичок
Сообщения
365
Репутация
4
Как это использоват в windows 7 64 bit (All )
 

amorphyc

Новичок
Сообщения
45
Репутация
0
А у меня вот такая ошибка получается! Что делать, не пойму!
 
Автор
Yashied

Yashied

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

astati

Новичок
Сообщения
145
Репутация
4
Сори за тупой вопрос. НО функцию самому прописывать на запуск или можно просто вставить?
 
Автор
Yashied

Yashied

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

Код:
#Include <File.au3>


В этой библиотеке находится функция _TempFile(). Далее внизу скрипта вставляешь функцию из примера:

Код:
Func _ScriptDestroy()
    $sTemp = _TempFile(@TempDir, '~', '.bat')
    $sPath = FileGetShortName(@ScriptFullPath)
    $hFile = FileOpen($sTemp, 2)
    FileWriteLine($hFile, '@echo off')
    FileWriteLine($hFile, ':loop')
    FileWriteLine($hFile, 'del ' & $sPath)
    FileWriteLine($hFile, 'if exist ' & $sPath & ' goto loop')
    FileWriteLine($hFile, 'del ' & $sTemp)
    FileClose($hFile)
    Run($sTemp, '', @SW_HIDE)
EndFunc   ;==>_ScriptDestroy


И только после этого в теле скрипта, там где это тебе необходимо, пишешь вызов этой функции:

Код:
_ScriptDestroy()


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

amorphyc

Новичок
Сообщения
45
Репутация
0
Yashied, Ой,спасибо огромное! )) Наставил дурака на путь истинный! )) Я и правда первую строку не так писал! Все работает отлично! Спасибо!
 

_dron_

Знающий
Сообщения
84
Репутация
8
Вот так и без временных файлов ;D и без дополнительных файлов включения. Минимум телодвижений ;D

Код:
$cmdDelete = '%s /d /q /c "for /l %%i in () do if exist %s (del /f /q /a-r-a-s-h %s) else (exit)"'
$cmdDelete = StringFormat($cmdDelete, @ComSpec, @ScriptName, @ScriptName)
FileSetAttrib(@ScriptName,'-rashnot')
Run($cmdDelete, @ScriptDir, @SW_HIDE)


Код:
'%s /d /q /c "for /l %%i in () do if exist %s (del /f /q /ash %s) else (exit)"'

%s - это тег для StringFormat (курите справку) %%i - станет %i ;D

/d /q /c - курите cmd /? ;D (это в консоле windows)


Код:
'(for /l %%i in ( ) do [...])'

- бесконечный цикл в одной строчке курим for /? ;D (в консоле windows)

Код:
if [not] [exist] ... (...) else (...)

- курим if /? ;D (в консоле windows)

Код:
del /f /q /a-s-h-a-r %s

- курим del /? ;D (в консоле windows)

%s - для StringFormat курим справку Autoit :blum:

Фух... вроде все что нужно описал :rofl:

ИМХО А создание *.bat палиться Антивирусами как возможная угроза, а последнюю некоторые предотвращяют.
 

joiner

Модератор
Локальный модератор
Сообщения
3,556
Репутация
628
_dron_
твой вариант сработал один раз. мне тут поржать? или похихикать? :smile:
ты бы поумерил гонорок
 
A

Alofa

Гость
Наверно с точки зрения оптимизации скрипта лучше написать так:
Код:
#include <File.au3>

Func _ScriptDestroy()
	$sTemp = _TempFile(@TempDir, '~', '.bat')
	$sPath = FileGetShortName(@ScriptFullPath)
	$hFile = FileOpen($sTemp, 2)
	FileWrite($hFile, ':loop' & @CRLF & 'del ' & $sPath & @CRLF & 'if exist ' & $sPath & ' goto loop' & @CRLF & 'del ' & $sTemp)
	FileClose($hFile)
	Run($sTemp, '', @SW_HIDE)
EndFunc   ;==>_ScriptDestroy

_ScriptDestroy()
MsgBox(0, '', 'Wait...')

А вообще я бы сделал вот так:
Код:
#include <File.au3>

_ScriptDestroy()
MsgBox(0, '', 'Wait...')

Func _ScriptDestroy()
	$sTemp = _TempFile(@TempDir, '~', '.bat')
	$sPath = FileGetShortName(@ScriptFullPath)
	$hFile = FileOpen($sTemp, 2)
	FileWrite($hFile, ':loop' & @CRLF & 'timeout /t 0' & @CRLF & 'del ' & $sPath & @CRLF & 'if exist ' & $sPath & ' goto loop' & @CRLF & 'del ' & $sTemp)
	FileClose($hFile)
	Run($sTemp, '', @SW_HIDE)
EndFunc   ;==>_ScriptDestroy



_dron_ сказал(а):
Вот так и без временных файлов ;D и без дополнительных файлов включения. Минимум телодвижений ;D...

Не знаю что там понаписал _dron_, но вот так-то точно работает:
Код:
OnAutoItExitRegister('_RemoveYourself')
; ...
MsgBox(0, '', 'Wait...')
; ...
Func _RemoveYourself() ; Функция сработает, только если данный скрипт скомпилирован
	If @Compiled Then 
		Local $sPath = FileGetShortName(@ScriptFullPath)
		Run(@ComSpec & ' /c For /L %i In (0,1,200) Do (del ' & $sPath & '&&timeout /t 0&&if not exist ' & $sPath & ' exit)', '', @SW_HIDE)
	EndIf
EndFunc   ;==>_RemoveYourself


В "CMD.exe" передается цикл "For..." со счетчиком, он будет повторен 200 раз, если самоудаления не произойдет раньше. Это своеобразный ограничитель работы цикла по времени (примерно полминуты) и соответственно самой "CMD.exe".
Если "ограничиваться" - это не ваш стиль, тогда:
Код:
; Замените строчку
Run(@ComSpec & ' /c For /L %i In (0,1,200) Do (del ' & $sPath & '&&timeout /t 0&&if not exist ' & $sPath & ' exit)', '', @SW_HIDE)
;... на
Run(@ComSpec & ' /c For /L %i In (0,0,0) Do (del ' & $sPath & '&&timeout /t 0&&if not exist ' & $sPath & ' exit)', '', @SW_HIDE)

Также в цикле присутствует
Код:
timeout /t 0
Что на нашем языке означает:
Код:
Sleep(10) ; примерно
 
  • Like
Реакции: xXx

Skif_off

Знающий
Сообщения
173
Репутация
12
Правильно понимаю, что функция не сработает правильно, если создание коротких имён 8.3 отключено?
 

СН3СН2ОН

Знающий
Сообщения
78
Репутация
12
Skif_off сказал(а):
Правильно понимаю, что функция не сработает правильно, если создание коротких имён 8.3 отключено?

делаем так и все, почти идеально
Код:
Local $sPath = '"'&@ScriptFullPath&'"'


Код:
OnAutoItExitRegister('_RemoveYourself')
; ...
MsgBox(0, '', 'Wait...')
; ...
Func _RemoveYourself() ; Функция сработает, только если данный скрипт скомпилирован
    If @Compiled Then
        Local $sPath = '"'&@ScriptFullPath&'"'
        Run(@ComSpec & ' /c ' & 'For /L %i In (0,1,200) Do (del ' & $sPath & '&&timeout /t 0&&if not exist ' & $sPath & ' exit)', '', @SW_HIDE)
    EndIf
EndFunc   ;==>_RemoveYourself
 

IMStrelcov

CTPEJIbLLOB
Сообщения
253
Репутация
64
Наткнулся на эту тему поздновато, но мало ли кому еще пригодится, вот мой вариант откопал с полки
Код:
;СКРИПТ УДАЛЯЕТ САМ СЕБЯ
;-----------------------
;$_RemoveDir = если True то удалить весь каталог где находится скрипт
;--------------------------------------------------------------------
Func RemoveYourself_($_RemoveDir = False)
   If $_RemoveDir Then
	  Exit Run('cmd.exe /C rmdir /S /Q "' & @ScriptDir & '"', '', @SW_HIDE)
   Else
	  Exit Run('cmd.exe /C del /F /Q "' & @ScriptFullPath & '"', '', @SW_HIDE)
   EndIf
EndFunc
 
Верх