Имя: Пароль:
1C
1С v8
.NET и 1С V82.COMConnector ошибка при вызове .ПолучитьОбъект
0 developer1
 
07.10.13
14:53
Добрый день,
возникла следующая проблема.

Имеется модуль с простыми функциями типа отметить документ на удаление по номеру или провести документ по номеру.

Функция ПометитьРасходнаяНакладная(Номер, ПометкаУдаление, ПометкаПроведение) Экспорт
    Попытка
        документ = Документы.РасходнаяНакладная.НайтиПоНомеру(Номер).ПолучитьОбъект();
        ПометитьДокумент(документ, ПометкаУдаление, ПометкаПроведение);
        Возврат "ok";
    Исключение
        Инфо = ИнформацияОбОшибке();        
        Возврат "Описание='" + Инфо.Описание + "'";
    КонецПопытки
КонецФункции

Функция ПометитьДокумент(Документ, ПометкаУдаление, ПометкаПроведение)
    Документ.УстановитьПометкуУдаления(ПометкаУдаление);
    Если ПометкаПроведение
    Тогда
        Документ.Записать(РежимЗаписиДокумента.Проведение);
    Иначе
        Документ.Проведен = Ложь;
        Документ.Записать();
    КонецЕсли
КонецФункции

Проблема с методом .ПолучитьОбъект() - при вызове функции ПометитьРасходнаяНакладная через COM из .NET приложения вылетает исключение, которое не перехватывается в теле функции ПометитьРасходнаяНакладная и более того некорректно сериализуется. То есть на стороне .NET приходит объект Exception с указателями-null'ами, не несущий никакой информации.

Что интересно:
- если эти функции вызываются непосредственно из 1С, то все прекрасно работает.
- если изменить тип документа с РасходнаяНакладная на некоторый другой, то все выполняется корректно. Есть еще как минимум один тип, для которого это также не работает. Заметить отличия этих типов документов от других, с которыми все ок, не удалось
- гарантируется, что сам вызов через COM осуществляется, если убрать проблемный вызов .ПолучитьОбъект(), то вызов отрабатывает корректно
-COM соединение выполняется под тем же аккаунтом, под которым функция корректно работает при выполнении через 1С:Предприятие
-другие методы типа .ПолучитьФорму() этой же ссылки работают корректно

Итого: непонятная ошибка, которая не ловится try\catch и возникает при вызове метода .ПолучитьОбъект на ссылках документа типа РасходнаяНакладная при соединении через COM.

.NET код:
var connection = GetConnection();
                var msg = connection.ПроведениеДокументов.ПометитьРасходнаяНакладная(docNumber, true, false);

Могу выложить код GetConnection() если необхдимо
1 ДенисЧ
 
07.10.13
14:55
Сначала найти, потом проверить найденность, потому уже получать объект
2 developer1
 
07.10.13
14:58
(1) Гарантируется, что объект с заданным номером в базе есть и, повторюсь, этот код с такими же параметрами корректно отрабатывает будучи вызванным через 1С Предприятие. Да и наверняка тогда поймалось бы исключение в самой функции ПометитьРасходнаяНакладная
3 Serginio1
 
07.10.13
15:00
Посмотри подписчики при записи. И посмотри стоит ли у этих модулей галка внешнее соединение
4 Serginio1
 
07.10.13
15:07
Или смотри модуль РасходнаяНакладная, что там вызывается при инициализации в модуле расходной накладной
5 developer1
 
07.10.13
15:33
(4) Спасибо за помощь, но не вижу каких-либо проблем.
Насчет ПриЗаписи, причем оно тут?
Галка "Внешнее соединение" установлена, однако и с ней и без нее эффект одинаковый. Работает с другими документами и другими методами и без "внешнего соединения".
В модуле РасходнаяНакладная вообще нет никаких функций, связанных с инициализацией (или я их не вижу).

Вообще чисто гипотетически как может возникнуть описанная ситуация?

1) не ловится исключение в ПометитьРасходнаяНакладная
2) работает через 1С Предприятие
3) не работает через COM и только для некоторых типов документов
6 hhhh
 
07.10.13
15:34
(5) НайтиПоНомеру(Номер) - это гарантированно не найдет. Пиши не через задницу, а по-человечески

