Имя: Пароль:
1C
1С v8
Удаление объектов в 1С при работе через COM (С#)
0 Tezcatlipoka
 
16.06.16
05:26
Всем добрый день. Прошу вашего совета.
Работаю с 1С через COM-соединение из внешнего приложения на C#. При попытке пометить на удаление элемент справочника "Файлы" вылетает с ошибкой "адресат вызова создал исключение" т.е. исключение возникает в самой 1С. (и через реквизит "ПометкаУдаления" и через функцию "УстановитьПометкуУдаления").
Причем такое поведение наблюдается только у данного справочника. Элементы других справочников без ошибок метятся на удаление.
В конфигурацию никаких изменений не вносилось. Подключение к 1С идет через учетную запись администратора с полными правами.
Из самой 1С файл метится на удаление без проблем. Так же, писал внешнюю обработку - файл так же метится без проблем.
Пока приходится просто удалять файлы. Но это оставляет "битые ссылки" что может быть потенциально опасно для базы.
Подскажите пожалуйста, в чем может быть проблема или хотя бы в каком направлении искать. Заранее, спасибо.
Работаю в:
1С Предприятие 8.3.6.2421
Документооборот 8 КОРП 2.0.15.6
1 Prog111
 
16.06.16
05:49
(0) Случайно не предопределенные элементы справочника?
2 varyag
 
16.06.16
05:54
а у справочника в правах данного пользователя удаление есть?
3 Tezcatlipoka
 
16.06.16
06:22
В данном случае я пытаюсь работать с элементами справочника "Файлы".
Права есть - руками в настройках прав выставил полный доступ.
4 Tezcatlipoka
 
16.06.16
06:25
Файлы с которыми я работаю я сам же и создаю через общий модуль РаботаСФайламиВызовСервера.СоздатьФайлНаОсновеФайлаНаДиске()
5 catena
 
16.06.16
06:33
(4)Может в справочнике что-то обрабатывается ПриЗаписи, ПередЗаписью?
6 Tezcatlipoka
 
16.06.16
06:43
Как я уже говорил выше - в конфигурацию изменений не вносилось и из самой 1С и внешних обработок объекты метятся. Так что там все стандартно.
7 Prog111
 
16.06.16
06:49
(6) Стандартно-то стандартно... Но возможно, что изначально прописано, что из формы помечаться может, а по соединению - какие-то условия не срабатывают. И покажи код, которым соединяешься.
8 catena
 
16.06.16
06:56
(6)Область действия кода могла быть не рассчитана на внешнее подключение.
9 Tezcatlipoka
 
16.06.16
06:58
Подключался двумя способами.
10 Tezcatlipoka
 
16.06.16
06:58
static void OldConnect()
        {
            dynamic connection;
            dynamic file;
            dynamic document;
            IV8COMConnector comConnector;
            Debug.WriteLine("Пытаемся подключиться к 1С.");
            try
            {
                comConnector = new COMConnector();
                connection = comConnector.Connect(connectionStringTest);
                Debug.WriteLine("Успешное подключение.");
            }
            catch (Exception exception)
            {
                comConnector = null;
                connection = null;
                Debug.WriteLine("Ошибка подключения:" + exception.Message);
            }

            file = connection.Справочники.Файлы.НайтиПоКоду("00-00024399").ПолучитьОбъект();
            Console.WriteLine(file.Наименование.ToString());
            //file = connection.Справочники.Файлы.НайтиПоКоду("00-00024347").ПолучитьОбъект();
            //document = connection.Справочники.ВнутренниеДокументы.НайтиПоКоду("0000-000950").ПолучитьОбъект();
            file.УстановитьПометкуУдаления(true);
            //file.ПометкаУдаления = true;
            //file.Записать();

            file = null;
            document = null;
            connection = null;
            comConnector = null;
        }
11 Tezcatlipoka
 
16.06.16
06:59
static void NewConnect()
        {
            var v83ComConnector = Type.GetTypeFromProgID("V83.ComConnector");
            var v83 = Activator.CreateInstance(v83ComConnector);
            object[] arguments = { "Srvr=\"" + serverT + "\";Ref=\"" + dataBaseT + "\";Usr=\"" + user + "\";Pwd=\"" + password + "\";" };
            var x = v83ComConnector.InvokeMember("Connect", BindingFlags.Public| BindingFlags.InvokeMethod|BindingFlags.Static, null, v83, arguments);
            var br = GetObjectProperty(v83, x, "Справочники");
            var files = GetObjectProperty(v83, br, "Файлы");
            var fileRef = InvokeObjectMethod(v83, files, "НайтиПоКоду", new object[] { "00-00024399" });
            var fileObj = InvokeObjectMethod(v83, fileRef, "ПолучитьОбъект", new object[] {});
            var internalDocuments = GetObjectProperty(v83, br, "ВнутренниеДокументы");
            //var intDocRef = InvokeObjectMethod(v83, internalDocuments, "НайтиПоКоду", new object[] { "0000-000953" });
            //var intDocObj = InvokeObjectMethod(v83, intDocRef, "ПолучитьОбъект", new object[] {});

            //var tmp = SetObjectProperty(v83, fileObj, "ПометкаУдаления", new object[] {true});
            //var tmp2 = InvokeObjectMethod(v83, fileObj, "Записать", new object[] {});
            var result = InvokeObjectMethod(v83, fileObj, "УстановитьПометкуУдаления", new object[] {true});
        }

        public static object GetObjectProperty(object v83, object refObject, string propertyName)
        {
            return v83.GetType().InvokeMember(propertyName, BindingFlags.GetProperty, null, refObject, null);
        }
        public static  object InvokeObjectMethod(object v83, object refObject, string methodName, object[] parameters)
        {
            return v83.GetType().InvokeMember(methodName, BindingFlags.Public | BindingFlags.NonPublic| BindingFlags.InvokeMethod | BindingFlags.Static | BindingFlags.Instance , null, refObject, parameters);
        }
        public static object SetObjectProperty(object v83, object refObject, string propertyName, object[] parameters)
        {
            return v83.GetType().InvokeMember(propertyName, BindingFlags.SetProperty, null, refObject, parameters);
        }
12 Tezcatlipoka
 
16.06.16
07:03
Как можно видеть, пробовал работать с Внутренними документами и файлами. Внутренние документы без проблем метятся. Так же пробовал и с другими объектами справочников - они тоже метятся.
13 Prog111
 
16.06.16
07:14
file.УстановитьПометкуУдаления(true);
            //file.ПометкаУдаления = true;

            //file.Записать();

Почему 2 последние строчки закомментированы?
14 arsik
 
гуру
16.06.16
07:18
(12) Посмотри что пишется в журнале регистрации 1С.
15 Провинциальный 1сник
 
16.06.16
07:20
А если попробовать то же самое, но не из дотнета, а из другой базы 1с?
16 Tezcatlipoka
 
16.06.16
07:21
Потому что пробовал двумя способами пометить.
Первый - через УстановитьПометкуУдаления(true), а второй - через реквизит ПометкаУдаления и непосредственную запись объекта. В обоих случаях валится в ошибку с NullReferenceExeption.

Журнал не смотрел. Сейчас взгляну.
17 Tezcatlipoka
 
16.06.16
07:35
Попробовать из другой базы, конечно, можно. Но это ничего не даст. Речь о взаимодействии с 1С из внешнего приложения написанного на C#, так что от дотнета я все равно никуда не смогу уйти.
18 Провинциальный 1сник
 
16.06.16
07:38
(17) Как минимум, это даст более четкую локализацию проблемы
19 Tezcatlipoka
 
16.06.16
07:46
В журнале регистрации при ошибках пометки на удаление для файла появляется запись следующего содержания:
Событие: Данные.Изменение
Статус транзакции:Отменена
Метаданные: Регистр сведений. Дескрипторы доступа для файлов.
20 hhhh
 
16.06.16
07:49
(19) значит прав нет на этот регистр сведений
21 Tezcatlipoka
 
16.06.16
07:57
Я работаю под админом с полными правами. Сейчас специально проверил - на этот регистр права на чтение, изменение, просмотр, редактирование и управление итогами.
22 Nuobu
 
16.06.16
09:34
Еще вариант: срабатывает подписка на событие, текст процедуры которой находится в модуле без галки "Внешнее подключение".
23 Tezcatlipoka
 
16.06.16
09:40
Благодарю. О варианте с подпиской не думал. Надо проверить.
24 Tezcatlipoka
 
16.06.16
10:44
Проблема решена.
В большинстве процедур и функций работы с файлами встречается вот такой кусочек кода который, собственно, и не давал помечать файл из COM:

Если Источник.ОбменДанными.Загрузка Тогда
        Возврат;
    КонецЕсли;

D моем случае всегда у полученного объекта файла значение ОбменДанными.Загрузка было равно Ложь. Проблема решилась тривиально:

    dynamic file = connection.Справочники.Файлы.НайтиПоКоду("00-00024399").ПолучитьОбъект();
    file.ОбменДанными.Загрузка = true;
    file.УстановитьПометкуУдаления(true, true);

Всё работает, пометка ставится и снимается корректно. Всем огромное спасибо за советы и оперативную помощь. )
25 hhhh
 
