Что нового

[Файловая система] Создание SFX - архивов

joiner

Модератор
Локальный модератор
Сообщения
3 254
Репутация
552
AutoIt: 3.3.12.0

Категория:Автоматизация

Описание: Это не готовая программа, не проект. Это пример, как можно создавать свои SFX-архивы, используя библиотеку 7zip

Первый код это sfx-модуль (SFX.au3). компилируется первым.этот код распаковывает наш архив (то есть , самого себя)
Код/Пример:
SFX.au3
Код:
#NoTrayIcon
#include <7ZipN.au3>
#include <WindowsConstants.au3>
Opt("GUIOnEventMode", 1)
Local $PathRes = FileSelectFolder('', '')
If @error Then Exit
Local $7zip = @TempDir & '\7-zip32.dll'
FileInstall('7-zip32.dll', $7zip, 1)
If @error Then Exit
Local $hDLL_7ZIP = DllOpen($7zip)
If $hDLL_7ZIP = -1 Then Exit
Local $title = StringRegExpReplace(@ScriptFullPath, '.*\\', '')
Global $Unpack = GUICreate("Распаковка - " & $title, 573, 140, -1, -1, $WS_CAPTION)
Global $Progress1 = GUICtrlCreateProgress(16, 90, 542, 17)
Global $Button1 = GUICtrlCreateButton("Отмена", 485, 115, 70, 17)
GUICtrlSetOnEvent(-1, '_Exit')
$Label1 = GUICtrlCreateLabel("Общий размер (байт)", 16, 16, 120, 17)
Global $Label2 = GUICtrlCreateLabel("", 16, 32, 120, 17)
Global $Label3 = GUICtrlCreateLabel("", 16, 60, 540, 17)
$Label4 = GUICtrlCreateLabel("Распаковано (байт)", 200, 16, 120, 17)
Global $Label5 = GUICtrlCreateLabel("", 200, 32, 120, 17)
GUISetState(@SW_SHOW)
Global $iWriteSize, $iPercent = 0, $szFileName, $SizeArc
_7ZipSetOwnerWindowEx($hDLL_7ZIP, $Unpack, "_ARCHIVERPROC")
_7ZIPExtractEx($hDLL_7ZIP, $Unpack, _Encoding_ANSIToOEM(@ScriptFullPath), _Encoding_ANSIToOEM($PathRes), 1)
DllClose($hDLL_7ZIP)
Exit

While 1
	Sleep(100)
WEnd

Func _ARCHIVERPROC($hWnd, $Msg, $nState, $ExInfo)
	If $nState = 1 Then
		Local $EXTRACTINGINFO = DllStructCreate($tagEXTRACTINGINFO, $ExInfo)
		$szFileName = StringRegExpReplace(DllStructGetData($EXTRACTINGINFO, "szSourceFileName"), '.*\\', '')
		GUICtrlSetData($Label3, $szFileName)
		$iWriteSize = DllStructGetData($EXTRACTINGINFO, "dwWriteSize")
		$SizeArc = DllStructGetData($EXTRACTINGINFO, "dwFileSize")
		GUICtrlSetData($Label5, $iWriteSize)
		GUICtrlSetData($Label2, $SizeArc)
		$iPercent = Int($iWriteSize / $SizeArc * 100)
		GUICtrlSetData($Progress1, $iPercent)
		Return 1
	EndIf
	If $nState = 2 Then GUICtrlSetData($Progress1, 100)
	Return 1
EndFunc   ;==>_ARCHIVERPROC

Func _Exit()
	Exit
EndFunc   ;==>_Exit

Func _Encoding_ANSIToOEM($strText)
	Local $sBuffer = DllStructCreate("char[" & StringLen($strText) + 1 & "]")
	Local $aRet = DllCall("User32.dll", "int", "CharToOem", "str", $strText, "ptr", DllStructGetPtr($sBuffer))
	If Not IsArray($aRet) Then Return SetError(1, 0, '')
	If $aRet[0] = 0 Then Return SetError(2, $aRet[0], '')
	Return DllStructGetData($sBuffer, 1)
EndFunc   ;==>_Encoding_ANSIToOEM

