При работе в конфигурации «Альфа-Авто» (особенно в редакциях 4 и 5) пользователи часто сталкиваются с неприятной ошибкой при попытке пробить фискальный чек. В журнале регистрации или прямо на экране кассира появляется сообщение: «Значение не является значением объектного типа (GetBounds)». При этом сама касса может физически выдать чек, а документ в 1С останется непроведенным, либо сессия зависнет.
Давайте подробно разберем, почему возникает эта ошибка, проанализируем внутренние механизмы взаимодействия 1С с торговым оборудованием через компоненты «1С-Рарус» и найдем несколько эффективных способов решения проблемы.
Для начала проанализируем фрагмент кода, на который указывает стек ошибки в обработке ФронтКассира:
КоличествоСтрок=0; КоличествоСтолбцов=0;
SafeArrayПараметрыЧека.GetBounds(КоличествоСтрок,КоличествоСтолбцов);
НомерСмены=Число(SafeArrayПараметрыЧека.GetValue(0,0));
Переменная SafeArrayПараметрыЧека — это специальный многомерный массив (структура SafeArray), который возвращается внешней компонентой защиты и оборудования «1С-Рарус» (например, protect.dll или Rarus_Equipment.dll) после отправки команды на пробитие чека.
Метод GetBounds() предназначен для определения размерности этого массива, чтобы затем безопасно считать из него фискальные реквизиты: номер чека, номер смены, дату и номер документа ФР.
Ошибка «Значение не является значением объектного типа» означает, что в момент вызова метода переменная SafeArrayПараметрыЧека не является COM-объектом. Вместо ожидаемой структуры она содержит значение Неопределено или Ложь. Это происходит потому, что внешняя компонента защиты по какой-то причине дала сбой, зависла или не смогла получить ответ от драйвера кассы, вернуть структуру параметров чека в 1С.
Выделим основные технические причины, по которым это происходит:
---
Первое, что мы должны сделать — обезопасить конфигурацию от аварийного завершения работы. Если компонента не вернула параметры чека, код не должен вызывать критическую ошибку, которая блокирует работу всей кассовой смены.
Давайте модифицируем исходный код в обработке ФронтКассира. Мы добавим строгую проверку типа возвращаемой переменной с помощью встроенной функции ТипЗнч(). Если переменная не является COM-объектом, мы корректно запишем ошибку в лог и сообщим пользователю, не прерывая выполнение программы.
Рассмотрим пример безопасного кода:
Если Результат И (УстановленРежим("Чек") ИЛИ УстановленРежим("ЧекНаВозврат") ИЛИ УстановленРежим("ЧекНаОплату") ИЛИ УстановленРежим("ЧекНаОплатуВозврат") ИЛИ УстановленРежим("ПриходныйКассовыйОрдер") ИЛИ УстановленРежим("РасходныйКассовыйОрдер")) Тогда
Попытка
КоличествоСтрок=0; КоличествоСтолбцов=0;
// Проверяем, что переменная действительно является COM-объектом
Если ТипЗнч(SafeArrayПараметрыЧека) = Тип("COMОбъект") Тогда
SafeArrayПараметрыЧека.GetBounds(КоличествоСтрок,КоличествоСтолбцов);
НомерСмены=Число(SafeArrayПараметрыЧека.GetValue(0,0));
НомерЧека=Число(SafeArrayПараметрыЧека.GetValue(1,0));
ДатаФР=Вычислить("'"+SafeArrayПараметрыЧека.GetValue(3,0)+"'");
НомерДокумента=Число(SafeArrayПараметрыЧека.GetValue(2,0));
СтруктураВозвратныхПараметров=Новый Структура("ДатаФР,НомерЧека,НомерДокумента,НомерСмены",ДатаФР,НомерЧека,НомерДокумента,НомерСмены);
Иначе
// Если пришел не COM-объект, обрабатываем ошибку без падения системы
ТекстОшибки = "Внешняя компонента Рарус вернула пустой результат. Проверьте физическое состояние ККТ.";
ЗаписьЖурналаРегистрации("Оборудование.ККТ", УровеньЖурналаРегистрации.Предупреждение, , , ТекстОшибки);
КонецЕсли;
Исключение
ТекстОшибки="Ошибка получения фискальных реквизитов пробитого чека: "+ОписаниеОшибки();
ЗаписьЖурналаРегистрации("Оборудование.ККТ", УровеньЖурналаРегистрации.Ошибка, , , ТекстОшибки);
КонецПопытки;
КонецЕсли;
Использование конструкции ТипЗнч(SafeArrayПараметрыЧека) = Тип("COMОбъект") гарантирует, что метод GetBounds никогда не вызовет фатальной ошибки в сеансе кассира.
---
Как показывает практика администрирования «Альфа-Авто», большинство сбоев внешних компонент торгового оборудования связано с нестабильной эмуляцией COM-портов при подключении ККТ (особенно моделей АТОЛ и Штрих-М) по USB.
Если пользователи работают на терминальном сервере (через RDP), проброс COM-портов регулярно сбоит, что приводит к потере пакетов данных между компонентой защиты Рарус и кассовым аппаратом. В этот момент и происходит «отвал» объекта SafeArray.
Давайте разберем, как кардинально решить эту проблему по шагам:
192.168.1.150).5555, для Штрих-М — 4000).Сетевое подключение по TCP/IP работает в десятки раз стабильнее, не зависит от сессий Windows/RDP и полностью устраняет проблему монополизации портов драйвером кассы.
---
Если ошибка начала появляться внезапно и регулярно, проблема может заключаться в повреждении локального кэша системы лицензирования Рарус на рабочем месте пользователя или сервере. Компонента защиты хранит временные файлы и настройки обмена в профилях пользователей.
Проанализируем шаги по очистке и обновлению файлов защиты:
1cv8.exe или 1cv8c.exe полностью завершены в диспетчере задач.C:\Users\<Имя_Пользователя>\AppData\Roaming\1C-Rarus\ и полностью удалите папку Protect (или Licensing в зависимости от версии компоненты). В этой папке хранятся кэшированные файлы лицензий оборудования, которые могут содержать ошибки.Rarus_Equipment.dll или аналогичные). Скопируйте их с заменой в каталог установки платформы или каталог шаблонов конфигурации.---
Самым надежным и долгосрочным решением, к которому прибегают многие системные интеграторы и программисты 1С, является полный отказ от использования закрытых модулей Раруса для работы с торговым оборудованием.
В типовой поставке «Альфа-Авто» ред. 4.1 работа с фискальными регистраторами жестко завязана на собственные компоненты защиты Рарус. Однако, вы можете переписать процедуры отправки чека на печать, используя прямые вызовы драйверов ККТ (например, драйвер АТОЛ v10 или Штрих-М) или внедрив БСП (Библиотеку стандартных подсистем 1С).
Почему это выгодно проанализировать?
Для реализации этого метода потребуется переписать функции в общих модулях работы с торговым оборудованием, заменив вызовы ВыполнитьКомандуОборудования() на прямую инициализацию COM-объекта драйвера производителя ККТ (например, Новый COMОбъект("AddIn.FPrnM45") для старых драйверов АТОЛ или через NativeAPI для новых версий).