16.06.16
19:45
(24) Источник.ОбменДанными.Загрузка должно быть Ложь. Вы не то нашли.
26 КМ155
 
16.06.16
20:15
(25) он то нашёл
27 Torquader
 
16.06.16
21:46
ОбменДанными.Загрузка=ИСТИНА переключает 1С в режим обязательной записи, то есть выключаются любые проверки корректности и т.п.
Конечно, таким образом, пометка удаления поставится, но, вполне вероятно, что в регистре "Регистр сведений. Дескрипторы доступа для файлов" были какие-то данные помечаемого файла, которые не позволяли это делать.
И вот - данные остались, а файл - пометился.

P.S. использование ОбменДанными.Загрузка даже выключает контроль уникальности кодов в справочнике - так что нужно быть очень аккуратным.
28 hhhh
 
16.06.16
21:53
(26) он теперь везде будет лепить эту свою находку: Источник.ОбменДанными.Загрузка = Истина;

и у него и в проведении будет фигня и половина подписок не будет выполняться, потому что в подписках везде эта проверка.
29 Torquader
 
16.06.16
22:41
(28) При установке ОбменДанными.Загрузка=ИСТИНА запись с проведением обычно не выполняется, но можно у документа поставить "Проведен=ИСТИНА" и просто записать, а потом удивляться - что это у нас вместо учёта в базе слово из четырёх букв.
30 Tezcatlipoka
 
