Кроссплатформенное использование классов .Net в 1С через Native ВК. Или замена COM на Linux




Принцип обмена данными из 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='\

24 Comments

  1. kiv1c

    Скажите, а таки чем вы руководствуетесь когда называете функции «Ъ», «Ъновый» и «Ътип» ???

    Reply
  2. Serginio

    Чтобы было сокращенно и было созвучно с Новый , а Ътип из той же оперы.

    Мне лично, так код удобнее читать.

    Reply
  3. pbazeliuk

    Плюс за старания. Но по опыту скажу, если совмещать высокую нагрузку с внешними компонентами, до добра это не доводит.

    Reply
  4. soba

    Направление интересное. Пожалуй только фраза про «импортозамещение» не к месту прикреплена. Вроде Линус Торвальдс российского паспорта не получал пока. Ну и из 1с- «Энумератор» и «Врап» звучат так себе.

    Reply
  5. Serginio

    (3) pbazeliuk,

    Проблема тут не в самой компоненте, а интерфейсе, что 1С предоставляет.

    Например практически все программисты 1С используют ComОбъект.

    По моей методе можно использовать

    NetОбъект,NetТип

    JavaОбъект,JavaТип

    И эти объявления будут реально кроссплатформенны.

    При это различия с ComОбъект минимальны. Имя класса равноценно комовскому ProgID. При этом нет ограничений на используемые типы.

    Ты можешь написать свою библиотеку поместить в определенное место и использовать её вместо COM. Без регистрации итд. Расширять возможности 1С станет легче.

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

    Учитывая кроссплатформенность можно использовать нетовские или явовские библиотеки везде где можно. Упрощая программирование.

    А что касается работы с HTTP,SMPT, JSON то эти библиотеки были задолго до того как 1С их реализовывала, при этом с ошибками и функционалом сильно недотягивающих до .Net или Java.

    Стоит ли тратить время на то, что можно взять из стандартных библиотек. А ведь можно легко расширить за счет своих сборок.

    При этом например нетовская библиотека весит всего 65 мегабайт, которую можно включить в дистрибутив и главное это кроссплатформенное решение. Причем нет ничего сложного передавать в параметрах и объекты 1С которые поддерживают аналогичный интерфейс. Можно пойти по пути подсчета ссылок в 1С, а доступ к объектам 1С только на время вызова метода ВК.

    Например Использование сборок .NET в 1С 7.x b 8.x. Создание внешних Компонент многие бы использовали на равне с ComОбъект, но главная причина её неприменения в том, что она неинтегрирована в 1С.

    Даже если 1С не хочет интегрировать .Net в 1С, то можно сделать вариант ВК под .Net и Java . Прежде всего для получения объектов ВК и передачи их в параметрах. Кроме того можно добавить доступ по индексу [], получения итератора.

    Reply
  6. Serginio

    (3) pbazeliuk,

    Кстати сейчас нашел способ вызвать методы и свойсва для Динамиков https://rsdn.ru/forum/dotnet/6493695.1

    и вставлю в компоненту

    Reply
  7. Serginio

    (4) soba,

    Согласен, но меня на это сподвигло собеседование при поиске работы. Так как моя разработка

    Использование сборок .NET в 1С 7.x b 8.x. Создание внешних Компонент

    была мало интересна, так как не кроссплатформенна, а в разрезе «импортозамещения» сейчас требуется кроссплатформенное решение.

    Сделал, но какого не то, что ажиотажа а даже простой заинтересованности не видно.

    Reply
  8. Serginio

    (4) soba, По поводу врап и Энумератор.

    Лучше было бы по аналогии с ComОбъек писать NetОбъект.

    Но так много писанины. На сче Энумератора, то не нашел лучшего перевода (перечислитель перечислимый)

    Было бы проще если бы по аналогии с COM была поддержка Для Каждого

    Reply
  9. Vovan58

    Идея +. А Java c CORBA — не рулят?

    Reply
  10. Serginio

    CORBA это Out Process, я предлагаю упрощенный In Process взаимодействие.

    Сейчас линуксоиды используют HTTP или Web сервисы, это и есть аналог CORBA .

    Java тоже можно прикрутить по аналогичной методе, если Java поддерживает экспорт методов в Native.

    Reply
  11. premierex

    (0) 5. Один из основных — это нельзя вернуть и передать экземпляр ВК из методов ВК.

    Я тоже писал много внешних компонент, но вот этого реально не понял. Куда надо передавать экземпляр ВК из методов ВК?

    Reply
  12. Serginio

    Ты статью читал?

    У ВК есть методы

    УстановитьСсылку Создается ВК по строковому представлению, применяется как ъ(

    ПолучитьСсылку Получается Ссылка для передачи в параметрах.

    Reply
  13. ётун

    (8) самое пикантное, что функция «ПолучитьЭнумератор» при этом возвращает переменную «Перечислитель». Первый звоночек — если человек не может понятно что-то назвать, то это сигнал о том, что в предметной области проблемы. Ну или несерьезное отношение.

    Общее впечатление, что решается какая-то очень локальная задача, черезчур много «я», «мне», «лично». Сам придумал, сам обиделся, что 1С не такая. Направление интересное, но не больше, типа «а смотрите как я могу».

    Reply
  14. Serginio

    Там на самом деле два захода. Сначала получаем Энумератор, а из энумератора получаем перечислитель. Это просто проблемы перевода.

    IEnumerator и IEnumerable

    Смотрите не как я могу, а используй то, что я сделал. И делюсь своим опытом, на что было потрачено куча времени в том числе и на изучение предметной области.

    Кроме того я просто говорю о недостатках реализации .Native ВК, которые легко исправить.

    Или вообще можно интегрировать в 1С. Хуже от этого точно не будет. Но будет замена ComОбъект

    Reply
  15. Serginio

    (13) ётун, >> Общее впечатление, что решается какая-то очень локальная задача

    Ну если использование огромного количества стандартных библиотек .Net и расширения за счет написания своих библиотек и практически замена COM это локальная задача, то что называется глобальной?

    Reply
  16. Serginio
    Reply
  17. PolSerg

    (7) Причем здесь импортозамещение, Linux интересен прежде всего тем, что не кишит всякой заразой как винда, поэтому и тренд во многих компаниях, включая ту в которой работаю я, как бонус свободный софт, как правило, бесплатен.

    Reply
  18. Serginio

    (17) Если ты прочитал 7 то это не мой термин. Но, что скажешь по поводу расширения функционала 1С на Linux за счет использования классов .Net?

    Reply
  19. Serginio

    Добави вывод типов для дженерик методов

    Теперь можно не выводить отдельно метод

    // public T ДженерикМетод<V, T>(V param1, T param2, V param3)
    Сообщить(Тест.ДженерикМетод(1,»Привет»,3));
    //
    
    //public V ДженерикМетод2<K, V>(Dictionary<K, V> param1, K param2, V param3)
    Словарь= ъНовый(«System.Collections.Generic.Dictionary`2[System.Int32,System.String]»);
    Сообщить(Тест.ДженерикМетод2(Словарь.ПолучитьСсылку(),3,»Привет2″));
    
    // public K ДженерикМетод3<K>(IList<K> param1, int param2, K param3)
    List=ъНовый(«System.Collections.Generic.List`1[System.String]»);
    Сообщить(Тест.ДженерикМетод3(List.ПолучитьСсылку(),3,»Привет3″));
    
    

    Показать

    Reply
  20. Serginio

    Сделал поддержку внешнего события

    В классе создадим пле типа Action<string, string, string>

    public class Тестовый
    {
    public Action<string, string, string>   ВнешнееСобытие1С;
    
    // И сделаем эмуляцию события.
    
    
    
    public async void TestВнешнегоСобытия()
    {
    for(int i=0;i<100; i++)
    {
    var значение = i.ToString();
    Task.Run(async() =>
    {
    await Task.Delay(1000).ConfigureAwait(false);
    this?.ВнешнееСобытие1С(«Тестовый», «ТестовоеСообщение», значение);
    });
    
    await Task.Delay(50).ConfigureAwait(false);
    }
    
    
    }
    
    

    Показать

    В 1С.

    Процедура ВнешнееСобытие(Источник, Событие, Данные)
    // Вставить содержимое обработчика.
    
    
    Сообщить(«Источник=»+Источник);
    Сообщить(«Событие=»+Событие);
    Сообщить(«Данные=»+Данные);
    КонецПроцедуры
    
    Процедура ТестВнешнегоСобытияНажатие(Элемент)
    // Вставить содержимое обработчика.
    
    Тестовый=ъТип(«TestDllForCoreClr.Тестовый, TestDllForCoreClr, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null»);
    
    Тест=ъ(Врап.Новый(Тестовый.ПолучитьСсылку(),» Свойство из Конструктора»));
    
    Делегат=Ъ(Врап.ПолучитьДелегатВнешнегоСобытия1C());
    Тест.ВнешнееСобытие1С=Делегат.ПолучитьСсылку();
    Тест.TestВнешнегоСобытия();
    КонецПроцедуры
    
    

    Показать

    И не забыть в Переменных модуля установить

    Перем   Тест;
    Reply
  21. Serginio

    В VS 2015 апдейт 3 появилась возможность создавать библиотеки и приложения под .Net Core

    Вкладка

    Шаблоны->Windows->.Net Core

    Такой проект отличается от портативного.

    В тестах добавил пример создания JObject и сериализации его в Json

    Про установку SDK и прочее можно посмотреть здесь

    http://metanit.com/sharp/aspnet5/1.2.php

    Reply
  22. Serginio

    Добавил поддержку параметров по умолчанию

    Тест вызова метода с параметрами по умолчанию

    //public static int OptionalParam(int x, int y, int z = 5, int s = 4,string str=»Привет»)
    //       {
    //           return x + y + z + s;
    //       }
    
    
    Сообщить(«OptionalParam(int x, int y)=»+Тестовый.OptionalParam(1,2));
    Сообщить(«OptionalParam(int x, int y, int z = 5)=»+Тестовый.OptionalParam(1,2,3));
    Сообщить(«OptionalParam(int x, int y, int z = 5, int s,string str)=»+Тестовый.OptionalParam(1,2,3,4,»ХаХа»));
    

    Показать

    Reply
  23. par_62

    Все хорошо,красиво. Но мы прагматики и зададим вопрос. И он сакраментальный. Зачем?

    Если 1С для Native API избрало С++ зачем использовать Net библиотеки? Есть море библиотек на С++ спокойно и хорошо работающих в ВК. Точно так же как нет смысла в СОМ на NET.

    Преимуществ нет никаких,одни проблемы.

    Автор проделал большую работу,теоретически интересную и прочитал я с удовольствием. Но использовать просто не для чего. Возможно,только мне лично. Без обид,просто делюсь мнением

    Reply
  24. Serginio

    Так ВК то тоже нужно программировать и для каждого случая своя. Да и С++ это не особо то удобный инструмент. А здесь есть одна ВК и ну и нужно знать только классы и методы. По сути то и C# знать не нужно. Только 1С.

    Если бы 1С удосужились дать возможность возвращать объект типа ВК то можно было бы избавиться от Ъ, но у них своя политика.

    Конечно в таком виде это использовать нельзя. А вот Использование классов .Net в 1С для новичков многие используют. Ну и как я понял линукс используют единицы

    Reply

Leave a Comment

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