Решил опубликовать исходный код C# для работы с форматом конфигураций 1С: Предприятие.
https://github.com/elisy/MdInternals
MdInternals понимает формат cf, cfu, epf, erf, распаковывает содержимое в удобочитаемые Xml и текстовые файлы и загружает обратно. Позволяет программно обращаться к внутренним файлам и свойствам объектов.
Проект состоит из частей:
- MdInternals программно обращается к объектам и свойствам конфигурации
- CfProject отвечает за сериализацию и десериализацию объектов MdInternals
- MdInternals.Cil декомпилирует байт-код (OpCode) 1С
- MdInternals.Serialization работает с внутренним полу-JSON форматом 1С вида "{ 19 { "", 2 } }"
Выгрузка файлов cf, cfu, epf, erf на диск
var cf = new CfPackage();
//или var cf = new EpfPackage();
//или var cf = new ErfPackage();
//или var cf = new CfuPackage();
cf.Open(@"D:config.cf");
var project = new CfProject();
project.Save(epf, @"D:ConfigXmlConfig.cfproj", ProjectType.Xml);
Распознанные файлы записываются в дерево каталогов по видам объектов. Нераспознанные помещаются в каталог Unresolved:
Распознанные файлы выгружаются в XML-формате. Формат XML позволяет контролировать логическую целостность файлов и обрабатывать файлы сторонними программами. Известные свойства перемещаются в соответствующие разделы (атрибуты или тэги) XML-структуры:
Чтение из MSSQL-таблицы
var image = ImageReader.ReadImageFromConfig(@"data source=192.168.1.2SQL2005;user=login;pwd=password;database=Database1C");
Обращение к внутренним файлам
var mp = new EpfPackage();
mp.Open(file);
var root = mp.MetadataObjects.Where(m => m.ImageRow.FileName == "root").FirstOrDefault();
var rp = new RootPointer(root.ImageRow);
var part = mp.MetadataObjects.Where(m => m.ImageRow.FileName == rp.MetadataPackageFileName.ToString()).FirstOrDefault();
Создание файла из выгруженного xml-формата
var project = new CfProject();
var mp = project.Load(@"D:ConfigXmlConfig.cfproj");
mp.Save(@"D:config.cf");
Описание Cf-Формата
Cf-файл состоит из заголовка образа (ImageHeader) и следующими за ним страницами (ImagePage1-ImagePageN). Заголовок образа состоит из 4х байт сигнатуры, которая равна 0xFF 0xFF 0xFF 0x7F, 4х байт размера страницы и 8 зарезервированных байт. После заголовка файла идут по порядку страницы с данными. Каждая предыдущая страница ссылается на последующую.
Каждая страница (ImagePage) состоит из заголовка страницы (ImagePageHeader), группы указателей на записи ImageRowPointers и области ImageRows.
Заголовок страницы ImagePageHeader содержит в себе: зарезервированные 2 байта 0x0D 0x0A, 27 байт текстовой информации и еще зарезервированные 2 байта 0x0D 0x0A. Текстовая информация содержит 3 шестнадцатеричных числа: общий размер данных всех страниц (FullSize), размер текущей страницы (PageSize) и адрес следующей страницы в файле (NextPageAddress). FullSize проставляется только для первой страницы цепочки страниц. Для остальных страниц цепочки это значение 0. Для последней страницы цепочки NextPageAddress принимается равным 0xFF 0xFF 0xFF 0x7F.
Блок указателей ImageRowPointers занимает размер, указанный в значении PageSize страницы. Каждый указатель состоит из 4х байт адреса заголовка HeaderAddress и 4х байт адреса тела BodyAddress. В конце каждого указателя помещается сигнатура 0xFF 0xFF 0xFF 0x7F. Адреса указывают на расположения внутри текущей страницы на область ImageRows.
Заголовок ImageRowHeader начинается с блока заголовка страницы ImagePageHeader, который сообщает, сколько байт отведено под заголовок. Далее идут 20 зарезервированных байт, UTF-16 строка идентификатора данных (Id) и 4 зарезервированных байт.
Тело ImageRowBody начинается с блока заголовка страницы ImagePageHeader, который сообщает, сколько байт отведено под тело данных. Если тело данных начинается на 0xEF 0xBB 0xBF (сигнатура UTF8), то тело содержит UTF-8 строку. Иначе тело данных содержит упакованные данные. Если распакованные данные начинаются на 0xFF 0xFF 0xFF 0x7F, то содержимое – последовательность объектов, и они записаны в CF-формате. Иначе содержимое – это строка сериализации.
Что не реализовано
- Утилита распознает только объекты конфигурации 1го уровня, помещая по подкаталогам. Не распознает остальное: формы, макеты, помещая в каталог Unresolved
- В каталоге Unresolved не распаковываются составные объекты с расширением img
- MdInternals распознает ограниченное числа свойств объектов
Автор: Elisy