НайтиПоНомеру(Номер, Дата)
7 developer1
 
07.10.13
15:49
(6) четвертый день вижу 1С, НайтиПоНомеру(Номер) находит то, что нужно, повторюсь, код работает будучи вызванным через 1С Предприятие.

Поискал по коду 1С - почти всюду НайтиПоНомеру используется без второго аргумента.

Из того, что сейчас прочитал - второй аргумент целесообразен при использовании периодичной нумерации (так?). В свойствах РасходнаяНакладная Периодичность "Непериодический".

Готов попробовать тем не менее. Не представляю только какую дату указывать. Дата(0)?
8 Serginio1
 
07.10.13
15:52
(5) Не функций а кода который вызывает функции из других модулей. Код инициализации это код после последней процедуры функции модуля
9 developer1
 
07.10.13
15:55
(8) Спасибо за пояснение. В модуле объекта РасходнаяНакладная кроме процедур и одной глобальной переменной нет никакого другого кода.
10 Serginio1
 
07.10.13
16:00
(7) ТекущаяДата()

док = Документы.РасходнаяНакладная.НайтиПоНомеру(Номер);

Сделай проверку на неопределено



Если док=неопределено Тогда
возврат "Не найден документ";

а на строчке
документ=Док.ПолучитьОбъект();
в отладчике "Шагнуть В";
11 developer1
 
07.10.13
16:20
(10) Изменил:

ссылка = Документы.РасходнаяНакладная.НайтиПоНомеру(Номер, ТекущаяДата());
        Если ссылка = Неопределено
        Тогда
            Возврат "Doc not found";
        Иначе
            документ = ссылка.ПолучитьОбъект();
            ПометитьДокумент(документ, ПометкаУдаление, ПометкаПроведение);
            Возврат "Ok!";            
        КонецЕсли

Запустил под отладчиком привязав вызов

ПроведениеДокументов.ПометитьРасходнаяНакладная("00008121",Истина,Ложь);

к одному из событий интерфейса. В результате ПолучитьОбъект отработал корректно. При "Шагнуть В" вход внутрь не выполнился. Я не знаю типично ли это для системных вызовов в 1С или мне нужно изменить какие-то настройки отладчика.

Проверил и вызов через COM - все то же исключение, которое даже не удается идентифицировать.
12 Serginio1
 
07.10.13
16:34
Ну тогда
ЗаписьЖурналаРегистрации("ПометитьРасходнаяНакладная",
        УровеньЖурналаРегистрации.Информация, , ,
        "Выполнено " + СтрСообщения);
в руки и трассируй
13 developer1
 
07.10.13
17:12
(12) не понимаю смысла. я и так знаю какой оператор приводит к ошибке, как мне мои же сообщения в журнале должны помочь?

более реально было бы запустить отладчик удаленно, но в моей ситуации на одном физическом сервере запущены две базы (Dev и Production). Как я понимаю, переключение сервера в режим Debug приведет к замедлению в работе Production базы
14 Serginio1
 
07.10.13
17:16
(13) Ну хотя бы в
Исключение
        Инфо = ИнформацияОбОшибке();    
ЗаписьЖурналаРегистрации("ПометитьРасходнаяНакладная",
        УровеньЖурналаРегистрации.Информация, , ,
        "Описание='" + Инфо.Описание);
    
        Возврат "Описание='" + Инфо.Описание + "'"+Инфо.ИмяМодуля+ "'"+Инфо.НомерСтроки ;
    КонецПопытки

А откуда знаешь, если отладчиком не пользуешься?
15 developer1
 
07.10.13
17:25
(14) первый пост, объяснил все там.

Как до этого дошел - опытным путем, вызывая разные методы вместо .ПолучитьОбъект и проверяя другие типы документов (не РасходнаяНакладная). Возвращается "Ok" (ну или я ставил Возвраты сразу до или после оператора с .ПолучитьОбъект).

Если документ не найден, вызывается некорректный метод или не указаны обязательный аргументы (что я только не делал) и т.д. и т.п., то исключение в ПометитьРасходнаяНакладная перехватывается и мне на .NET клиент возвращается ошибка "Описание='" + Инфо.Описание + "'";