Второй код это "архиватор" (SFXCreate.au3). компилируется вторым. он создает SFX-архив.
Код/Пример:
SFXCreate.au3
Код:
#NoTrayIcon
#include <7ZipN.au3>
#include <GUIConstantsEx.au3>
#include <EditConstants.au3>
Global $hDLL_7ZIP = 0, $sizefolder, $PathRes
Global $SFX = GUICreate("Создать SFX - файл", 532, 220, -1, -1)
$Progress1 = GUICtrlCreateProgress(16, 152, 502, 17)
Global $Label1 = GUICtrlCreateLabel("", 16, 120, 502, 20)
$Checkbox1 = GUICtrlCreateCheckbox("Стандартное", 16, 16, 97, 17)
$Checkbox2 = GUICtrlCreateCheckbox("Максимальное", 16, 48, 97, 17)
$Label2 = GUICtrlCreateLabel("Общий объем (байт)", 150, 16, 110, 17)
Global $Label3 = GUICtrlCreateLabel("", 150, 48, 110, 17)
$Input = GUICtrlCreateInput("Путь к папке для архивации -------------------->", 16, 88, 442, 17, $ES_READONLY)
$Button1 = GUICtrlCreateButton("........", 475, 88, 43, 17)
$Label5 = GUICtrlCreateLabel("Обработано (байт)", 280, 16, 110, 17)
Global $Label6 = GUICtrlCreateLabel("", 280, 48, 110, 17)
$Button2 = GUICtrlCreateButton("Старт", 16, 184, 75, 17)
$Button3 = GUICtrlCreateButton("Отмена", 445, 184, 75, 17)
GUISetState(@SW_SHOW)

While 1
	$nMsg = GUIGetMsg()
	Switch $nMsg
		Case $GUI_EVENT_CLOSE
			Exit
		Case $Checkbox1
			GUICtrlSetState($Checkbox2, $GUI_UNCHECKED)
		Case $Checkbox2
			GUICtrlSetState($Checkbox1, $GUI_UNCHECKED)
		Case $Button1
			$PathRes = FileSelectFolder('', '', 4, '', $SFX)
			If Not @error Then GUICtrlSetData($Input, $PathRes)
		Case $Button2
			Local $iRatio = 0
			If $PathRes <> '' Then
				If GUICtrlRead($Checkbox1) = 1 Then
					$iRatio = 5
				ElseIf GUICtrlRead($Checkbox2) = 1 Then
					$iRatio = 9
				EndIf
				_CreateSFX($PathRes, @DesktopDir, $iRatio)
				Exit
			EndIf
		Case $Button3
			Exit
	EndSwitch
WEnd