27.06.16
04:28
Уважаемый hhhh - возможно, я не прав, используя Источник.ОбменДанными.Загрузка = Истина;
Но предложите тогда верное решение данной проблемы, если мое не верно. У всех получаемых мной файлов всегда Источник.ОбменДанными.Загрузка равно Ложь. И при таком значении данного атрибута функция записи файла для установки пометки удаления просто не сработает.
31 Serginio1
 
27.06.16
06:45
void УничтожитьОбъект(object Объект)
        {
            Marshal.Release(Marshal.GetIDispatchForObject(Объект));
            Marshal.ReleaseComObject(Объект);


        }


ну и вызов
                УничтожитьОбъект(Object1C);
                 Object1C = null;

/// Можешь и не один
        GC.Collect();
        GC.WaitForPendingFinalizers();
32 hhhh
 
27.06.16
07:51
(30) надо искать ошибку. Режим загрузка = Истина  это выключение обычного режима работы программы. То есть лучше просто тогда непосредственно удалить - это будет меньше вреда для базы.
33 DES
 
27.06.16
09:09
а разве при работе через ком нельзя пройти момент удаления под отладчиком ?
34 VensHak
 
27.06.16
09:49
(30) также и я могу ошибаться, но проверьте из режима предприятия этот справочник. У элементов справочника есть реквизит "редактирует" где хранится имя пользователя, который не закрыл редактирование файла. И если реквизит не пустой, то пометить на удаление этот элемент нельзя.