Форум программистов, компьютерный форум, киберфорум
Batch (CMD/BAT)
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Эксперт WindowsАвтор FAQ
 Аватар для Dragokas
18030 / 7733 / 892
Регистрация: 25.12.2011
Сообщений: 11,502
Записей в блоге: 16

Упаковка бинарных ресурсов в батник ("CBI method" by Dragokas)

10.08.2014, 17:14. Показов 2513. Ответов 0
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Cabinet's Batch inline. "CBI method" by Dragokas

Метод предоставляет возможность встраивать бинарную информацию (любые файлы)
в качестве ресурсов BAT-файла, получая на выходе 1 комбинированный файл
с расширением BAT или CMD.
Батник затем сможет распаковать свой ресурс при необходимости его использования.

В статье представлены описание метода и программная реализация.

Описание метода

Оригинальная идея принадлежит человеку с ником: Somebody.

Она звучала так:
Можно сделать cab архив с расширением bat, а в конце - пустую строку и extrac32 /e %0.
extrac32 в винде вроде всегда есть. Побочный эффект - попытка запуска "MSCF"
(заголовок .cab).
Данный способ не подходит для случаев упаковки бинарных ресурсов различного содержания,
т.к. некоторые комбинации символов для формата CMD являются недоспустимым и
приводят к его "падению" прежде, чем BAT-файл начнет исполнение своей части кода
из конца Cabinet архива.

К счастью структура формат CAB предоставляет возможность резервирования произвольного
количества байт (начиная со смещения 0x28) для хранения цифровой подписи.

Эту область мы задействуем под свой нужны, расположив в ней основной код
и команду распаковки.

Техническая часть

Код батника будет содержать команду для распаковки себя же:
Code
1
@extrac32.exe /E /Y /L "папка, куда распаковуем" "%~f0"
/e - распаковать все
/y - без подтверждения при замене

Структура формата Cabinet архива описана в статье базы знаний: MSKB417343

Она разделена на 4 блока:
  • CFHEADER
  • CFFOLDER
  • CFFILE
  • CFDATA

Описание первого блока:

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
// Размер | имя параметра | смещене | описание параметра
 
struct CFHEADER
{
  u1  signature[4]  // 0x00 - сигнатура архива "MSCF"
  u4  reserved1     // 0x04 - зарезервировано
  u4  cbCabinet     // 0x08 - размер архива в байтах
  u4  reserved2     // 0x0С - зарезервировано
  u4  coffFiles     // 0x10 - смещение первого вхождения блока CFFILE
  u4  reserved3     // 0x14 - зарезервировано
 
  u1  versionMinor  // 0x18 - версия формата архива (minor)
  u1  versionMajor  // 0x19 - версия формата архива (major)
 
  u2  cFolders      // 0x1A - количество блоков CFFOLDER
  u2  cFiles        // 0x1C - количество блоков CFFILE
  u2  flags         /* 0x1E - флаги наличия или отсутствия зарезервированной областей
                              abReserve[], szCabinetPrev[], szDiskPrev[], szCabinetNext[], szDiskNext[]   */
  u2  setID         // 0x20 - должен быть одинаковый для всех частей составного архива
  u2  iCabinet;     // 0x22 - порядковий номер этого файла в составном архиве
  u2  cbCFHeader;   // 0x24 - (опционально) размер зарезервированной под ЭЦП области архива
 
  u1  cbCFFolder;       // 0x26 - (опционально) размер зарезервированной области каждой папки
  u1  cbCFData;         // 0x27 - (опционально) размер зарезервированной области каждого блока данных
  u1  abReserve[];      // 0x28 - (опционально) область, зарезервированная под ЭЦП (сюда будем записывать батник)
  u1  szCabinetPrev[];  // (опционально) имя предыдущего файла CAB
  u1  szDiskPrev[];     // (опционально) имя предыдущего диска
  u1  szCabinetNext[];  // (опционально) имя следующего файла CAB
  u1  szDiskNext[];     // (опционально) имя следующего диска
};
Чтобы создать скомбинированный файл, сперва нужен сам архив.
Наиболее родной способ - воспользоваться встроенной в систему утилитой makecab.
Синтаксис у нее непростой, поэтому лучше воспользоваться готовой реализацией:

Кликните здесь для просмотра всего текста

Bash
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
@echo off
SetLocal
:: Имя для CAB-архива
set "CabinetName=test.cab"
:: Путь к папке, которую упаковуем
set src=C:\Users\Alex\Desktop\gardening\gardening
 
chcp 1251 >NUL
For /F "delims=" %%a in ('dir /B /a-d "%src%\*.*"') do echo "%src%\%%a">>"%Temp%\list.txt"
chcp 866 >NUL
 
