Опыты с автоматическим переводом кода C# в 1С-код через Roslyn




Принцип обмена данными из 1С с сайтом (на MySQL) и выдачи (публикации) этих данных по запросу.
PHP-Скрипт автоматической загрузки данных из файла данных в формате CSV в базу данных сайта работающего на WordPress.

В продолжение моей темы: 1С:Альфа-Авто Автосалон Автосервис: обмен с сайтом.
С помощью данного скрипта можно загружать в автоматическом режиме, по расписанию, данные сервисных книжек (ремонтов авто) из 1С:Альфа-Авто Автосалон Автосервис.
Также можно загружать данные в ручном режиме: для этого делается скрытая страница, где размещается специальная кнопка.
Комментарии размещенные внутри скрипта разъяснят логику и порядок действия.
Комментарии с "/////    echo" использовались для отладки.
Дополнительно создана таблица для журналирования результатов загрузки данных.
Скрипт включает в себя защиту от SQL инъекций (думаю безопасность соблюдена в полной мере).
В кратце:
1. Пишется скрипт, который запускает этот.
2. Создается регламентное задание в WordPress, по которому запускается скрипт из п.1. 
3. Этот скрипт осуществляет проверку на существование файла обмена в папке.
4. Если данные не новые, загрузка не производится.
5. Если данные новые, очищается таблица сервисных книжек.
6. Загружаются новые данные.

Собственно сам скрипт:

<?php // Полная загрузка сервисных книжек, создан 2024-01-05 12:44:55

global $wpdb2;
global $failure;
global $file_hist;

/////  echo '<H2><b>Старт загрузки</b></H2><br>';

$failure=FALSE;
//подключаемся к базе
$wpdb2 = include_once 'connection.php'; ; // подключаемся к MySQL
// если не удалось подключиться, и нужно оборвать PHP с сообщением об этой ошибке
if (!empty($wpdb2->error))
{
/////   echo '<H2><b>Ошибка подключения к БД, завершение.</b></H2><br>';
$failure=TRUE;
wp_die( $wpdb2->error );
}

$m_size_file=0;
$m_mtime_file=0;
$m_comment='';
/////проверка существования файлов выгрузки из 1С
////файл выгрузки сервисных книжек
$file_hist = ABSPATH.'/_1c_alfa_exchange/AA_hist.csv';
if (!file_exists($file_hist))
{
/////   echo '<H2><b>Файл обмена с сервисными книжками не существует.</b></H2><br>';
$m_comment='Файл обмена с сервисными книжками не существует';
$failure=TRUE;
}

/////инициируем таблицу лога
/////если не существует файла то возврат и ничего не делаем
if ($failure){
///включает защиту от SQL инъекций и данные можно передавать как есть, например: $_GET['foo']
/////   echo '<H2><b>Попытка вставить запись в лог таблицу</b></H2><br>';
$insert_fail_zapros=$wpdb2->insert('vin_logs', array('time_stamp'=>time(),'last_mtime_upload'=>$m_mtime_file,'last_size_upload'=>$m_size_file,'comment'=>$m_comment));
wp_die();
/////    echo '<H2><b>Возврат в начало.</b></H2><br>';
return $failure;
}
/////проверка лога загрузки, что бы не загружать тоже самое
$masiv_data_file=stat($file_hist);   ////передаем в массив свойство файла
$m_size_file=$masiv_data_file[7];    ////получаем размер файла
$m_mtime_file=$masiv_data_file[9];   ////получаем дату модификации файла
////создаем запрос на получение последней удачной загрузки
////выбираем по штампу времени создания (редактирования) файла загрузки AA_hist.csv, $m_mtime_file

/////   echo '<H2><b>Размер файла: '.$m_size_file.'</b></H2><br>';
/////   echo '<H2><b>Штамп времени файла: '.$m_mtime_file.'</b></H2><br>';
/////   echo '<H2><b>Формирование запроса на выборку из лога</b></H2><br>';
////препарируем запрос
$text_zaprosa=$wpdb2->prepare("SELECT * FROM `vin_logs` WHERE `last_mtime_upload` = %s", $m_mtime_file);
$results=$wpdb2->get_results($text_zaprosa);

if ($results)
{   foreach ( $results as $r)
{
////если штамп времени и размер файла совпадают, возврат
if (($r->last_mtime_upload==$m_mtime_file) && ($r->last_size_upload==$m_size_file))
{////echo '<H2><b>Возврат в начало, т.к. найдена запись в логе.</b></H2><br>';
$insert_fail_zapros=$wpdb2->insert('vin_logs', array('time_stamp'=>time(),'last_mtime_upload'=>$m_mtime_file,'last_size_upload'=>$m_size_file,'comment'=>'Загрузка отменена, новых данных нет, т.к. найдена запись в логе.'));
wp_die();
return $failure;
}
}
}
////если данные новые, пишем в лог запись о начале загрузки
/////echo '<H2><b>Попытка вставить запись о начале загрузки в лог таблицу</b></H2><br>';
$insert_fail_zapros=$wpdb2->insert('vin_logs', array('time_stamp'=>time(),'last_mtime_upload'=>0, 'last_size_upload'=>$m_size_file, 'comment'=>'Начало загрузки'));

