Что нового

Удаление папки @ScriptDir

madmasles

Модератор
Глобальный модератор
Сообщения
7,790
Репутация
2,322
Этот код опасный. Просто так его лучше не запускать.
Делаю деинсталлятор программы. Так как в папке программы находится зарегистрированная 678.dll, то деинсталлирую в 2 этапа. Первый - удаление ярлыков, ключей реестра и прописывание в автозагрузку второго этапа. Второй, после перезагрузки, - удаление самой папки программы с содержимым. Проблема во втором этапе. Вот он:
Код:
#include <File.au3>

RegDelete("HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Run", "Finish.exe")
FileDelete(@ScriptDir & "\123.bat")
FileDelete(@ScriptDir & "\234.bat")
FileDelete(@ScriptDir & "\345.htm")
FileDelete(@ScriptDir & "\456.exe")
FileDelete(@ScriptDir & "\567.url")
FileDelete(@ScriptDir & "\678.dll")
FileDelete(@ScriptDir & "\789.ini")
FileSetAttrib(@ScriptDir, "-RASHNOT", 1)
DirRemove(@ScriptDir, 1)
_ScriptDestroy()
Sleep(1000)


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

Все файлы удаляются, но сама папка @ScriptDir (она в Program Files) не удаляется, а остается пустой.
При этом, если просто создать папку и запустить из нее скрипт, то папка удаляется из любого места.
Помогите, пожалуйста, решить эту проблему и удалить эту папку.
Спасибо.

PS
Я был не совсем прав. Папка удаляется из любого места, если запустить не скомпилированный скрипт, а, если скрипт скомпилирован в .exe, то папка не удаляется, а остается пустой.
 

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8,671
Репутация
2,481
Код:
#include <File.au3>

RegDelete("HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Run", "Finish.exe")

_SelfUninstall()

Func _SelfUninstall()
    FileSetAttrib(@ScriptDir, "-RASHNOT", 1)
    $sTemp = _TempFile(@TempDir, '~', '.bat')
    $sPath = FileGetShortName(@ScriptDir)
    $hFile = FileOpen($sTemp, 2)
    FileWriteLine($hFile, '@echo off')
    FileWriteLine($hFile, ':loop')
    FileWriteLine($hFile, 'rd /s /q ' & $sPath)
    FileWriteLine($hFile, 'if exist ' & $sPath & ' goto loop')
    FileWriteLine($hFile, 'del ' & $sTemp)
    FileClose($hFile)
    Run($sTemp, '', @SW_HIDE)
EndFunc
 

Yashied

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

Не совсем верно, может случиться так, что папку нельзя будет удалить без перезагрузки системы. В этом случае скрипт просто зависнет...
 
Автор
madmasles

madmasles

Модератор
Глобальный модератор
Сообщения
7,790
Репутация
2,322
CreatoR
Yashied
Спасибо Вам за советы и с наступающим Вас Новым годом.
Получилось удалить так: В первом этапе деинсталлляции (удаление ярлыков, ключей реестра и прописывание в автозагрузку второго этапа) добавил запись пути @ScriptDir в файл.ini, перемещение в Application Data этого файл.ini и самоудаляющегося Finish.exe (т.е. второй этап после перезагрузки. Не в Temp, так как у меня, например, перед выключением компьютера Temp очищается) Так удаляет. 1-ый этап:
Код:
#NoTrayIcon
#include <File.au3>

$iMsgBoxAnswer = MsgBox(36, "My Proga", "Вы действительно хотите удалить" & @CRLF & _
		"       программу My Proga?")
If $iMsgBoxAnswer = 7 Then Exit

IniWrite(@ScriptDir & "\Deinstall.ini", "Deinstall", "key", @ScriptDir)
RegDelete("HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\My Proga")
RegDelete("HKEY_LOCAL_MACHINE\SOFTWARE\My Proga")
DirRemove(@ProgramsDir & "\Утилиты\My Proga", 1)
FileDelete(@DesktopDir & "\My Proga.lnk")
FileDelete(@AppDataDir & "\Microsoft\Internet Explorer\Quick Launch\My Proga.lnk")
FileMove(@ScriptDir & "\Finish.exe", @AppDataDir & "\Finish.exe")
FileMove(@ScriptDir & "\Deinstall.ini", @AppDataDir & "\Deinstall.ini")
RegWrite("HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Run", "Finish.exe", _
		"REG_SZ", @AppDataDir & "\Finish.exe")
_ScriptDestroy()
MsgBox(64, "msmEraser", "Программа My Proga" & @CRLF & "         удалена." & @CRLF & _
		"Папка  " & @ScriptDir & @CRLF & " будет удалена после" & @CRLF & "     перезагрузки.", 5)


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
. 2-ой этап:
Код:
#include <File.au3>

