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




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

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

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

<?php // Полная загрузка сервисных книжек, создан 2026-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 не будет опубликован. Обязательные поля помечены *