Func _CreateSFX($sPath, $dPath = @DesktopDir, $iRatio = 0)
	GUIRegisterMsg(0x0111, 'WM_COMMAND')
	Global $TmpArc = @TempDir & '\_CreateSFX.bin'
	Global $7zip = @TempDir & '\7-zip32.dll'
	FileInstall('7-zip32.dll', $7zip, 1)
	If @error Then Return
	$hDLL_7ZIP = DllOpen($7zip)
	If $hDLL_7ZIP = -1 Then Return
	FileDelete($TmpArc)
	$sizefolder = DirGetSize($sPath)
	GUICtrlSetData($Label3, $sizefolder)
	GUICtrlSetData($Label1, 'Составление списка файлов')
	Global $iWriteSize, $iPercent = 0, $szFileName
	_7ZipSetOwnerWindowEx($hDLL_7ZIP, $SFX, "_ARCHIVERPROC")
	_7ZipAdd($hDLL_7ZIP, $SFX, $TmpArc, _Encoding_ANSIToOEM($sPath), 1, $iRatio, 2)
	If @error > 0 Then
		_7ZipKillOwnerWindowEx($hDLL_7ZIP, $SFX)
		DllClose($hDLL_7ZIP)
		GUICtrlSetData($Progress1, '')
		Return
	EndIf
	_7ZipKillOwnerWindowEx($hDLL_7ZIP, $SFX)
	DllClose($hDLL_7ZIP)
	GUICtrlSetData($Progress1, '')
	Local $fname = StringRegExpReplace($sPath, '.*\\', '')
	GUICtrlSetData($Label1, 'Собираю SFX')
	FileInstall('SFX.exe', $dPath & '\' & $fname & '.exe', 1)
	Local $sizetmp = FileGetSize($TmpArc)
	Local $fo = FileOpen($dPath & '\' & $fname & '.exe', 17)
	Local $fotmp = FileOpen($TmpArc, 16), $perc, $allread
	While 1
		$frs = FileRead($fotmp, 4096)
		If @error = -1 Then ExitLoop
		$allread += @extended
		FileWrite($fo, $frs)
		$perc = Int($allread / $sizetmp * 100)
		GUICtrlSetData($Progress1, $perc)
	WEnd
	FileClose($fo)
	FileClose($fotmp)
	FileDelete($TmpArc)
	FileDelete($7zip)
EndFunc   ;==>_CreateSFX

Func _ARCHIVERPROC($hWnd, $Msg, $nState, $ExInfo)
	If $nState = 1 Then
		Local $PACKINGINFO = DllStructCreate($tagINDIVIDUALINFO, $ExInfo)
		$szFileName = StringRegExpReplace(DllStructGetData($PACKINGINFO, "szFileName"), '.*\\', '')
		GUICtrlSetData($Label1, $szFileName)
		$iWriteSize = DllStructGetData($PACKINGINFO, "dwCompressedSize")
		GUICtrlSetData($Label6, $iWriteSize)
		$iPercent = Int($iWriteSize / $sizefolder * 100)
		GUICtrlSetData($Progress1, $iPercent)
		Return 1
	EndIf
	If $nState = 2 Then GUICtrlSetData($Progress1, 100)
	Return 1
EndFunc   ;==>_ARCHIVERPROC

Func _Encoding_ANSIToOEM($strText)
	Local $sBuffer = DllStructCreate("char[" & StringLen($strText) + 1 & "]")
	Local $aRet = DllCall("User32.dll", "int", "CharToOem", "str", $strText, "ptr", DllStructGetPtr($sBuffer))
	If Not IsArray($aRet) Then Return SetError(1, 0, '')
	If $aRet[0] = 0 Then Return SetError(2, $aRet[0], '')
	Return DllStructGetData($sBuffer, 1)
EndFunc   ;==>_Encoding_ANSIToOEM

Func WM_COMMAND($hWnd, $Msg, $wParam, $lParam)
	Local $nNotifyCode = BitShift($wParam, 16)
	Local $nID = BitAND($wParam, 0xFFFF)
	Switch $nNotifyCode
		Case 0
			Switch $nID
				Case $Button3
					FileDelete($TmpArc)
					Exit
			EndSwitch
	EndSwitch
	Return 'GUI_RUNDEFMSG'
EndFunc   ;==>WM_COMMAND

Можно выбрать два режима сжатия. Если не выбран ни один, то будет создан архив без сжатия
В данном примере используется только путь к папке для сжатия
Готовый SFX-архив появится на рабочем столе
По ссылке все недостающие детали для компиляции

Файл: Исходники + EXE
Внизу скрины окон упаковщика и распаковщика
Источник: autoit-script.ru
Автор(ы): joiner
 

Вложения

madmasles

Модератор
Глобальный модератор
Сообщения
7 790
Репутация
2 319
joiner,
Режим сжатия, ИМХО, через Radio-кнопку удобнее выбирать.
 

gora

Знающий
Сообщения
315
Репутация
19
joiner [?]
Это не готовая программа, не проект. Это пример, как можно создавать свои SFX-архивы, используя библиотеку 7zip
А для чего все это? Какова конечная цель? Где все это может пригодиться?
 
Автор
joiner

joiner

Модератор
Локальный модератор
Сообщения
3 254
Репутация
552
создание своего модуля sfx. в модуле можно учесть и распаковку куда надо и то, что надо. можно сделать как инсталятор программы.
где это может пригодиться - решает каждый сам. я сразу обозначил что это пример.
как и пример записи в один файл с последующей распаковкой всего или по выбору Упаковка файлов в один исполняемый файл
был проект - писал установщик модов для WoT. управляемый установщик без использования других программ-инсталяторов. в некоторых случаях я хочу сам руководить процессом распаковки а не доверять это стороннему SFX
 

sims

Осваивающий
Сообщения
184
Репутация
24
По моему, метр для распаковщика это много. Лучше его переписать на какой-то компилируемый язык, создающий файлы поменьше.
 
Верх