RegDelete("HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Run", "Finish.exe")
$vPath = IniRead(@ScriptDir & "\Deinstall.ini", "Deinstall", "key", "NotFound")
DirRemove($vPath, 1)
FileDelete(@ScriptDir & "\Deinstall.ini")
_ScriptDestroy()
Sleep(1000)


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
.
С вариантом CreatoR-а буду пробовать - он проще.



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

CreatoR,
Yashied был прав. С Вашим вариантом папка остается пустой, а в процессах висит процесс cmd. При этом, пока процесс cmd не убьешь, эту папку не удалить.
 

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8,671
Репутация
2,481
Yashied [?]
может случиться так, что папку нельзя будет удалить без перезагрузки системы. В этом случае скрипт просто зависнет...
Зависание можно исправить (поставиить ограничение на ожидание), ну а хендл папки можно закрыть, например используя OpenedFilesView (сам exe'шник весит всего 40 kb), типа такого:

Код:
#include <File.au3>

_SelfUninstall()

Func _SelfUninstall()
	RunWait(@ScriptDir & '\OpenedFilesView.exe /closefolder "' & @ScriptDir & '"', @ScriptDir, @SW_HIDE)
	
	$sTemp = _TempFile(@TempDir, '~', '.bat')
	$sPath = FileGetShortName(@ScriptDir)
	
	$sBat_Data = _
		'@Echo Off' & @CRLF & _
		'Set Counter=0' & @CRLF & _
		':Loop' & @CRLF & _
		'RD /S /Q ' & $sPath & @CRLF & _
		'Ping -n 1 LocalHost > Nul' & @CRLF & _
		'Set /A Counter=%Counter%+1' & @CRLF & _
		'If Counter==10 GoTo Del' & @CRLF & _
		'If Exist ' & $sPath & ' GoTo Loop' & @CRLF & _
		':Del' & @CRLF & _
		'Del ' & $sTemp & @CRLF & _
	
	$hFile = FileOpen($sTemp, 2)
	FileWrite($hFile, $sBat_Data)
	FileClose($hFile)
	
	Run($sTemp, '', @SW_HIDE)
EndFunc
 
Автор
madmasles

madmasles

Модератор
Глобальный модератор
Сообщения
7,790
Репутация
2,322
CreatoR, а чем Вам не нравится мой вариант с перемещением. Он четко отрабатывает и не требует посторонних утилит.
Может быть в моем варианте есть какие-то ошибки, но, при моем поверхностном знакомстве с AutoIt-ом, я их не вижу. В чем я не прав?
 

Yashied

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

madmasles

Для удаления папки, тебе нужно добавить в функцию _ScriptDestroy() всего лишь две строчки, а точнее одну (другую добавил CreatoR) - FileChangeDir(). Я даже выше намекнул про это. Windows не даст удалить папку, пока она является текущей для приложения, т.е используется.

Код:
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, 'rd /q /s ' & FileGetShortName(@ScriptDir))
    FileWriteLine($hFile, 'del ' & $sTemp)
    FileClose($hFile)
    FileChangeDir(@TempDir)
    Run($sTemp, '', @SW_HIDE)
EndFunc   ;==>_ScriptDestroy



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

А вообще-то для скриптов такого рода нужно писать БОЛЬШИМИ КРАСНЫМИ БУКВАМИ предупреждение, что бы народ случайно не запустил этот код, так, интереса ради.

:smile:
 
Автор
madmasles

madmasles

Модератор
Глобальный модератор
Сообщения
7,790
Репутация
2,322
CreatoR.
1. В Вашем коде:
Код:
#include <File.au3>

_SelfUninstall()

Func _SelfUninstall()
    RunWait(@ScriptDir & '\OpenedFilesView.exe /closefolder "' & @ScriptDir & '"', @ScriptDir, @SW_HIDE)
    
    $sTemp = _TempFile(@TempDir, '~', '.bat')
    $sPath = FileGetShortName(@ScriptDir)
    
    $sBat_Data = _
        '@Echo Off' & @CRLF & _
        'Set Counter=0' & @CRLF & _
        ':Loop' & @CRLF & _
        'RD /S /Q ' & $sPath & @CRLF & _
        'Ping -n 1 LocalHost > Nul' & @CRLF & _
        'Set /A Counter=%Counter%+1' & @CRLF & _
        'If Counter==10 GoTo Del' & @CRLF & _
        'If Exist ' & $sPath & ' GoTo Loop' & @CRLF & _
        ':Del' & @CRLF & _
        'Del ' & $sTemp & @CRLF & _
    
    $hFile = FileOpen($sTemp, 2)
    FileWrite($hFile, $sBat_Data)
    FileClose($hFile)
    
    Run($sTemp, '', @SW_HIDE)
