Что нового

[Новая функция] Запись в саму себя

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8,673
Репутация
2,486
VitAl2013 [?]
почему сам скрипт.exe такого не может?
Его нужно научить это делать. На офф. форуме кстати есть пример самоуничтожения скрипта (на данный момент форум в офлайне), где используется изменённая в памяти версия самого скрипта (скомпилированного естественно). Может эту концепцию можно использовать в целях данной темы.
 

NoMad73rus

Продвинутый
Сообщения
124
Репутация
80
Очень классная идея!! Очень думаю многим пригодится, но предложенные здесь варианты сложны и не удобны в использовании (
 

aleratorio

Осваивающий
Сообщения
85
Репутация
43
Наткнулся тут на форуме на эту тему, думаю не поздно может предложить свой вариант (если кто нибудь еще помнит о чем в ней говорилось :smile:)...

Идея такова:
Зачем использовать архиваторы, компиляторы, заново пересобирать исполняемый файл, если можно просто дописывать в нужные данные в конец исполняемого файла? (т.к. это никак не влияет на работу основного кода, который находится в начале)

Как это работает:
1) Запущенная программа копирует себя во временный каталог, запускает свою копию из временного каталога (при этом передает временной копии указание, что она временная и путь на основной исполняемый файл) и завершает работу.
2) Запущенная временная копия делает необходимую работу, дописывает в конец основного исполняемого файла различные данные. В конце работы запускает основной исполняемый файл с указанием удалить временный.
3) Запускается основной исполняемый файл, удаляет временный и завершает работу.

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

Вот пример с добавлением введенных пользователем данных в исполняемый файл, как будто это обычный ini-файл(скрипт необходимо скомпилировать):
Код:
#include <ButtonConstants.au3>
#include <GUIConstantsEx.au3>
#include <GUIListBox.au3>
#include <WindowsConstants.au3>

If Not @Compiled Then
	MsgBox(0, '', 'Для работы необходимо скомпилировать скрипт!')
	Exit
EndIf

$tempFullPath = @TempDir & '\' & @ScriptName

If $CmdLine[0] = 0 Then  ;если исполняемый файл запущен без параметров, то копируем его во временную папку, запускаем из временной папки и завершаем работу
	FileCopy(@ScriptFullPath, $tempFullPath, 9)
	Run($tempFullPath & ' -work_in_temp "' & @ScriptFullPath & '"') ;передаем во временный файл путь до основного исполняемого файла
	Exit
ElseIf StringCompare($CmdLine[1], '-delete_temp') = 0 Then ;если в качестве первого параметра идет -delete_temp, значит надо удалить временный файл
	ProcessWaitClose(Number($CmdLine[2])) ;ждем пока временный файл не закончит работу (Во втором параметре передан PID процесса временного файла)
	FileDelete($tempFullPath)
	Exit
ElseIf StringCompare($CmdLine[1], '-work_in_temp') <> 0 Then ;если в качестве первого параметра не идет -work_in_temp, завершаем работу
	Exit
EndIf

;иначе запускается временный исполняемый файл
$mainFileFullPath = $CmdLine[2]  ;путь к основному файлу

#Region ### START Koda GUI section ### Form=
$Form1 = GUICreate("Users:", 321, 226, 192, 124)
$List1 = GUICtrlCreateList("", 0, 0, 319, 175)
$Button_AddUser = GUICtrlCreateButton("Add User", 50, 189, 75, 25)
$Button_RemoveUser = GUICtrlCreateButton("Remove User", 181, 189, 75, 25)
GUISetState(@SW_SHOW)
#EndRegion ### END Koda GUI section ###

$asUsers = IniReadSection($CmdLine[2], 'Users')
If Not @error Then
	For $i = 1 to UBound($asUsers, 1) - 1
		_GUICtrlListBox_AddString($List1, $asUsers[$i][1])
	Next
EndIf

While 1
	$nMsg = GUIGetMsg()
	Switch $nMsg
		Case $GUI_EVENT_CLOSE
			ExitLoop

		Case $Button_AddUser
			$user = InputBox('Enter User Name', '', '')
			If $user <> '' Then
				IniWrite($mainFileFullPath, 'Users', $user, $user) ;записываем данные в основной исполняемый файл - как будто это обычный ini-файл
				_GUICtrlListBox_AddString($List1, $user)
			EndIf
		Case $Button_RemoveUser
			$i = _GUICtrlListBox_GetCurSel($List1)
			$user = _GUICtrlListBox_GetText($List1, $i)
			IniDelete($mainFileFullPath, 'Users', $user)
			_GUICtrlListBox_DeleteString($List1, $i)
	EndSwitch
WEnd

If StringCompare($CmdLine[1], '-work_in_temp') = 0 Then ;если работал временный файл, то запускаем основной с указанием удалить временный
		Run($mainFileFullPath & ' -delete_temp ' & @AutoItPID) ;вторым параметром передаем PID текущего процесса, для того что бы основной
																; исполняемый файл перед удалением временного - дождался его завершения
EndIf
Exit
После добавления данных можно открыть файл программы в редакторе и увидеть что введенные данные находятся в конце файла, после основного кода

В принципе аналогично можно добавлять различные изображения и другие данные. Только вместо IniRead/IniWrite придется написать свои функции, которые дописывают данные в исполняемый файл...

Типа:
1. Основной код программы
2. Маркер ресурса (например [Bitmap1])
3. Данные ресурса
4. Маркер ресурса (например [Sound1])
5. Данные ресурса
и т.п. ..........................................
 

Garrett

Модератор
Локальный модератор
Сообщения
3,999
Репутация
967
aleratorio
К сожалению этот способ не нов. ;) Он мне уже встречался на просторах интернета, на другом форуме посвящённом программированию на Си.
 

aleratorio

Осваивающий
Сообщения
85
Репутация
43
Garrett сказал(а):
aleratorio
К сожалению этот способ не нов. ;) Он мне уже встречался на просторах интернета, на другом форуме посвящённом программированию на Си.

Жаль, я думал, что стал первооткрывателем :-[ Просто тут, в теме, было столько заморочек со всякими архиваторами/компиляторами...

Ну пусть останется, мало ли кому пригодиться пример на AutoIt, из тех, кто не программирует на Си и не посещает соответствующие форумы...
 
Верх