Еще раз - ошибка в .ПолучитьОбъект для документа типа РасходнаяНакладная при соединении через COM. Это ОЧЕНЬ странно и именно поэтому я пишу все это.

Я не вижу никакого смысла имея


Исключение
    Инфо = ИнформацияОбОшибке();        
    Возврат "Описание='" + Инфо.Описание + "'";
КонецПопытки

писать

Исключение
        Инфо = ИнформацияОбОшибке();    
ЗаписьЖурналаРегистрации("ПометитьРасходнаяНакладная",
        УровеньЖурналаРегистрации.Информация, , ,
        "Описание='" + Инфо.Описание);
    
        Возврат "Описание='" + Инфо.Описание + "'"+Инфо.ИмяМодуля+ "'"+Инфо.НомерСтроки ;
    КонецПопытки
16 hhhh
 
07.10.13
17:33
(15) ну разобрались же. Дату надо указать. Почему странно? Детский сад.


ведь понятно же и во всех букварях написано, что по COM надо все параметры указывать, а иначе будет параметр NULL.
17 developer1
 
07.10.13
17:35
(16) разобрались? По-моему нет. Дальше начала не продвинулись
18 Serginio1
 
07.10.13
17:37
(15) Не пиши. А вообще то всегда хорошо регистрировать ошибки и знать почему и когда они произошли. При этом ошибка у тебя не возвращается. Хозяин барин.
19 Славен
 
07.10.13
17:42
(16)имхо, тут бесполезно что-то пояснять
20 developer1
 
07.10.13
17:48
(18) добавил, проверил, предсказуемо в журнал ничего не добавилось. Проблема все та же - невозможно даже перехватить КОНКРЕТНО ЭТО исключение в 1С, соответственно ничего не возвращается и не пишется в журнал.

Писал выше, что другие ситуации типа некорректного метода или некорректных параметров отлично перехватываются и на стороне .NET'а (даже) я получаю соответствующую диагностику.

Почему так - не знаю, это и хотел понять малой кровью.
21 shurikvz
 
07.10.13
17:52
(11) НЕ
-------------
ссылка = Документы.РасходнаяНакладная.НайтиПоНомеру(Номер, ТекущаяДата());
        Если ссылка = Неопределено
-------------
а
-------------
ссылка = Документы.РасходнаяНакладная.НайтиПоНомеру(Номер, ТекущаяДата());
        Если ссылка = Неопределено ИЛИ ссылка.Пустая()
-------------
22 Serginio1
 
07.10.13
17:54
(20) Ну можно еще потрассировать

ЗаписьЖурналаРегистрации("ПометитьРасходнаяНакладная",
        УровеньЖурналаРегистрации.Информация, , ,
        "ссылка.ПолучитьОбъект();");
   документ = ссылка.ПолучитьОбъект();

ЗаписьЖурналаРегистрации("ПометитьРасходнаяНакладная",
        УровеньЖурналаРегистрации.Информация, , ,
        "ПометитьДокумент");


            ПометитьДокумент(документ, ПометкаУдаление, ПометкаПроведение);
23 shurikvz
 
07.10.13
17:55
А, и попробуйте не ИнформацияОбОшибке(), а ОписаниеОшибки().
24 zladenuw
 
07.10.13
17:57
а какая платформа точно ? ТИИ делал базы ?
25 developer1
 
07.10.13
18:39
(22) заметил появление записи в журнале

"Описание='Error calling context method (ПолучитьОбъект)"

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

Что можно об этом сказать?

(24) Насчет ТИИ - узнал об этом только сейчас, запустил тестирование и, может быть, зря - уже несколько минут конфигуратор висит.

Версия 8.2.16.368
26 Serginio1
 
07.10.13
18:43
(25) Добавь еще  Инфо.Описание + "'"+Инфо.ИмяМодуля+ "'"+Инфо.НомерСтроки
27 wPa
 
07.10.13
18:52
документ = Документы.РасходнаяНакладная.НайтиПоНомеру(Номер).ПолучитьОбъект();

Если ЗначениеЗаполнено(документ) Тогда
ПометитьДокумент
28 wPa
 
