Как программно получить ID ключа HASP из 1С?

Программист 1С v8.3 (Обычные формы) IT и автоматизация бизнеса
← На главную

При разработке систем защиты конфигураций 1С часто возникает задача идентификации конкретного экземпляра аппаратного ключа защиты (HASP). Это необходимо для того, чтобы привязать работу программы к физическому носителю, предотвращая несанкционированное копирование базы. Хотя встроенных средств в языке 1С для прямого обращения к низкоуровневым параметрам USB-устройств не существует, мы можем воспользоваться системными механизмами Windows. В данной статье мы подробно разберем несколько способов решения этой задачи: от простых WMI-запросов до использования специализированных библиотек и утилит.

Метод 1: Использование WMI (Windows Management Instrumentation)

Самый доступный способ, не требующий установки дополнительных компонент, — это обращение к инструментарию управления Windows (WMI). Мы можем опросить систему о подключенных USB-устройствах и найти среди них ключи HASP. Разберем по шагам, как это реализовать в коде 1С.

Рассмотрим базовый пример кода, который позволяет получить список идентификаторов устройств. Для этого используется COM-объект winmgmts. Проанализируем следующий фрагмент:


// Определяем имя компьютера, на котором запущен сеанс
ИмяКомпьютера = "."; // Текущий компьютер
WinMGMT = ПолучитьCOMОбъект("winmgmts:\\" + ИмяКомпьютера + "\root\cimv2");

// Выполняем запрос к классу Win32_USBHub
// Этот класс содержит информацию о концентраторах и подключенных устройствах
ЗапросWMI = "SELECT * FROM Win32_USBHub";
СписокУстройств = WinMGMT.ExecQuery(ЗапросWMI);

Для Каждого Устройство Из СписокУстройств Цикл
    // Выводим DeviceID в консоль или сообщение
    Сообщить("Найдено устройство: " + Устройство.DeviceID);
КонецЦикла;

Важный нюанс: Класс Win32_USBHub показывает общую информацию. Чтобы точнее идентифицировать именно ключ HASP, нам нужно знать его Vendor ID (VID) и Product ID (PID). Для ключей производства Aladdin (ныне Thales/Sentinel) Vendor ID обычно равен 0529. Выясним, как уточнить наш запрос, используя класс Win32_PnPEntity, который предоставляет более детальную информацию о Plug-and-Play устройствах.


// Более точный поиск по ID производителя (VID_0529)
ЗапросWMI = "SELECT * FROM Win32_PnPEntity WHERE DeviceID LIKE '%VID_0529%'";
СписокКлючей = WinMGMT.ExecQuery(ЗапросWMI);

Для Каждого Ключ Из СписокКлючей Цикл
    // В строке DeviceID после последнего слеша обычно находится серийный номер
    // Пример: USB\VID_0529&PID_0001\12345678
    Идентификатор = Ключ.DeviceID;
    Сообщить("ID ключа HASP: " + Идентификатор);
КонецЦикла;

Нужно учитывать, что старые модели HASP4 не всегда транслируют свой внутренний ID в поле DeviceID операционной системы. В таких случаях мы увидим только общую строку устройства без уникального заводского номера.

Метод 2: Использование внешней утилиты HASP Info

Если WMI не выдает нужной детализации, можно воспользоваться консольными утилитами от производителя. Существует специализированная утилита HASP Info, которая умеет опрашивать ключи и выводить информацию в текстовом виде. Проанализируем ситуацию: как нам запустить внешнюю программу из 1С и получить результат её работы напрямую?

Для запуска внешних приложений в 1С используется объект ЗапуститьПриложение() или COM-объект WScript.Shell. Рассмотрим второй вариант, так как он позволяет более гибко управлять процессом. Посмотрим на пример реализации через временный файл:


// Путь к утилите (должна быть доступна на компьютере)
ПутьКУтилите = "C:\Tools\hasp_info.exe";
ФайлРезультата = "C:\Temp\hasp_data.txt";