////очищаем таблицу
$clear_tbl_zap=$wpdb2->prepare("TRUNCATE TABLE %s", 'vin_history');
$clear_tbl_zap_repl=str_replace("'","`",$clear_tbl_zap);
$results=$wpdb2->query($clear_tbl_zap_repl);
/////   echo '<H2><b>Очистка таблицы сервисных книжек</b></H2><br>';
if (empty($results))
{
/////   echo '<H2><b>Ошибка очистки таблицы книжек, завершение.</b></H2><br>';
//// если очистка не удалась, возврат
$failure=TRUE;
wp_die();
return $failure;
}

////загружаем данные
$table='vin_history';         // Имя таблицы для импорта
//$file_hist Имя CSV файла, откуда берется информация     // (путь от корня web-сервера)
$delim=';';          // Разделитель полей в CSV файле
$enclosed='"';      // Кавычки для содержимого полей
$escaped='\

13 Comments

  1. cool.vlad4

    Elisy +1, но увы не прочитал толком код. Есть же gist в конце концов. Можно было туда код поместить. (не упущу случай похвалить microsoft, в целом они очень радуют в последнее время, бесплатная Visual Studio 2013 Community Edition, планы по выкладыванию в open source Core .Net Framework и т.п. Странно почему изначально Roslyn не сделали и пилили бы на нем все)

    Reply
  2. Elisy

    (1) cool.vlad4,

    Код не особо интересен. Главное, что его можно скопировать к себе, если возникнет необходимость.

    Reply
  3. Elisy

    Изначально статья была опубликована на Хабре:

    http://habrahabr.ru/post/245453/

    Reply
  4. matytsin_new

    Интересно, но сложно придумать обоснованное коммерческое применение.

    Мой личный опыт интеграции 1с и C# убедил меня в том, что код C# не стоит пытаться транслировать в код 1с. Реализация классов C# не может быть сымитирована в 1с полностью. Полноценного ООП нет. Контроля типов нет. Самодокументирования нет. Код выполняется иначе. После долгих переборов различных способов интеграции .net и 1с я для себя выбрал вариант, когда исходный код модулей на C# тем или иным способом формируется в коде 1с. Затем? с помощью System.Reflection, создается динамическая сборка, содержащая все необходимые модули и эта сборка подгружается как Com-объект. После чего, можно работать с этим объектом в синтаксисе любого .net языка. Способ не идеальный, поскольку COM-соединения иногда ведут себя непредсказуемо (например при разрыве COM-соединения) и дорогой по времени инициализации. Однако это единственный способ, позволяющий на лету формировать свои классы, соответствующие неким уже существующим интерфейсам и разделить разработку кода C# и кода 1c между разными исполнителями с наименьшим риском. Думаю,что использовать интеграцию 1с и .NET на простых классах (без сложной логики внутри классов .net) имеет смысл только для наработки навыков сопряжения вышеозначенных технологий, поскольку простые задачи надежнее решать средствами самой 1с.

    Reply
  5. Elisy

    (4) matytsin_new,

    До коммерческого использования далеко. Скорее пока академический интерес в новогодние каникулы. Продолжение опубликовал только что на Хабре. Суть сводится к тому, что теоретически на Visual Studio можно создать альтернативный 1С конфигуратор.

    http://habrahabr.ru/post/247659/

    Reply
  6. serge_focus

    На самом деле , как мне кажется, подобные интересы вызваны во первых недостаточностью внимания со стороны 1С к разработчикам. «убогая » среда конфигуратора 1С подталкивает на такие эксперименты. Идея понравилась. Так что творческой удачи в экспериментах.

    Reply
  7. Darklight

    Идея интересная, и действительно, соглашусь с serge_focus, что в будущем может найти и коммерческое применение в альтернативных редактора 1С. Но, остаётся лишь вопрос эффективности получаемого кода. Насколько хорошо он будет работать. Такие конвертации из более мощного языка в менее мощный — всегда чреваты потерей эффективности конкретных алгоритмических реализаций (даже по сравнение с их аналогичной ручной реализацией на конечном языке). Эффективность и гибкость конвертации можно было бы увеличить, если бы сразу конвертировать в байт код машины 1С (что правильнее), как аналог IL-кода, платформы .NET.

    И, конечно же, особняком будет стоять проблема отладки. Она тут в крайне затруднена (требует отдельной реализации генератора специфического кода, который встраивал бы отладочные конструкции, которые хоть как-то давали бы обратную связь с жутким снижением производительности). А это ставит очень большой минус для таких разработок. Но, при должном рвении, ресурсов, гениальности и терпения может выйти занятный инструмент. Но, это вряд ли — запал иссякнет раньше, либо не хватит ресурсов. Слишком тяжелый проект, даже для команды.

    Была бы интересна и обратная конвертация. Из кода 1С в код C# — для реализации обратного перевода проектов, написанных на 1С в среду .NET framework. Это, как мне кажется, более перспективная и простая в реализации вещь. И оптимизация тут может достичь очень высоких результатов. Вот бы ещё движки присобачить (визуальных форм (в т.ч. печатных) и работы с БД, и метаданными — и была бы хорошая перспектива-альтернатива для 1С).

    Reply
  8. zqzq

    (5) 1С и сами планируют альтернативный конфигуратор на эклипс выпустить (к 1С 8.4?), вперёд паровоза бежите.

    Reply
  9. Elisy

    (8) zqzq,

    (5) 1С и сами планируют альтернативный конфигуратор на эклипс выпустить (к 1С 8.4?), вперёд паровоза бежите.

    Наивно верить, что у 1С получится качественно сделать что-то новое?

    Reply
  10. Elisy

    (7) Darklight,

    Но, остаётся лишь вопрос эффективности получаемого кода. Насколько хорошо он будет работать. Такие конвертации из более мощного языка в менее мощный — всегда чреваты потерей эффективности конкретных алгоритмических реализаций (даже по сравнение с их аналогичной ручной реализацией на конечном языке). Эффективность и гибкость конвертации можно было бы увеличить, если бы сразу конвертировать в байт код машины 1С (что правильнее), как аналог IL-кода, платформы .NET.

    Конвертация в код 1С — это компромисс, позволяющий отлаживать полученное решение средствами 1С. А так, конечно, оп-код был бы более предпочтительным. Принципиальных барьеров против этого нет.

    Была бы интересна и обратная конвертация. Из кода 1С в код C# — для реализации обратного перевода проектов

    По идее в полноценном проекте должна быть конвертация из 1С в C#, чтобы как можно больше разработчиков переманить на свою сторону.

    Reply
  11. AlexanderKai

    (8) zqzq,

    Скорей всего получится, что «хотели как лучше, получилось как всегда».

    Reply
  12. zhichkin

    Прошло несколько лет с момента последнего комментария к этой публикации…

    Тем не менее хотелось бы её возродить. Сам занимаюсь чем-то подобным =)

    Мой опыт работы и общения с коллегами говорит о том, что проблемы крупных компаний, использующих 1С и знающих что такое high load не по наслышке, заставляют их всё чаще решать проблемы при помощи непосредственного использования прямых SQL запросов, прикручивания сбоку стронних систем версионирования, тестирования кода, платформ для разработки web UI, а также систем обмена данными, основанных на брокерах очередей и т.д. и т.п. Более того, как выяснилось на круглом столе по high load на последнем Infostart’е 2019 — «все 1С-ники делают это» =) =) =)

    ИТ культура компаний выросла за эти годы очень сильно, а вместе с ней потребность в современных средствах разработки. 1С по прежнему не решает всех проблем и, по всей видимости, это нормально — так сложилось исторически и это фактически уже константа.

    Теперь хотелось бы сказать немного о коммерческой составляющей проекта. Сразу скажу, что в проекте, о котором далее пойдёт речь, я лично не участвовал. Очень жаль, кстати =)

    Как-то очень давно мне довелось познакомиться с проектом, который был рождён в недрах очень крупной и известной компании. Идея была очень простой: компания выпускала свою конфигурацию 1С для автоматизации розничной торговли. Клиентов было много и с каждой копии проданной программы нужно было что-то платить 1С. А ведь наверное можно было бы не делать этого, подумали руководители этой организации…

    Проблема была в том, что с нуля кассовый софт со всем его функционалом писать было дорого, а сэкономить очень хотелось. В итоге пара программистов C# сделала конвертер всей конфигурации 1С на C#. С формами, кодом всех модулей, структурами данных и прочим. Примерно год работы. Конвертер получился настолько удачным, что в принципе он мог конвертировать почти любую конфигурацию 1С. В любом случае для своих целей и своей конфигурации ребятам вполне этого конвертера было достаточно.

    Бомба, не правда ли ? Однако, дальше произошло что-то удивительное. По слухам очень влиятельные люди из компании 1С лично встретились с руководством этой «жадной» компании и им удалось договориться проект закрыть. Так это или нет, но проект действительно закрыли и результаты этого проекта канули в Лету.

    Эта история заставляет меня думать, что коммерческой составляющей в этом проекте вполне достаточно. Особенно в свете последних изменений ситуации с high load в крупных компаниях, плюс развитие web проектов, проектов по интеграции всего и вся со всем и всюду. Лицензионное соглашение по web сервисам от 1С… Это же вообще золотая жила какая-то!

    Так что было бы интересно возродить этот проект =) Только не C# транслировать в 1С, а наоборот, как это однажды уже было сделано в рамках отдельно взятой компании =)

    Reply
  13. Elisy

    (12)

    Чтобы транслировать 1С в C#, нужно на стороне C# иметь стройную систему классов. Транслятор C# в 1С как раз создает систему классов и интерфейсов, совместимых с объектами 1С. Если кода на C# будет наработано много, можно задуматься об обратной конвертации, ведь будет известно код 1С во что нужно конвертировать.

    Reply

Leave a Comment

Ваш адрес email не будет опубликован. Обязательные поля помечены *