EndFunc
- закралась ошибка. Должно быть:
Код:
#include <File.au3>

_SelfUninstall()

Func _SelfUninstall()
    RunWait(@ScriptDir & '\OpenedFilesView.exe /closefolder "' & @ScriptDir & '"', @ScriptDir, @SW_HIDE)
    
    $sTemp = _TempFile(@TempDir, '~', '.bat')
    $sPath = FileGetShortName(@ScriptDir)
    
    $sBat_Data = _
        '@Echo Off' & @CRLF & _
        'Set Counter=0' & @CRLF & _
        ':Loop' & @CRLF & _
        'RD /S /Q ' & $sPath & @CRLF & _
        'Ping -n 1 LocalHost > Nul' & @CRLF & _
        'Set /A Counter=%Counter%+1' & @CRLF & _
        'If Counter==10 GoTo Del' & @CRLF & _
        'If Exist ' & $sPath & ' GoTo Loop' & @CRLF & _
        ':Del' & @CRLF & _
        'Del ' & $sTemp
    
    $hFile = FileOpen($sTemp, 2)
    FileWrite($hFile, $sBat_Data)
    FileClose($hFile)
    
    Run($sTemp, '', @SW_HIDE)
EndFunc
.
2. Если Ваш скрипт запускать без перезагрузки, то он отрабатывает, но папка не удаляется, а в процессах висят cmd.exe и ping.exe (в своем вопросе про .dll я писал, то есть папка под процессом) и временный батник не удаляется.
Если делать в два этапа (с перезагрузкой), то отрабатывает, но:
В моем варианте 604 кб (1-ый деинсталлятор - 302 кб, 2-ой деинсталлятор - 301 кб и файл.ini - 1 кб). В вашем варианте 643 кб (302 кб, 301 кб + 40 кб - OpenedFilesView.exe). В принципе, мелочь.

И еще раз спрашиваю, ответьте, пожалуйста, есть ли в моем варианте ошибки?

Yashied.
Пока я готовил свой ответ, появилось Ваше сообщение.
Отпишусь после экспериментов.


PS
Программа, к которой я пытаюсь сделать деинсталятор находится здесь: http://www.s-melnikov.net/pg007.html
 

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8,671
Репутация
2,481
madmasles [?]
есть ли в моем варианте ошибки?
Я не могу его протестировать, и если честно не очень горю желанием. Но с виду вроде всё нормально.

Свои примеры я тоже не тестировал, накидал всё с головы, и это только как идея, не больше.

Вариант от Yashied видимо самый оптимальный, опять же, я не тестировал, но с виду так должно быть, оно логичнее :smile:
 
Автор
madmasles

madmasles

Модератор
Глобальный модератор
Сообщения
7,790
Репутация
2,322
Yashied,
Я протестировал Ваш вариант и он оказался самым оптимальным. Не надо никаких перемещений, никаких лишних .ini файлов.
Большое Вам спасибо.
Только я не понял, что делает функция FileChangeDir. К сожалению, в русской справке очень лаконичное описание, а с английским я не дружу.

Yashied,
CreatoR,

Еще раз большое Вам спасибо и, еще раз, с наступающим Новым годом.

PS
В английской справке описание функции FileChangeDir такое же лаконичное, как и в русской. Тут, похоже, надо азы изучать...
 

Yashied

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

Код:
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, 'rd /q /s ' & FileGetShortName(@ScriptDir))
    FileWriteLine($hFile, 'del ' & $sTemp)
    FileClose($hFile)
    Run($sTemp, @TempDir, @SW_HIDE)
EndFunc   ;==>_ScriptDestroy
 
Автор
madmasles

madmasles

Модератор
Глобальный модератор
Сообщения
7,790
Репутация
2,322
Yashied,
Я протестировал Ваш последний вариант. Он отлично удаляет.
Спасибо.
 

ArsMaxim

Новичок
Сообщения
1
Репутация
0
Подскажите пожалуйста...

Как этим скриптом удалить отдельно лежащие папки?
Одна папка в %CommonDocuments%, другая в %CommonAppData% и сама программа в ProgramFiles...
Собственно задумка такая:
1. один скрипт встроить в инсталлятор программы, удаляющий после установки программы сам инсталлятор.
2. второй скрипт удалял установленную программу, после её запуска и проверки функциональности программы, (как бы демонстрация программы).

За раннее благодарю!
 
Верх