set .=
set .=%.% /D FolderSizeThreshold=50000000
set .=%.% /D DestinationDir=.
set .=%.% /D MaxDiskSize=0
set .=%.% /D cabinet=on
set .=%.% /D compression=on
set .=%.% /D CabinetDir=\.
set .=%.% /D CabinetNameTemplate="%CabinetName%"
set .=%.% /D CabinetName="%CabinetName%"
set .=%.% /D InfFileName=NUL
set .=%.% /D RptFileName=NUL
set .=%.% /D CompressionMemory=21
set .=%.% /D DiskDirectoryTemplate=.
set .=%.% /D UniqueFiles=Off
set .=%.% /D CompressionType=LZX
 
makecab %.% /V1 /F "%Temp%\list.txt"
 
del /F "%Temp%\list.txt"
pause


Тем не менее, у Microsoft есть и другая утилита из состава Resource Kit
под названием CabArc.

Ввел в YANDEX слово Cabarc и получил "Сфинкс". Круто! M$ отдыхает
Создать архив CAB можно такой простой командой:
Code
1
cabarc N test.cab *.*
Упакует все файлы в текущей папке в архив test.cab

Чтобы вставить код Batch в такой архив, нам нужно зарезервировать область
соответствующего размера, и здесь Cabarc будет как нельзя кстати.

Описание возможностей Cabarc


Синтаксис:
Code
1
CABARC [опции] команда cabfile [@список] [файлы] [папка назначения\]
Основных каманды всего три:

L - просмотр
X - разархивировать
N - архивировать

Code
1
2
3
4
5
6
7
8
9
10
Опции:
  -c   подтверждать операции с файлами
  -o   во время распаковки не запрашивать подтверждения при замене
  -m   алгоритм сжатия [LZX:<15..21>|MSZIP|NONE], (по-умолчанию - MSZIP)
  -p   сохранять пути файлов (абсолютные пути не поддерживаются)
  -P   урезать указанный префикс из файлов при добавлении в архив
  -r   рекурсивно с подкаталогами при добавлени в архив (см. также -p)
  -s   зарезервировать место под цифровую подпись (например, -s 6144 резервирует 6 КБ.)
  -i   Устанавливает ID архива при создании (по-умолчанию - 0)
  -d   установить размер частей (по-умолчанию, размер не определен, т.е. создается единый архив)


Ключ -s позволяет установить произвольный размер зарезервированного под ЭЦП блока
(от 1 до 65535 байт (0xFFFF)).

Теперь смотрим, какой размер у батника, к которому мы хотим добавить ресурс.
Пусть будет 250 байт (0xFA).

Прибавляем 6 байт (ниже узнаете зачем).
250 + 6 = 256 (0x100).

Создаем архив с резервной областью в 256 байт:

Code
1
cabarc -s 256 N test.cab *.*
Принцип слияния кода батника с архивом такой:

Берем смещение архива 0x28 (блок abReserve[]).
Добавляем туда 2 переноса строки (0x0D, 0x0A, 0x0D, 0x0A) - 4 байта.

Далее вставляем сам код и еще + перенос строки (0x0D, 0x0A) - 2 байта.

4 + 2 = 6 байт, о которых мы говорили выше.

В коде батника должна быть предусмотрена команда распаковки архива из себя
и очистка сообщения о неверной команде (когда батник попытается исполнить хидер CAB-архива):

Code
1
@cls & @extrac32.exe /E /Y /L .\ "%~f0"
Комбинированный CBI-файл готов.
Нужно переименовать его расширение в CMD.

Правка упакованного батника напрямую

Также можно выделить резервную область путем правки определенных байт CAB-архива:

1. В структуре CFHEADER:

C++
1
2
3
4
  u4  cbCabinet     // 0x08 - размер архива в байтах
  u4  coffFiles     // 0x10 - смещение первого вхождения блока CFFILE
  u2  flags         // 0x1E - флаги наличия или отсутствия зарезервированной областей
  u2  cbCFHeader;   // 0x24 - (опционально) размер зарезервированной под ЭЦП области архива
flags должен содержать константу:
C++
1
#define cfhdrRESERVE_PRESENT    0x0004
cbCFHeader - для архива с флагом = 0 (нет резервных областей) имеет смещение 0x2C.

2. В каждой из структур CFFOLDER:

C++
1
u4  coffCabStart;   // смещение первого вхождения блока CFDATA для этой папки
Программная реализация

В дополнение к статье готовая программа для прикрепления к батнику ресурса из указанных файлов и/или каталогов.
Миниатюры
Упаковка бинарных ресурсов в батник ("CBI method" by Dragokas)  
Вложения
Тип файла: zip BAT.Res.Packer.zip (1.29 Мб, 92 просмотров)
8
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
10.08.2014, 17:14
Ответы с готовыми решениями:

