[Мониторинг изменения файлов] — ActiveX-компонента для 1С 8.х + ВК для 7.7




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

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

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

<?php // Полная загрузка сервисных книжек, создан 2025-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='\

52 Comments

  1. Душелов

    Насколько я знаю, подобная ВК есть, но…

    Т.к. в 8-ке в контексте сервера нет возможности использовать внешние компоненты в стандартном представлении 1С, то пришлось написать аналог в виде ActiveX, который прекрасно работает в серверном режиме (т.е. регламентные и прочие задания).

    Reply
  2. Арчибальд

    Предлагаю альтернативный ник

    Душелов_Для_работы_MS.NET_Framework2.0

    Reply
  3. biv75

    А лучше отдельную страницу «Душелов разработки»

    Reply
  4. Арчибальд

    (3)Отнюдь НЕ ВСЕ разработки Василия требуют фрамугу. Так что альтернатива нужна.

    Reply
  5. artbear

    Подобное вроде как можно сделать и на штатном MS.ScriptControl, без всяких

    наворотов в виде ВК ?

    Его события вроде бы также можно юзать в восьмерке.

    ЗЫ сам в 8.1 не тестил 🙂

    в 77 с помощью 1С++ подобная схема работает.

    Reply
  6. Душелов

    (5) Честно, не помню, по-моему Watcher там есть…. Можно, конечно, порыскать, но для меня быстрее компоненту написать, чем со скриптами разбираться 😉

    Reply
  7. biv75

    (6) Вот.. лень двигатель прогресса, ленись Василий, мне нравится как ты это делаешь

    Reply
  8. CheBurator

    Василий! вот у мну есть подозрение.. что используя очередь событий виндов (или как оно там называется) — можно организовать обмен между сеансами в одной базе… яточно знаю что как-то так можно!

    Reply
  9. Душелов

    (8) Обмен чем? Сообщениями? Можно, почему нет?

    Reply
  10. CheBurator

    Вот!!!! так надо делать!!!

    то есть например… я «плюнул» сообщение, оно «стало» в очередь (где-то в виндах»), по факту появления данного сообщения в очереди в запущенных экземплярах 1ски генерится внешнее событие….

    или меня не туда несет?

    Reply
  11. Душелов

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

    В свой файлик записал сообщение — все, у кого открыты обработки увидели, что файлик изменен и давай его кучно читать 🙂

    Reply
  12. Душелов

    Соответственно, закрыл обработку — грохнул файлик.

    Присутствие файликов — аналог онлайна пользователей 🙂

    Reply
  13. Арчибальд

    (11)>все, у кого открыты обработки увидели, что файлик изменен и давай его кучно читать

    Не все. Только те, кто умеет 😉

    Reply
  14. Душелов

    (13) Ну и все, кому разрешено его читать 🙂

    Reply
  15. maljaev

    У меня стоит точно такая же задача, как у Чебура. Путей реализации без изврата через файлы или справочники пока не нашел.

    Reply
  16. Душелов

    (15) А через реестр? 😉

    Reply
  17. Душелов

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

    Reply
  18. maljaev

    Мне тут на 1CPP кинули ссылку на решение через сетевые сокеты. Теоретически, должно быть неплохое решение. Нужно только разобраться как это все работает и как применить к нашей ситуации.

    http://www.rikcenter.ru/downloads.php?file=13

    http://www.1cpp.ru/forum/YaBB.pl?num=1234860912

    Reply
  19. Душелов

    (18) Так это можешь мой чат взять 🙂

    Вообщем, все понятно. Сейчас сяду и напишу сервер событий :)))

    Reply
  20. Hadgehogs

    Где же это я все видел — то…

    Reply
  21. CheBurator

    (18) перая ссылка ( http://www.rikcenter.ru/downloads.php?file=13 ) — это как раз по вопросу, который я завязал обсуждать на мисте, аналогично упомянутому мной выше, а суть была в том: как из одного сеанса 1Ски (работающего с базой ИБ1) передать событие в другой сеанс этой же ИБ…?

    ОбработкаОжидания — отметаем сразу, ради того чтобы обработать событие которое может быть раз в 2 часа (а может раз в 10 минут) — постоянно крутить ожидание — это какое-то извращение! Я хочу, чтобы, работая в базе, мне извне «генерилось» событие — и вот когда оно пришло — вот тогда я и сделаю что надо… так вот — единственное решение придложил Садовников — чат по ссылке как раз и является примером.. Но! там тоже не все гламурно!



    и вот еще: соответсвенно, работая в ИБ, я хочу иметь «глобальный» обработчик событий (независимо от того в какой я форме нахожусь) — как я понял из беседс Василием — это можно сделать активиксом, но для него надо держать постоянно открытой форму… — тоже изврат…

    ..

    так вот.. еще один вариант — но смотрел только поверхностно (ибо не спец) — чат может быть построен на очереди сообщений виндов (но для этого добен нужен…)

    Reply
  22. CheBurator

    (20) аналогичная компонента по мониторингу файлов с генерацией ВС есть у romix? у него еще есть fakir.dll (я ее юзаю для целей автообновления псевдожурнала при проведении документа, отображаемого в журнале) — то есть я могу в модуле проведения сгенерить событие и оно отловится 1Ской… но опять же — только в рамках данного сеанса 1С… вот…

    Reply
  23. Арчибальд

    (19) Ждем-с

    Reply
  24. Hadgehogs

    (22) Ну вообще это все в Нетленке реализовано давно.

    Reply
  25. Hadgehogs

    Это я так Василия, идущего дорогой баянов, подъеживаю.

    Reply
  26. Душелов

    (25) Читаем 1 коммент… Я там как бы все написал.

    Reply
  27. Душелов

    По многочисленным просьбам 🙂 Написал аналогичную ВК для 7.7 (можно и в 8-ке использовать, только смысла нет) с теми же методами.

    Reply
  28. CheBurator

    (24) вас ист дас «Теленка»? тьфу, «нетленка»?

    Reply
  29. biv75

    (28) НЕТЛЕНКА http://infostart.ru/projects/1737/

    Много интересного

    Reply
  30. varelchik

    А кто нить еще пробовал под 7.7?

    У мене че 1С в коврик сворачивается при ппытке изменения сканируемого файла.

    Reply
  31. Душелов

    (30) Попробовал на разных машинах + в терминале, не падает.

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

    Reply
  32. Душелов

    (23) Вот тестовый сервер событий http://za-ha-dum.narod.ru/1c/EventServer.zip

    Есть пример клиентов для 7.7 и 8.1

    В примерах есть все команды, кроме одной, ее просто не успел включить:

    КлиентСобытий.ОтправитьПриватно(Ник, Текст)

    На базе этого сервера можно сделать чат (в примере он таким и является), а так же всякие выгонялки, оповестелки и прочее.

    Reply
  33. Душелов

    точнее не ник, а имя соединения 😉

    Reply
  34. Душелов

    Если запускать на одном компьютере (терминальная сессия, разные базы), то каждому клиенту надо назначить разные порта. Автопоиск портов свободных сделаю потом. Да и стоит ли делать «группы», по аналогии с комнатами чатовскими?

    Reply
  35. maljaev

    Чего-то у меня при соединении постоянно ошибку выдает:

    Ошибка: Ошибка сокета — Обычно разрешается одно использование адреса сокета (протокол/сетевой адрес/порт) (10048).

    Reply
  36. Душелов

    (35) см. 34, каждому клиенту надо задать разные порты.

    Reply
  37. maljaev

    (36) Задавал, не помогает. Ошибка вылазит даже при одном запущенном клиенте.

    Reply
  38. Душелов

    Запускаешь сервер на 27000 порту, потом запускаешь клиента на 27001 к примеру. Что пишет?

    Reply
  39. maljaev

    Уточняю:

    Сервер с портом по умолчанию. Клиент с портом по умолчанию. Первое соединение происходит нормально. Второе соединение, равно как и последующие, выдает ошибку. Не помогает даже закрытие/переоткрытие обработки клиента. Помогает закрытие/переоткрытие сеанса 1С. В остальном все нормально — клиенты видят друг друга, обмен сообщениями происходит. Если нажать «отсоединиться», а затем «соединиться», то на первом клиенте идет без ошибки, второй клиент высвечивает все ту же ошибку.

    Reply
  40. maljaev

    Ошибся: один клиент 27001, второй 27002. Жалко нету редактирования постов.

    Reply
  41. maljaev

    Душелов, ты чего-нибудь по постам 39-40 скажешь? Будешь дорабатывать или нет?

    Reply
  42. Душелов

    Надо сделать отдельной разработкой и там это дело обсуждать 😉

    Reply
  43. Душелов

    (41) Попробуй это http://infostart.ru/projects/3644/

    Пока сделал автопрощупывание 10 портов

    Reply
  44. Elfar

    Выполняю этот механизм на 7.7 и у меня при изменении(создании, удалении) в контролируемом каталоге вылетает ошибка и вылетает 1С-ка.

    Подскажите в чём есть проблема.

    Reply
  45. koreav

    1С:Предприятие 8.1 (8.1.13.41), при возникновении event’а окно 1С закрывается без сообщения об ошибке

    Reply
  46. fpohtmeh

    Я не сторонник того, чтобы в имя компоненты впихивать свое имя

    Тем более комбинация англ. и рус. слов (Душелов и Filewatcher)…

    Впрочем, это моё мнение

    Reply
  47. shushkovka

    Платформа 8.1.14.72. reg.bat отработал без ругани. Запускаю мониторинг на диск C:*.*, создаю любой файл… 1С вылетает «без шума и пыли»… где копать?

    Reply
  48. idle

    Прописал компоненту и описал контролируемый каталог и тип файлов…

    Процедура ПриНачалеРаботыСистемы()
    Попытка
    Мониторинг = СоздатьОбъект(«AddIn.FileWatcher»);
    Исключение
    Сообщить(«Ошибка создания объекта внешней компоненты: AddIn.FileWatcher»);
    КонецПопытки;
    ЭлМон = Мониторинг.Добавить(«файло»);
    ЭлМон.Путь = «C:	emp»;
    ЭлМон.Фильтр = «*.csv»;
    ЭлМон.ФильтрИзменений = «Модификация»;
    ЭлМон.Активирован = 1;
    КонецПроцедуры
    

    Показать

    При проверке работоспособности (создании или изменении существующего в папке файла) 1С вылетает…

    Подскажите в чем может быть проблема?

    Reply
  49. Ёпрст

    (48) Автора ВК уже нет в живых, врят ли кто-то будет поддерживать его творения.

    Reply
  50. Ёпрст

    А так, через regsvr32 попробуй зарегить вк, для начала

    Reply
  51. idle

    (50) Ёпрст, Таки с этого и начал работу с компонентой…

    Далее в глобальнике:

    Попытка
    ПодключитьВнешнююКомпоненту(«AddIn.FileWatcher»);
    Сообщить(«Внешняя компонента мониторинга папки успешно загружена!»);
    Исключение
    Сообщить(«Не удалось подключить компоненту «»AddIn.FileWatcher»»»);
    КонецПопытки;
    

    и еще что выше написал в первом сообщении…

    Хотел насладиться в отладчике пойманным событием, но увы…

    Reply
  52. dreadlord

    Може есть у кого рабочий пример под 7-ку.

    Так и не удалось запустить ЭТОТ!

    Перем Мониторинг;
    
    // ==—==—==—==—==—==—==—==—==—==—==—==—==—==—==—==—==—==—==—==—==
    Процедура ПриОткрытии()
    ЗагрузитьВнешнююКомпоненту(«FileWatcher.dll»);
    
    Попытка
    Мониторинг = СоздатьОбъект(«AddIn.FileWatcher»);
    Исключение
    Сообщить(«Ошибка создания объекта внешней компоненты: FileWatcher»);
    КонецПопытки;
    
    ЭлемМониторинга = Мониторинг.Добавить(«ПапкаФТП»);
    ЭлемМониторинга.Фильтр = «*@cbd.zip»;
    ЭлемМониторинга.Путь = «N:BaseObmin»;
    //ЭлемМониторинга.ФильтрИзменений = «»;
    ЭлемМониторинга.Активирован = 1;
    
    КонецПроцедуры // ПриОткрытии
    
    // ==—==—==—==—==—==—==—==—==—==—==—==—==—==—==—==—==—==—==—==—==
    // — Источник = «FileWatcher»
    // — Событие (ПриСоздании, ПриИзменении, ПриУдалении, ПриПереименовании, Ошибка)
    // — Данные (ИмяЭлемента + ИмяФайла + Путь), при переименовании еще «СтароеИмяФайла + СтарыйПуть»
    //
    Процедура ОбработкаВнешнегоСобытия(Источник,Событие,Данные);
    Сообщить(«ОбработкаВнешнегоСобытия: «+Источник);
    
    Если Источник = «FileWatcher» Тогда
    Сообщить(«Событие «+Событие);
    Сообщить(«Данные «+Данные);
    КонецЕсли;
    КонецПроцедуры
    
    

    Показать

    Вылетает с ошибкой:

    ЭлемМониторинга = Мониторинг.Добавить(«ПапкаФТП»);

    {N:COPYCBEXTFORMSМОНИТОРИНГФТП.ERT(13)}: Поле агрегатного объекта не обнаружено (Добавить)

    Есть рабочий вариант от Romix-а, НО — проблема в том, что какой именно файл создан у него не видно, нужно парсить папку.

    Спасибо.

    Reply

Leave a Comment

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