Создание CAB-архива

Тема в разделе "Пакетные файлы CMD, BAT", создана пользователем Dragokas, 4 фев 2014.

  1. Dragokas
    Онлайн

    Dragokas Very kind Developer Команда форума Супер-Модератор Разработчик Клуб переводчиков

    Сообщения:
    4.473
    Симпатии:
    4.303
    Создание CAB-архива через командную строку
    (в т.ч. самораспаковующихся EXE), а также распаковка CAB.

    Автор: Alex Averchenkoff
    Код (DOS):
    @echo **************************************************
    @echo ((((((((((((((((((((((((((((((((((((((((((((((((((
    @echo Name: CabMaker.exe
    @echo Description: A program for creating cab archives
    @echo Version: v. 1.0.0.0
    @echo Copyright: @[USER=8310]Alex[/USER] Averchenkoff
    @echo Create: 2011
    @echo ))))))))))))))))))))))))))))))))))))))))))))))))))
    @echo **************************************************

    @echo off

    set SaveName=""

    rem ******************************************************

    rem СТАРТОВЫЙ БЛОК - ВЫБИРАЕМ ДЕЙСТВИЕ:ПРОСМОТР\РАСПАКОВКА\СОЗДАНИЕ АРХИВА
    rem ******************************************************
    :start
    echo.
    set /p action=VIEW-1^|EXPAND-2^|CREATE-3:
    if /i "%action%"=="1" (goto view)
    if /i "%action%"=="2" (goto extract)
    if /i "%action%"=="3" (goto create)
    exit

    rem ******************************************************

    rem ПРОСМОТР CAB АРХИВА
    rem ******************************************************
    :view
    set /p name=ENTER NAME ARCHIVE:
    if "%SaveName%"=="" ( set SaveName=%name%)
    if "%name%"=="" ( set name=%SaveName%)
    if not "%name%"=="" (expand -D %name%.cab) else ( goto view)

    if errorlevel 0 (goto action)
    if errorlevel 1 (@echo An error occurred, try again)

    rem ******************************************************

    rem РАСПАКОВКА CAB АРХИВА - ФАЙЛЫ РАСПАКОВЫВАЮТСЯ В ДИРЕКТОРИЮ ОДНОИМЕННУЮ С ИМЕНЕМ АРХИВА
    rem ******************************************************
    :extract
    set /p name=ENTER NAME ARCHIVE:
    if "%SaveName%"=="" ( set SaveName=%name%)
    if "%name%"=="" ( set name=%SaveName%)
    if not "%name%"=="" (md "%~dp0%name%" && expand %name%.cab /F:* .\%name%) else ( goto extract)


    if errorlevel 0 (@echo Archive successfully unzipped! & goto action)
    if errorlevel 1 (@echo An error occurred, try again)

    :action
    echo You want to continue or exit the program?
    set /p action=TO CONTINUE OR EXIT? [Y\N]:
    if /i "%action%"=="Y" (goto start) else exit

    rem ******************************************************

    rem СОЗДАНИЕ НОВОГО CAB АРХИВА - СОЗДАЕТСЯ В ПАПКЕ РАСПОЛОЖЕНИЯ БАТНИКА
    rem ******************************************************
    :create
    set /p name=ENTER NAME FOR ARCHIVE:
    if "%SaveName%"=="" ( set SaveName=%name%)
    if "%name%"=="" ( set name=%SaveName%)
    if "%name%"=="" ( goto create)

    rem ******************************************************

    rem БУДЕМ ЛИ СОЗДАВАТЬ РАСПАКОВЫВАЮЩИЙСЯ АРХИВ
    rem ******************************************************
    set /p sfx=CREATE SFX?[Y\N]:

    if /i "%sfx%"=="Y" (@echo Initiated the creation of self-extracting archive)
    echo.
    rem ******************************************************
    rem СОЗДАЕМ СПИСОК ФАЙЛОВ И ФАЙЛ ОТВЕТОВ ДЛЯ MAKECAB
    rem ******************************************************
    @echo .Set CabinetNameTemplate=%name%.cab>make.ddf
    @echo .Set CompressionType=MSZIP>>make.ddf
    @echo .Set MaxDiskSize=CDROM>>make.ddf
    @echo .Set ReservePerCabinetSize=6144>>make.ddf
    @echo .Set Compress=on>>make.ddf
    @echo .Set CompressionMemory=21>>make.ddf
    @echo .Set DiskDirectoryTemplate=".">>make.ddf
    @echo .Set Cabinet=ON>>make.ddf
    @echo .Set MaxCabinetSize=999999999>>make.ddf
    @echo .Set CompressionLevel=^7>>make.ddf

    rem ******************************************************

    rem СОЗДАЕМ ОБЫЧНЫЙ АРХИВ
    rem ******************************************************
    chcp 1251>nul
    FOR /R %%f IN (*.*) DO (
    If not "%%~nxf"=="make.ddf" (
    @If not "%%~nxf"=="CabMaker.bat" (@echo "%%f">>make.ddf))
    )
    makecab /F make.ddf
    if /i "%sfx%"=="Y" (goto create_sfx) else ( goto clear)

    :clear
    del setup.inf
    del setup.rpt
    del make.ddf
    chcp 866 > nul
    echo.
    echo Creating a backup is successfully completed!
    goto action


    rem ******************************************************

    rem МАГИЕЙ ПРЕВРАЩАЕМ ОБЫЧНЫЙ АРХИВ В САМРАСПАКОВЫВАЮЩИЙСЯ :-)
    rem ******************************************************
    :create_sfx
    copy /b %windir%\system32\extrac32.exe+%name%.cab %name%.exe
    del setup.inf
    del setup.rpt
    del make.ddf
    del %name%.cab
    chcp 866 > nul
    echo.
    echo Create self-extracting archive completed successfully!
    goto action
    Также перевод на VB6 от меня, созданный на основе кода от Alex Averchenkoff с правками от Dark_Timur.
    Код (vb.net):
    Option Explicit

    ' Alex Averchenkoff принадлежит оригинальный код BAT программы MakeCab.
    ' Dragokas перевел программу на язык Visual Basic 6.
    ' Dark_Timur исправил и дополнил программу.
    ' И затем Dragokas еще раз подправил :)
    ' Версия: 1.1.1

    Function CreateCab(Source As String, SourceType As String, ArchName As String, Destination As String, Compress As Boolean, _
        CompressLvl As Byte, SubFolders As Boolean, Ext As String, SFX As Boolean, Silent As Boolean) As Long

        Dim AddData As String, DDF As String

        If LCase(SourceType) = "d" Or LCase(SourceType) = "dir" Or LCase(SourceType) = "directory" Then
            AddData = GetData(Source, True, LCase(Ext), Silent)
        ElseIf LCase(SourceType) = "f" Or LCase(SourceType) = "file" Then
            AddData = """" & Source & """" & vbCrLf
        Else
            If Not Silent Then MsgBox "Неправильно задан тип исходных данных", vbCritical
            CreateCab = 272
            Exit Function
        End If

        If (Err <> 0) Then Exit Function
        DDF = GetTempFile() 'DDF будет во временной папке Windows
        CreateDDF DDF, ArchName, AddData, Destination, IIf(Compress, "ON", "OFF"), CompressLvl

        With CreateObject("WScript.Shell")

            CreateCab = .Run("makecab.exe /F """ & DDF & """", 0, True)
            If (CreateCab <> 0) Then
                If Not Silent Then MsgBox "Ошибка создания архива (" & CreateCab & ")", vbCritical
                Dim ExecObj As Object
                If Not Silent Then
                    Set ExecObj = CreateObject("WScript.Shell").Exec("cmd /c makecab.exe /F """ & DDF & """")
                    MsgBox "Ошибка создания архива (" & CreateCab & ")" & vbCrLf & ExecObj.StdOut.ReadAll(), vbCritical
                    Set ExecObj = Nothing
                End If
                Exit Function
            End If

            If SFX Then 'Превращаем обычный архив в SFX
                .Run "cmd /x /c ""copy /b """ & Environ("windir") & "\system32\extrac32.exe""+""" & _
                    Destination & "\" & ArchName & ".cab"" """ & Destination & "\" & ArchName & ".exe""""", 0, True
                Kill Destination & "\" & ArchName & ".cab"
            End If
        End With
     
        Call Clear(DDF)
        If Not Silent Then MsgBox "Готово.", vbInformation
    End Function

    Function GetData(fold As String, SubFolders As Boolean, Ext As String, Silent As Boolean) As String
        On Error Resume Next 'Пропуск папок/файлов, защищенных правами
        Dim myfiles As Object, mydirs As Object
        Dim fil As Object, dir As Object

        With CreateObject("Scripting.FileSystemObject").GetFolder(fold)
            Set myfiles = .Files
            Set mydirs = .SubFolders
        End With

        For Each fil In myfiles
            If Trim(Ext) = "*" Or Trim(Ext) = "*.*" Or Trim(Ext) = "" Or (LCase(Right(fil.Name, Len(Ext)))) = Ext Then
                GetData = GetData & """" & fil.Path & """" & vbCrLf
            End If
        Next

        If SubFolders Then
            For Each dir In mydirs
                GetData = GetData & ".Set DestinationDir=" & Chr(34) & dir.Name & Chr(34) & vbCrLf & _
                GetData(dir.Path, True, Ext, Silent) & vbCrLf
            Next
        End If

        GetData = Left(GetData, Len(GetData) - 2) 'CrLf
        Set myfiles = Nothing: Set mydirs = Nothing
    End Function

    Function GetTempFile() 'Получить временный незанятый файл
        Dim FSO As Object, FN As String
     
        Set FSO = CreateObject("Scripting.FileSystemObject")
     
        FN = FSO.GetTempName()
        FN = Environ("temp") & "\" & FN
     
        If dir(FN) <> vbNullString Then FN = GetTempFile()

        GetTempFile = FN
        Set FSO = Nothing
    End Function

    Function CreateDDF(DDF$, ArchName, GetData$, Out, SetCom As String, SetComLvl As Byte)
        Dim ff As Integer
        ff = FreeFile()

        'Подготовим DDF-файл ответов для архиватора CAB
        Open DDF For Output As #ff
     
            Print #ff, ".Set CabinetNameTemplate=" & ArchName & ".cab"
            Print #ff, ".Set CompressionType=MSZIP"
            Print #ff, ".Set MaxDiskSize=CDROM"
            Print #ff, ".Set ReservePerCabinetSize=6144"
            Print #ff, ".Set Compress=" & SetCom
            Print #ff, ".Set CompressionMemory=21"
            Print #ff, ".Set DiskDirectoryTemplate=""."""
            Print #ff, ".Set Cabinet=ON"
            Print #ff, ".Set UniqueFiles=ON"
            If LCase(SetCom) = "on" Then Print #ff, ".Set CompressionLevel=" & CStr(SetComLvl)
            Print #ff, ".Set DiskDirectory1=" & Out
            Print #ff, GetData
     
        Close #ff

    End Function

    Sub Clear(DDF$)
    On Error Resume Next
        Kill Environ("temp") & "\setup.inf"
        Kill Environ("temp") & "\setup.rpt"
        Kill DDF
    End Sub
     
    Source - путь до исходного файла/папки.

    SourceType - тип исходных данных. Значения: "d", "dir", "directory" означают, что исходными данными является папка, а Значения: "f", "file" означают, что исходными данными является файл. Регистр значения SourceType не важен. Остальные значения завершают функцию с ошибкой 272.

    ArchName - имя будущего архива без расширения. Расширение выбирается компьютером, так что смысла его вводить в ArchName нет.

    Destination - путь до папки, где будет создан архив.

    Compress - флаг, устанавливающий, использовать сжатие (True) или не использовать (False).

    CompressLvl - если используется сжатие, то устанавливает уровень сжатия. Диопазон: 1...7 включительно. При отключенном сжатии важности не представляет.

    SubFolders - если архивируется папка и там есть подпапки, то этот флаг устанавливает, архивировать подпапки (True) или не архивировать (False). При архивировании файла важности не представляет.

    Ext - если архивируется папка, то устанавливает разрешенное расширение файлов для архивирования. Файлы с неправильным расширением архивированы не будут. Если вы хотите, чтоб архивировались все файлы, то оставьте переменную пустой ("") или введите звездочку ("*" или "*.*"). Также действует и на подпапки, если они архивируются. При архивировании файла важности не представляет.

    SFX - устанавливает тип архива. Обычный архив с расширением CAB будет создан, если SFX = False. Иначе, если SFX = True, будет создан SFX (самораспаковывающийся) архив с расширением EXE.

    Silent - включает или отключает тихий режим. Если Silent = False, то на экран будут выводиться сообщения. Иначе, если Silent = True, на экран ничего выводиться не будет.
     

    Вложения:

    • CabMaker.zip
      Размер файла:
      1,4 КБ
      Просмотров:
      12
    Последнее редактирование: 5 фев 2014
    Kиpилл нравится это.
  2. Phoenix
    Оффлайн

    Phoenix Активный пользователь

    Сообщения:
    1.839
    Симпатии:
    1.829
    Код (Text):
    rem СОЗДАЕМ ОБЫЧНЫЙ АРХИВ
    rem ******************************************************
    chcp 1251>nul
    FOR /R %%f IN (*.*) DO (
    If not "%%~nxf"=="make.ddf" (
    @If not "%%~nxf"=="CabMaker.bat" (@echo "%%f">>make.ddf))
    )
    makecab /F make.ddf
    А что и где он создаст ? Даже для демо не понятно.
     
  3. Dragokas
    Онлайн

    Dragokas Very kind Developer Команда форума Супер-Модератор Разработчик Клуб переводчиков

    Сообщения:
    4.473
    Симпатии:
    4.303
    Все претензии к автору.
    Вечером постараюсь объяснить принцип работы. Если нужно - модифицировать скрипт.
     
  4. Phoenix
    Оффлайн

    Phoenix Активный пользователь

    Сообщения:
    1.839
    Симпатии:
    1.829
    Разобрался. Вот так работает (/v 1..3 - verbosity level) :cigar:
    Код (Text):
    chcp 1251>nul
    FOR /R %%f IN (*.*) DO  (
        If not "%%~nxf"=="make.ddf" (
           @If not "%%~nxf"=="CabMaker.bat" (@echo "%%f">>make.ddf))
        )
    makecab /F make.ddf /V2
    chcp 866
    Не удается найти C:\Users\..\setup.inf
    Не удается найти C:\Users\..\setup.rpt
     
  5. Dragokas
    Онлайн

    Dragokas Very kind Developer Команда форума Супер-Модератор Разработчик Клуб переводчиков

    Сообщения:
    4.473
    Симпатии:
    4.303
    С помощью CAB-архиватора можно вытягивать информацию о версии файла и CRC32.

    Получение сведений о версии файла и CRC32 нативными средствами [через makecab]

    Способ найден на просторах Интернета.
    Мною упрощен и превращен в функцию.
    Демо:

    Код (DOS):
    @echo off
    SetLocal EnableExtensions
    :: Полный путь к файлу
    set file=h:\_CMD рус\FileVersion\Units_Compile_helper.exe

    call :GetFileInfo "%file%" "*ver*" FileVer
    echo Версия файла: %FileVer%

    call :GetFileInfo "%file%" "*vers*" ProductVer
    echo Версия продукта: %ProductVer%

    call :GetFileInfo "%file%" "*csum*" CheckSum
    echo CRC32: %CheckSum%

    call :GetFileInfo "%file%" "*lang*" Language
    echo Язык: %Language%

    pause
    exit /B

    :GetFileInfo [_in_ FullFileName] [_in_ Type of Information] [_out_ Variable, that receive a bufer]
      pushd "%~dp1" & echo "%~nx1"> "%TEMP%\file.path"
      (echo .set DoNotCopyFiles=on&echo .Set Cabinet=off&echo .Set Compress=off&echo .Set InfFileLineFormat="%~2") > "%TEMP%\cab.inf"
      makecab /d InfFileName="%TEMP%\file.inf" /d "DiskDirectory1=%TEMP%" /f "%TEMP%\cab.inf" /f "%TEMP%\file.path" /v0 >NUL
      for /f "usebackq skip=4 delims=" %%f in ("%TEMP%\file.inf") do set "%~3=%%f"
      (del /f "%TEMP%\file.inf" & del /f "%TEMP%\file.path" & del /f "%TEMP%\cab.inf") 2>NUL & popd
    exit /B
     
    Kиpилл и Phoenix нравится это.
  6. Phoenix
    Оффлайн

    Phoenix Активный пользователь

    Сообщения:
    1.839
    Симпатии:
    1.829
    Версия файла: [file list]
    Версия продукта: [file list]
    CRC32: 6a5d7b41
    Язык: [file list]
    :Dash1: Почему не показывает другую инфу ?
     
  7. Dragokas
    Онлайн

    Dragokas Very kind Developer Команда форума Супер-Модератор Разработчик Клуб переводчиков

    Сообщения:
    4.473
    Симпатии:
    4.303
    Phoenix, на каком файле проверял? У меня все показывает. А в свойствах этого файла данная инфа имеется?
     
    Phoenix нравится это.
  8. Phoenix
    Оффлайн

    Phoenix Активный пользователь

    Сообщения:
    1.839
    Симпатии:
    1.829
    Да получает - лень было на чём то другом проверить.
    Версия файла: 9.1.0.6270
    Версия продукта: 9.1.0.06270
    CRC32: 4289ebab
     

Поделиться этой страницей