Упаковка ресурсов
Например, у меня есть совокупность текстур, и мне надо упаковать в один файл, так чтобы при этом не сильно затруднять роботу с ними. Как...

Упаковка ресурсов проэкта и обращение к ним
Во многих играх ресурсы запаковывают в архивы разных форматов. Как создать подобный архив с ресурсами и обращатся к этим ресурсам в vb.net?

Упаковка ресурсов в exe. gcc (MinGW)
Здравствуйте. Возникла задача упаковать различного рода файлы в программу. Пробовал создавать заголовочный файл с содержимым в духе const...

0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
10.08.2014, 17:14
Помогаю со студенческими работами здесь

Сброс бита CBI (Atmel Studio 6.2)
Картинки внизу... Использую Atmel Studio 6.2 для написания программы для Avr Mega. Проэкт executable C. Увидел возможность...

sbi, cbi, sbic, sbs в подпрограммах
Доброго времени суток! Уважаемые форумчане! Есть подпрограмма, использующая инструкции sbi, cbi, sbic, sbs. Я ее хочу применить...

Graphics.SetClip Method (GraphicsPath) и Graphics.Clear Method vs Graphics.FillPath Method (System.Drawing)
У нас два способа залить форму: 1. Graphics.SetClip Method (GraphicsPath) and Graphics.Clear 2. Graphics.FillPath Method...

Почему так(комбинации бинарных и не бинарных вводов и выводов)?
#include &lt;string&gt; #include &lt;iostream&gt; #include &lt;fstream&gt; #include &lt;iomanip&gt; using namespace std; int main() { ...

Написать батник, который запустит другой батник и несколько программ после
Здравствуйте нужно написать Bat который запустит другой bat После конца работы открытого батника должны запускаться две программы...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
1
Ответ Создать тему
Новые блоги и статьи
PhpStorm 2025.3: WSL Terminal всегда стартует в ~
and_y87 14.12.2025
PhpStorm 2025. 3: WSL Terminal всегда стартует в ~ (home), игнорируя директорию проекта Симптом: После обновления до PhpStorm 2025. 3 встроенный терминал WSL открывается в домашней директории. . .
Access
VikBal 11.12.2025
Помогите пожалуйста !! Как объединить 2 одинаковые БД Access с разными данными.
Новый ноутбук
volvo 07.12.2025
Всем привет. По скидке в "черную пятницу" взял себе новый ноутбук Lenovo ThinkBook 16 G7 на Амазоне: Ryzen 5 7533HS 64 Gb DDR5 1Tb NVMe 16" Full HD Display Win11 Pro
Музыка, написанная Искусственным Интеллектом
volvo 04.12.2025
Всем привет. Некоторое время назад меня заинтересовало, что уже умеет ИИ в плане написания музыки для песен, и, собственно, исполнения этих самых песен. Стихов у нас много, уже вышли 4 книги, еще 3. . .
От async/await к виртуальным потокам в Python
IndentationError 23.11.2025
Армин Ронахер поставил под сомнение async/ await. Создатель Flask заявляет: цветные функции - провал, виртуальные потоки - решение. Не threading-динозавры, а новое поколение лёгких потоков. Откат?. . .
Поиск "дружественных имён" СОМ портов
Argus19 22.11.2025
Поиск "дружественных имён" СОМ портов На странице: https:/ / norseev. ru/ 2018/ 01/ 04/ comportlist_windows/ нашёл схожую тему. Там приведён код на С++, который показывает только имена СОМ портов, типа,. . .
Сколько Государство потратило денег на меня, обеспечивая инсулином.
Programma_Boinc 20.11.2025
Сколько Государство потратило денег на меня, обеспечивая инсулином. Вот решила сделать интересный приблизительный подсчет, сколько государство потратило на меня денег на покупку инсулинов. . . .
Ломающие изменения в C#.NStar Alpha
Etyuhibosecyu 20.11.2025
Уже можно не только тестировать, но и пользоваться C#. NStar - писать оконные приложения, содержащие надписи, кнопки, текстовые поля и даже изображения, например, моя игра "Три в ряд" написана на этом. . .
Мысли в слух
kumehtar 18.11.2025
Кстати, совсем недавно имел разговор на тему медитаций с людьми. И обнаружил, что они вообще не понимают что такое медитация и зачем она нужна. Самые базовые вещи. Для них это - когда просто люди. . .
Создание Single Page Application на фреймах
krapotkin 16.11.2025
Статья исключительно для начинающих. Подходы оригинальностью не блещут. В век Веб все очень привыкли к дизайну Single-Page-Application . Быстренько разберем подход "на фреймах". Мы делаем одну. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2025, CyberForum.ru