Привязка конфигурации к диску




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

38 Comments

  1. SergeyT2006

    А если с базой работают несколько пользователей? Или база на одной машине, а запускаем по сети? Диск будет определяться для локальной машины.

    Однобокая система защиты какая-то 😉

    Reply
  2. Re:аниматор

    Термин «ЗащитаОтДурака» имеет другой смысл …

    Reply
  3. Русский

    Кому надо, те используют ключи HASP, вынося часть конфы в DLL, и привязав эту DLL к ID ключа HASP.

    Reply
  4. alexk-is

    (0) Выглядит как-то сыровато. Программный код можно было бы раскрасить получше.

    Reply
  5. shurik_shurik

    Как для простенькой конфы на одного пользователя…. пройдет..

    Или ввести в конфу закрытый справочник серийных номеров, можна даже контролировать количество лицензий…

    Или не справочник, а закрытый код с жестко прописаными серийниками, или…….

    Вариантов масса….

    Reply
  6. DMon

    Не очень практично. А если у пользователя вышел из строя винт? …или переустановили операционную систему (при этом установив другой винчестер и грузятся с него)? Как вариант простенькой защиты — пойдет! 🙂

    Reply
  7. Re:аниматор

    ПодключитьОбработчикОжидания(«ЗащитаОтДурака»,60,Истина) ;

    а зачем обработчик? разве при начале работы нельзя это проверять? или предполагается что винты на ходу будут меняться)))

    Reply
  8. simgo83

    (7) нет не на ходу)))), фантазия у Вас конечно есть)

    пауза в 60 секунд для «Для клиентов которые заплатили, устанавливаем номер константы обработкой ЗащитаОтДурака.epf в первые 60 секунд работы системы и работаем)»

    Reply
  9. pricec

    использую такой прием в своих разработках — идея вполне работоспособная.По трудозатратом не сравнима с dll(тоже кстати делал на с++).А вариант с хаспом стоит денег.Так что для небольшого авторского коллектива этот вариант самое то! Всем рекомендую.

    Reply
  10. vde69

    вся эта защита строится на закритии модуля приложения…

    нельзя закрывать его!!! ни один нормальный заказчик не купит такую конфу.

    закрыть можно отдельный модуль, но не глобальный…

    Reply
  11. orefkov

    Насколько я помню, drive.SerialNumber использует для работы метод WinAPI GetVolumeInformation — который возвращает не «железный» серийный номер харда, а программный серийный номер тома (volume serial number), устанавливаемый при форматировании раздела.

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

    Получение настоящего серийного номера харда, зашиваемого производителем индивидуально для каждого винта — несколько более сложная задача.

    Reply
  12. ra9000

    Спасибо развеселили.

    Reply
  13. simgo83

    (11) давайте подумаем как узнать из 1с «Получение настоящего серийного номера харда, зашиваемого производителем индивидуально для каждого винта — несколько более сложная задача.»

    Reply
  14. awa

    Ничего нового в статье нет, всё это давно описано, например Простые примеры реализации демо-версий обработок на платформе «1С:Предприятие 8».

    Неплохо бы пользоваться поиском по сайту прежде чем размещать свои публикации.

    Reply
  15. orefkov

    (13)

    А что тут думать — прыгать надо.

    Если серьезно — зависит от оси.

    Под 9х использовалась дыра, через которую можно было выполнить свой код в ring0, напрямую обращаясь к устройству, под 2К — через обращение к драйверу диска (но вроде не работало со флэшками). Это все требует WinAPI, то есть реализуемо через ВК. Под XP и старше — точно не знаю, вроде бы появилась возможность через WMI, но я лично не проверял. Это уже можно сделать и без ВК, на VBScript’е.

    Ну а так метод сойдет, как первый ров перед крепостной стеной. Крестьянское ополчение остановит, пехоту чуть задержит. Кавалерия перескочит.

    Reply
  16. venger

    (15) На локальном компе средствами WMI вывод всех свойств и их значений WMI класса Win32_DiskDrive (информация о дисковых накопителях HDD):

    Попытка
    Locator = Новый COMОбъект(«WbemScripting.SWbemLocator»);
    Исключение
    Сообщить(ОписаниеОшибки());
    КонецПопытки;
    ServicesSet = Locator.ConnectServer(«.»);
    ObjectSet = ServicesSet.InstancesOf(«Win32_DiskDrive»);
    Для Каждого Item Из ObjectSet Цикл
    Для Каждого Свойство Из Item.Properties_ Цикл
    Сообщить(Свойство.Name + » = » + Свойство.Value);
    КонецЦикла;
    КонецЦикла;
    
    

    Показать

    Reply
  17. venger

    (15) +16, в классе WMI «Win32_LogicalDisk» искать бесполезно, логические диски, а так вроде средствами WMI все, помимо «Win32_DiskDrive»…

    Reply
  18. venger

    (15) +17, помимо класса «Win32_DiskDrive», но что, например, в свойстве «PNPDeviceID» этого класса, есть там серийник харда или нет.У меня, например, там и производитель, и модель, а потом наверно серийник…

    Reply
  19. orefkov

    Ну и вот http://technet.microsoft.com/ru-ru/sysinternals/bb897436.aspx — прога от микрософта, позволяющая установить желаемый volume serial number.

    Reply
  20. simgo83

    а может серийник диска брать из реестра HKEY_LOCAL_MACHINESYSTEMCurrentControlSetServicesDiskEn­um

    смотрите значение параметра «0»

    Reply
  21. venger

    (20) Это тоже, что и (только если дисков несколько или вставлены флешки, то будет параметр не только 0, но и 1, и 2 😎 ):

    Locator = Новый COMОбъект(«WbemScripting.SWbemLocator»);
    ServicesSet = Locator.ConnectServer(«.»);
    ObjectSet = ServicesSet.InstancesOf(«Win32_DiskDrive»);
    Для Каждого Item Из ObjectSet Цикл
    Сообщить(Item.Caption+»: «+Item.PNPDeviceID);
    КонецЦикла;
    
    Reply
  22. venger

    (20) +21, а это из реестра вариант, из ветки, что предложена в 20-м посте, тот же результат:

    Locator = Новый COMОбъект(«WbemScripting.SWbemLocator»);
    ServicesSet = Locator.ConnectServer(«.»);
    ObjectSet = ServicesSet.InstancesOf(«Win32_ComputerSystem»);
    ИмяКомпьютера=»»;
    Для Каждого Item Из ObjectSet Цикл
    ИмяКомпьютера=Item.Name;
    КонецЦикла;
    Значение=»»;
    HKEY_LOCAL_MACHINE = 2147483650;
    ПутьККлючу = «SYSTEMCurrentControlSetServicesDiskEnum»;
    ИмяПараметра = «0»;
    Reg = ПолучитьCOMОбъект(«winmgmts:{impersonationLevel=impersonate}!\» +
    ИмяКомпьютера + »
    ootdefault:StdRegProv»);
    Reg.GetStringValue(HKEY_LOCAL_MACHINE, ПутьККлючу, ИмяПараметра, Значение);
    Сообщить(«Значение параметра ветки реестра: » + Значение);
    Пока ПустаяСтрока(СокрЛП(Значение))=Ложь Цикл
    ИмяПараметра=Строка((Число(ИмяПараметра)+1));
    Reg.GetStringValue(HKEY_LOCAL_MACHINE, ПутьККлючу, ИмяПараметра, Значение);
    Если ПустаяСтрока(СокрЛП(Значение))=Ложь Тогда
    Сообщить(«Значение параметра ветки реестра: » + Значение);
    Иначе
    Прервать;
    КонецЕсли;
    КонецЦикла;
    

    Показать

    Reply
  23. simgo83

    Есть у кого опыт определения серийника через SCSI комманды???, т.к. WMI уже формируется на основе данных, предоставляемых ДРОВАМИ!!!, и как там сформировано будет от версии к версии — неизвестно. Насколько я знаю(если что не так — поправьте), там постфиксы добавляются, если серийник короче скольких-то символов.

    «IDEDiskST3500418AS_____________________________CC38____5&­1726dd96&0&0.0.0″

    Reply
  24. venger

    (23) После второго слеша и идет серийник, скорее всего…

    Reply
  25. igor_gk

    А я поставлю + 🙂

    Reply
  26. YRAtomic

    Ну вот привязались к диску :)))

    Есть же еще куча железа с айдишками

    Reply
  27. venger

    (26) Проц, например;-)

    Reply
  28. simgo83

    (27)для варианта с процессором какой скрипт нужно тогда использовать?

    Reply
  29. MrDen

    Если код закрытый, то можно привязываться к чему угодно, иначе не стоит

    Параметры можно брать разные и HDD, и системы и тд. и тп.

    Reply
  30. venger

    (28) Если для локального компа, то примерно так:

    Попытка
    Locator = Новый COMОбъект(«WbemScripting.SWbemLocator»);
    Исключение
    Сообщить(ОписаниеОшибки());
    КонецПопытки;
    ServicesSet = Locator.ConnectServer(«.»);
    ObjectSet = ServicesSet.InstancesOf(«Win32_Processor»);
    Для Каждого Item Из ObjectSet Цикл
    Сообщить(«ProcessorId: «+Item.ProcessorId);
    КонецЦикла;
    

    Показать

    Reply
  31. Yurken

    А как это реализовать на 7.7

    Reply
  32. venger

    (31) Например, так: http://infostart.ru/public/69066/

    Я имею ввиду доступ к WMI, остальное по 7.7 очевидно….

    Reply
  33. arjuna

    удалено, уже все написано в предыдущем посте.

    Reply
  34. avavadim

    Спасибо за полезную мысль которую можно доработать…

    Reply
  35. kr_andr

    Спасибо

    Reply
  36. the1

    я бы автоматизировал процесс установки константы

    Если константы.НомерС.Получить() = «» тогда // первый запуск
    константы.НомерС.Установить(Строка(Drive.SerialNumber))
    ИначеЕсли константы.НомерС.Получить() <> Строка(Drive.SerialNumber) тогда
    Предупреждение(«Вы используете более одной копии программы! Обратитесь к разработчику»);
    ЗавершитьРаботуСистемы(Ложь);
    КонецЕсли

    А по сабжу конечно очень ограниченное применение найдется

    Reply
  37. Tarlich

    т.е такое решение актуально если база не сетевая и пользуется на одном компе

    Интересно : а если константу НомерС сделать ХранилишемЗначений

    ТЗ и хранить серийники винтов , проверять при открытии ….

    Reply
  38. Bond

    Кто подскажет, для проверки номера серийника процессора, можно ли вызвать функцию на сервере и получить данные сервера? или так или иначе будет возвращать номер локального компа?

    Reply

Leave a Comment

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