// Формируем команду запуска (результат перенаправляем в файл)
Команда = "cmd /c " + ПутьКУтилите + " > " + ФайлРезультата;

Шелл = Новый COMОбъект("WScript.Shell");
Шелл.Run(Команда, 0, Истина); // 0 - скрыть окно, Истина - ждать завершения

// Читаем полученный файл
Текст = Новый ТекстовыйДокумент;
Текст.Прочитать(ФайлРезультата);
Для НомерСтроки = 1 По Текст.КоличествоСтрок() Цикл
    Строка = Текст.ПолучитьСтроку(НомерСтроки);
    Если Найти(Строка, "HASP ID:") > 0 Тогда
        // Извлекаем ID из строки
        IDКлюча = СокрЛП(СтрЗаменить(Строка, "HASP ID:", ""));
        Сообщить("Уникальный номер ключа: " + IDКлюча);
    КонецЕсли;
КонецЦикла;

Метод 3: Вызов PowerShell для получения данных без временных файлов

Современные версии Windows позволяют выполнять мощные скрипты PowerShell. Это избавляет нас от необходимости создавать промежуточные текстовые файлы. Мы можем перехватить «стандартный поток вывода» (Stdout) напрямую в 1С. Разберем этот эффективный подход:


// Команда PowerShell для поиска устройств с VID 0529
КомандаPS = "powershell -command ""Get-PnpDevice | Where-Object {$_.InstanceId -match 'VID_0529'} | Select-Object -ExpandProperty InstanceId""";

Шелл = Новый COMОбъект("WScript.Shell");
Процесс = Шелл.Exec(КомандаPS);

// Читаем ответ пока поток не закончится
Результат = "";
Пока НЕ Процесс.StdOut.AtEndOfStream Цикл
    Результат = Результат + Процесс.StdOut.ReadAll();
КонецЦикла;

Сообщить("Данные от PowerShell: " + СокрЛП(Результат));

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

Метод 4: Использование Sentinel Runtime API (DLL)

Для наиболее профессиональной и защищенной реализации следует использовать родные библиотеки поставщика ключей, такие как hasp_windows.dll. В этой библиотеке есть функция hasp_get_info(), которая возвращает XML-структуру с полными данными о ключе, включая тег <hasp_id>.

Поскольку 1С не может напрямую вызывать функции из произвольных DLL, нам потребуется либо написать свою «Внешнюю компоненту» на C++ или Delphi, которая будет оберткой над этой функцией, либо использовать специальные компоненты-загрузчики. Преимущество этого метода заключается в том, что информацию, полученную через официальное API, практически невозможно подделать, в отличие от текстового файла или ответа WMI, которые могут быть эмулированы злоумышленником.

Особенности программных лицензий и сетевых ключей

Важно проанализировать ситуацию, когда в организации используются не аппаратные USB-ключи, а программные лицензии (пин-коды). Программная лицензия не имеет физического ID ключа. Если ваш код жестко завязан на поиск VID_0529, то на компьютере с программной лицензией система защиты просто не сработает и заблокирует вход пользователю.

Посмотрим, как можно обработать этот момент в коде:

  1. Сначала проверяем наличие физического ключа через WMI или API.
  2. Если ключ не найден, проверяем наличие программной лицензии через встроенную функцию 1С ПолучитьИнформациюОПрограммныхЛицензиях().
  3. Если найдена программная лицензия, используем в качестве уникального ключа её регистрационный номер или уникальные характеристики оборудования (HWID).

Также стоит помнить о разнице между локальными и сетевыми ключами. Если ключ вставлен в сервер, а пользователь работает в клиент-серверном варианте, WMI-запрос, выполненный НаКлиенте, ничего не найдет. В этом случае опрос ключа нужно выполнять либо на стороне сервера, либо использовать утилиты, умеющие работать с HASP License Manager по сетевому протоколу.

Подводя итог, можно сказать, что для простой защиты достаточно использовать WMI или PowerShell. Для серьезных тиражных решений лучше инвестировать время в создание внешней компоненты, работающей напрямую с драйвером ключа через официальное API.

← На главную