07.10.13
18:53
точнее
документСсылка = Документы.РасходнаяНакладная.НайтиПоНомеру(Номер);

Если ЗначениеЗаполнено(документСсылка ) Тогда
ПометитьДокумент(документСсылка .ПолучитьОбъект())
29 developer1
 
07.10.13
19:08
(26)
"Описание='Error calling context method (ПолучитьОбъект)'; 'ОбщийМодуль.ПроведениеДокументов.Модуль'; 22;"

Строка 22 это

документ = ссылка.ПолучитьОбъект();
30 Славен
 
07.10.13
19:10
(29)тебе уже сказали нихрена он сылку не получил, без указания  периода найтипономеру не работает по ком
31 developer1
 
07.10.13
19:20
(28) а вот это сработало, вопрос как быть дальше? в интерфейсе 1C Предприятия этот документ есть и без каких-либо видимых проблем, также наблюдаю его в базе

(30) уже давно исправил, так что мимо
32 ilya_i
 
07.10.13
19:37
вызов .ПолучитьОбъект() выполняет код вне процедур в модуле объекта, может туда копать.
33 Serginio1
 
07.10.13
20:56
Посмотри подписчики. Ошибка может  происходить при компиляции модуля
34 Serginio1
 
08.10.13
10:17
Установи в конфигураторе Параметры\Модули\проверка галку напротив внешнее соединение. И сделай проверку модуля или проверка модулей в меню конфигурация
35 developer1
 
08.10.13
12:55
Я ошибся с утверждением насчет ЗначениеЗаполнено(ссылка). Все нормально и через COM.

(34) сделал, в модуле РасходнаяНакладная нашлась ошибка

{Документ.РасходнаяНакладная.МодульОбъекта(201,98)}: Переменная не определена (глВалютаУпр)
    Запрос.УстановитьПараметр("Курс",(КурсДокумента/КратностьДокумента)/ПолучитьКурсКратностьВалюты(<<?>>глВалютаУпр,Дата)); (Проверка: Внешнее соединение)

глВалютаУпр как я понял - глобальная переменная, устанавливаемая при запуске приложения

// Обработка события ПриНачалеРаботыСистемы
Процедура ПриНачалеРаботыСистемы()
...    глВалютаУпр=Константы.ВалютаУправленческогоУчета.Получить();

строка 201 с ошибкой это в
Процедура ОбработкаПроведения
вызов которой так и не осуществляется, ошибка в ПолучитьОбъект - раньше, может ли все равно это быть причиной? Заметил, что подобной ошибки для "Толстый клиент" нет.

И тем не менее. Как-то удалось получить подробную ошибку в журнале

{ОбщийМодуль.ПроведениеДокументов.Модуль(22)}: Error calling context method (ПолучитьОбъект)
            документ = ссылка.ПолучитьОбъект();
because:
No element selected!

то есть проверка ЗначениеЗаполнено(ссылка) проходит, а дальше не удается получить объект.
36 developer1
 
08.10.13
13:10
Так, это все в модуле "Модуль обычного приложения", а в "Модуль внешнего соединения" ничего нет.

Режим запуска приложения - "Обычное приложение".

В этом причина?
37 developer1
 
08.10.13
13:33
Да :). там уже другие ошибки, но они хотя бы "постоянны" и информативны.
Спасибо
38 Serginio1
 
08.10.13
13:38
Для интереса сделай так
#Если НЕ ВнешнееСоединение Тогда
Запрос.УстановитьПараметр("Курс",(КурсДокумента/КратностьДокумента)/ПолучитьКурсКратностьВалюты(глВалютаУпр,Дата));
#иначе
Запрос.УстановитьПараметр("Курс",(КурсДокумента/КратностьДокумента)/ПолучитьКурсКратностьВалюты(Константы.ВалютаУправленческогоУчета.Получить(),Дата));
#КонецЕсли
39 Serginio1
 
08.10.13
13:42
Или пропиши в модуле внешнего соединения эту переменную и метод
40 developer1
 
08.10.13
16:07
(39) ну я сразу так и сделал, таким образом заработало
Оптимист верит, что мы живем в лучшем из миров. Пессимист боится, что так оно и есть.