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




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

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 не будет опубликован. Обязательные поля помечены *