Обновлено 27.08.2022
Добрый день! Уважаемые читатели IT блога Pyatilistnik.org, в прошлый раз мы с вами разобрали за, что отвечает библиотека vcruntime140.dll и на сколько она важна для работы многих программ. Сегодня я хочу вам рассказать, об интересном случае, когда специализированный софт может не получить доступ к удаленному компьютеры по RPC протоколу из-за новых политик безопасности DCOM. В логах будет фигурировать событие об ошибке DCOM ID 10036 «политика уровня проверки подлинности на стороне сервера не разрешает пользователю». Давайте смотреть в чем дело.
❌Описание ошибки DCOM ID 10036 (EOleException)
Обратился ко мне мой коллега с просьбой показать ему, как отправлять сообщение всем пользователям терминального хоста. Я предложил ему бесплатную утилиту Terminal Services Manager и подумал, что задача выполнена, но не тут то было. Коллега сказал, что у него не подключается к RDSH хосту и высвечивается ошибка доступа. Я решил так же проверить данную ситуацию.
Запустив Terminal Services Manager, в логе я увидел вот такую ошибку подключения:
Сразу отмечу, что права на удаленный сервер у меня были и сетевая доступность присутствовала. Первым делом я полез на сам сервер, куда не удавалось произвести подключение. В логах системы я обнаружил массовую ошибку:
ID 10036: Политика уровня проверки подлинности на стороне сервера не разрешает пользователю ROOTsem SID (S-1-5-21-551888299-3078463796-123456789-46162) с адреса 10.11.11.210 для активации DCOM-сервера. Повысьте уровень проверки подлинности активации, чтобы RPC_C_AUTHN_LEVEL_PKT_INTEGRITY в клиентском приложении. («The server-side authentication level policy does not allow the user ROOTsem SID (S-1-5-21-551888299-3078463796-123456789-46162) from address 10.11.11.210 to activate DCOM server. Please raise the activation authentication level at least to RPC_C_AUTHN_LEVEL_PKT_INTEGRITY in client application.»)
Давайте выяснять в чем дело и как это можно обойти.
⚙️Причина ошибки DCOM ID 10036
Первое, что я стал изучать, что такое RPC_C_AUTHN_LEVEL_PKT_INTEGRITY. В итоге я наткнулся на статью Microsoft о константах уровня аутентификации.
Константы уровня аутентификации представляют собой уровни аутентификации, передаваемые различным функциям времени выполнения. Эти уровни перечислены в порядке возрастания аутентификации. Каждый новый уровень добавляет к аутентификации, обеспечиваемой предыдущим уровнем. Если библиотека времени выполнения RPC не поддерживает указанный уровень, она автоматически обновляется до следующего более высокого поддерживаемого уровня.
В итоге есть вот такой список констант:
- RPC_C_AUTHN_LEVEL_DEFAULT — Использует уровень проверки подлинности по умолчанию для указанной службы проверки подлинности.
- RPC_C_AUTHN_LEVEL_NONE — Не выполняет аутентификацию.
- RPC_C_AUTHN_LEVEL_CONNECT — Аутентифицируется только тогда, когда клиент устанавливает связь с сервером.
- RPC_C_AUTHN_LEVEL_CALL — Выполняет аутентификацию только в начале каждого вызова удаленной процедуры, когда сервер получает запрос. Не применяется к удаленным вызовам процедур, выполненным с использованием последовательностей протоколов на основе соединения (тех, которые начинаются с префикса «ncacn»). Если последовательность протокола в дескрипторе привязки представляет собой последовательность протокола на основе соединения, и вы указываете этот уровень, эта процедура вместо этого использует константу RPC_C_AUTHN_LEVEL_PKT.
- RPC_C_AUTHN_LEVEL_PKT — Аутентифицирует только то, что все полученные данные получены от ожидаемого клиента. Не проверяет сами данные.
- RPC_C_AUTHN_LEVEL_PKT_INTEGRITY — Аутентифицирует и проверяет, что никакие данные, передаваемые между клиентом и сервером, не были изменены.
- RPC_C_AUTHN_LEVEL_PKT_PRIVACY — Включает все предыдущие уровни и гарантирует, что данные в открытом виде могут быть видны только отправителю и получателю. В локальном случае это предполагает использование безопасного канала. В удаленном случае это включает шифрование значения аргумента каждого удаленного вызова процедуры.
Теперь стало понятно, за что отвечает RPC_C_AUTHN_LEVEL_PKT_INTEGRITY и видимо Microsoft, ужесточила какую-то политику безопасности, я стал изучать вопрос дальше. Поиск ошибки DCOM ID 10036 привел меня ну обсуждение нового обновления KB5004442, которое как я выяснил и вызывает эту ситуацию.
KB5004442 призвана усилить защиту DCOM объектов. Удаленный протокол модели распределенных компонентов (DCOM) — это протокол для предоставления объектов приложений с помощью удаленных вызовов процедур (RPC). DCOM используется для связи между программными компонентами сетевых устройств. Многие из нас на самом деле не понимают этого, и мы не можем диагностировать ошибки DCOM в наших журналах событий, которые, по-видимому, не оказывают серьезного влияния на наши сети. Эта технология представляет собой протокол для предоставления объектов приложения с помощью удаленных вызовов процедур (RPC).
RPC являются ключевой частью Windows. RPC — это клиент-серверный протокол, который разработчики приложений могут использовать для вызова процедур на локальном или удаленном узле в сети. Детали подключения и сортировка данных выполняются за кулисами на уровне RPC, что дает разработчикам средства для прямого подключения клиентских приложений к удаленному компьютеру. Это позволяет разработчикам не беспокоиться о знании деталей того, как данные передаются между двумя машинами и как вызываются процедуры.
С обновлениями безопасности от 14 июня 2022 г. RPC_C_AUTHN_LEVEL_PKT_INTEGRITY на серверах DCOM теперь включен по умолчанию. Клиент, которому это необходимо, может отключить его с помощью раздела реестра RequireIntegrityActivationAuthenticationLevel.
Согласно бюллетеню, злоумышленник сначала воспользуется уязвимостью, предложив клиенту DCOM каким-либо образом подключиться к специально созданному серверу, как правило, отправив пользователю фишинговое электронное письмо, чтобы завладеть системой. Затем злоумышленник использует эту информацию для доступа к серверу DCOM, а затем скомпрометирует его. Патч исправляет и усиливает аутентификацию, используемую между клиентами и серверами DCOM.
Я проверил RDSH хосты и действительно там прилетело данное обновление. Microsoft пока полностью не закрутило данную политику безопасности и ее еще можно обойти, но самое правильное, это доделать приложение, чтобы оно при обращении к серверу и запросе данных выполняло все требования вендора. На текущий момент есть вот такой график внедрения:
- 8 июня 2021 г. — Изменения защиты отключены по умолчанию, но с возможностью включить их с помощью ключа реестра.
- 14 июня 2022 г. — Защитные изменения включены по умолчанию, но с возможностью отключить их с помощью ключа реестра.
- 14 марта 2023 г. — Усиление изменений включено по умолчанию, отключить их невозможно. К этому моменту вы должны решить все проблемы совместимости с усиливающими изменениями и приложениями в вашей среде.
Еще список обновлений несущих данное изменение: Windows Server 2022 — KB5005619, KB5005568. Windows 10, version 2004, Windows 10, version 20H2, Windows 10, version 21H1 — KB5005101. Windows Server 2019, Windows 10, version 1809 — KB5005102. Windows Server 2016, Windows 10, version 1607 — KB5005573. Windows Server 2012 R2 and Windows 8.1 — KB5006714. Данный список всегда меняется, так что смотрите в каталоге центра обновлений, что чем заменяется (https://www.catalog.update.microsoft.com/).
Так же помимо события ID 10036, есть еще два:
ID 10037: «Приложение %1 с PID %2 запрашивает активацию CLSID %3 на компьютере %4 с явно заданным уровнем аутентификации %5. Минимальный уровень аутентификации активации, требуемый DCOM, — 5 (RPC_C_AUTHN_LEVEL_PKT_INTEGRITY). Чтобы повысить уровень аутентификации активации, пожалуйста, обратитесь к поставщику приложения». («Application %1 with PID %2 is requesting to activate CLSID %3 on computer %4 with explicitly set authentication level at %5. The lowest activation authentication level required by DCOM is 5(RPC_C_AUTHN_LEVEL_PKT_INTEGRITY). To raise the activation authentication level, please contact the application vendor.»)
ID 10038: «Приложение %1 с PID %2 запрашивает активацию CLSID %3 на компьютере %4 с уровнем аутентификации активации по умолчанию %5. Минимальный уровень аутентификации активации, требуемый DCOM, — 5 (RPC_C_AUTHN_LEVEL_PKT_INTEGRITY). Чтобы повысить уровень аутентификации активации, пожалуйста, обратитесь к поставщику приложения». («Application %1 with PID %2 is requesting to activate CLSID %3 on computer %4 with default activation authentication level at %5. The lowest activation authentication level required by DCOM is 5(RPC_C_AUTHN_LEVEL_PKT_INTEGRITY). To raise the activation authentication level, please contact the application vendor.»)
- %1 — путь к приложению
- %2 — PID приложения
- %3 — CLSID класса COM, который приложение запрашивает для активации
- %4 — имя компьютера
- %5 — значение уровня аутентификации
💡Как устранить ошибку ID 10036
Первое, что вы должны сделать, это установить все доступные обновления, как на стороне сервера, куда идет подключение, так и на стороне системы откуда идет подключение. Напоминаю, что последнего можно найти в тексте ошибки:
ID 10036: Политика уровня проверки подлинности на стороне сервера не разрешает пользователю ROOTsem SID (S-1-5-21-551888299-3078463796-123456789-46162) с адреса 10.11.11.210 для активации DCOM-сервера. Повысьте уровень проверки подлинности активации, чтобы RPC_C_AUTHN_LEVEL_PKT_INTEGRITY в клиентском приложении.
Тут IP-адрес откуда идет подключение 10.11.11.210, там и нужно установить все возможные обновления безопасности.
Как только я обновился, ошибка EOleException ушла и мой Terminal Services Manager успешно подключился к серверу.
Если по каким, то причинам ваше приложение не заработало, а вам нужно, то есть лазейка до 2023 года в виде ключа реестра, который вы должны добавить на сервере, куда вы пытаетесь производить подключение. Запустите реестр Windows и перейдите в раздел:
HKEY_LOCAL_MACHINESOFTWARE MicrosoftOleAppCompat
И создайте там ключ реестра с типом REG_DWORD (32-бита) с именем RequireIntegrityActivationAuthenticationLevel.
- RequireIntegrityActivationAuthenticationLevel = 0x00000000 выключает политику
- RequireIntegrityActivationAuthenticationLevel = 0x00000001 включает политику
не забываем после создания ключа в реестре Windows произвести перезагрузку сервера
Если и данный метод вам не помог, то как крайняя мера может быть, это удаление обновления. Посмотрите список установленных обновлений командой:
После чего просто прочитайте инструкцию, как это сделать. Надеюсь, что вам оказалась полезна данная статья, и вы устранили ошибку EOleException. Если остались вопросы, то пишите их в комментариях. С вами был Иван Сёмин, автор и создатель IT портала Pyatilistnik.org.
Дополнительные ссылки
- https://docs.microsoft.com/en-us/windows/win32/rpc/authentication-level-constants
- https://support.microsoft.com/en-us/topic/kb5004442-manage-changes-for-windows-dcom-server-security-feature-bypass-cve-2021-26414-f1400b52-c141-43d2-941e-37ed901c769c
- https://msrc.microsoft.com/update-guide/vulnerability/CVE-2021-26414
Обновлено 27.08.2022
Добрый день! Уважаемые читатели IT блога Pyatilistnik.org, в прошлый раз мы с вами разобрали за, что отвечает библиотека vcruntime140.dll и на сколько она важна для работы многих программ. Сегодня я хочу вам рассказать, об интересном случае, когда специализированный софт может не получить доступ к удаленному компьютеры по RPC протоколу из-за новых политик безопасности DCOM. В логах будет фигурировать событие об ошибке DCOM ID 10036 «политика уровня проверки подлинности на стороне сервера не разрешает пользователю». Давайте смотреть в чем дело.
❌Описание ошибки DCOM ID 10036 (EOleException)
Обратился ко мне мой коллега с просьбой показать ему, как отправлять сообщение всем пользователям терминального хоста. Я предложил ему бесплатную утилиту Terminal Services Manager и подумал, что задача выполнена, но не тут то было. Коллега сказал, что у него не подключается к RDSH хосту и высвечивается ошибка доступа. Я решил так же проверить данную ситуацию.
Запустив Terminal Services Manager, в логе я увидел вот такую ошибку подключения:
Сразу отмечу, что права на удаленный сервер у меня были и сетевая доступность присутствовала. Первым делом я полез на сам сервер, куда не удавалось произвести подключение. В логах системы я обнаружил массовую ошибку:
ID 10036: Политика уровня проверки подлинности на стороне сервера не разрешает пользователю ROOTsem SID (S-1-5-21-551888299-3078463796-123456789-46162) с адреса 10.11.11.210 для активации DCOM-сервера. Повысьте уровень проверки подлинности активации, чтобы RPC_C_AUTHN_LEVEL_PKT_INTEGRITY в клиентском приложении. («The server-side authentication level policy does not allow the user ROOTsem SID (S-1-5-21-551888299-3078463796-123456789-46162) from address 10.11.11.210 to activate DCOM server. Please raise the activation authentication level at least to RPC_C_AUTHN_LEVEL_PKT_INTEGRITY in client application.»)
Давайте выяснять в чем дело и как это можно обойти.
⚙️Причина ошибки DCOM ID 10036
Первое, что я стал изучать, что такое RPC_C_AUTHN_LEVEL_PKT_INTEGRITY. В итоге я наткнулся на статью Microsoft о константах уровня аутентификации.
Константы уровня аутентификации представляют собой уровни аутентификации, передаваемые различным функциям времени выполнения. Эти уровни перечислены в порядке возрастания аутентификации. Каждый новый уровень добавляет к аутентификации, обеспечиваемой предыдущим уровнем. Если библиотека времени выполнения RPC не поддерживает указанный уровень, она автоматически обновляется до следующего более высокого поддерживаемого уровня.
В итоге есть вот такой список констант:
- RPC_C_AUTHN_LEVEL_DEFAULT — Использует уровень проверки подлинности по умолчанию для указанной службы проверки подлинности.
- RPC_C_AUTHN_LEVEL_NONE — Не выполняет аутентификацию.
- RPC_C_AUTHN_LEVEL_CONNECT — Аутентифицируется только тогда, когда клиент устанавливает связь с сервером.
- RPC_C_AUTHN_LEVEL_CALL — Выполняет аутентификацию только в начале каждого вызова удаленной процедуры, когда сервер получает запрос. Не применяется к удаленным вызовам процедур, выполненным с использованием последовательностей протоколов на основе соединения (тех, которые начинаются с префикса «ncacn»). Если последовательность протокола в дескрипторе привязки представляет собой последовательность протокола на основе соединения, и вы указываете этот уровень, эта процедура вместо этого использует константу RPC_C_AUTHN_LEVEL_PKT.
- RPC_C_AUTHN_LEVEL_PKT — Аутентифицирует только то, что все полученные данные получены от ожидаемого клиента. Не проверяет сами данные.
- RPC_C_AUTHN_LEVEL_PKT_INTEGRITY — Аутентифицирует и проверяет, что никакие данные, передаваемые между клиентом и сервером, не были изменены.
- RPC_C_AUTHN_LEVEL_PKT_PRIVACY — Включает все предыдущие уровни и гарантирует, что данные в открытом виде могут быть видны только отправителю и получателю. В локальном случае это предполагает использование безопасного канала. В удаленном случае это включает шифрование значения аргумента каждого удаленного вызова процедуры.
Теперь стало понятно, за что отвечает RPC_C_AUTHN_LEVEL_PKT_INTEGRITY и видимо Microsoft, ужесточила какую-то политику безопасности, я стал изучать вопрос дальше. Поиск ошибки DCOM ID 10036 привел меня ну обсуждение нового обновления KB5004442, которое как я выяснил и вызывает эту ситуацию.
KB5004442 призвана усилить защиту DCOM объектов. Удаленный протокол модели распределенных компонентов (DCOM) — это протокол для предоставления объектов приложений с помощью удаленных вызовов процедур (RPC). DCOM используется для связи между программными компонентами сетевых устройств. Многие из нас на самом деле не понимают этого, и мы не можем диагностировать ошибки DCOM в наших журналах событий, которые, по-видимому, не оказывают серьезного влияния на наши сети. Эта технология представляет собой протокол для предоставления объектов приложения с помощью удаленных вызовов процедур (RPC).
RPC являются ключевой частью Windows. RPC — это клиент-серверный протокол, который разработчики приложений могут использовать для вызова процедур на локальном или удаленном узле в сети. Детали подключения и сортировка данных выполняются за кулисами на уровне RPC, что дает разработчикам средства для прямого подключения клиентских приложений к удаленному компьютеру. Это позволяет разработчикам не беспокоиться о знании деталей того, как данные передаются между двумя машинами и как вызываются процедуры.
С обновлениями безопасности от 14 июня 2022 г. RPC_C_AUTHN_LEVEL_PKT_INTEGRITY на серверах DCOM теперь включен по умолчанию. Клиент, которому это необходимо, может отключить его с помощью раздела реестра RequireIntegrityActivationAuthenticationLevel.
Согласно бюллетеню, злоумышленник сначала воспользуется уязвимостью, предложив клиенту DCOM каким-либо образом подключиться к специально созданному серверу, как правило, отправив пользователю фишинговое электронное письмо, чтобы завладеть системой. Затем злоумышленник использует эту информацию для доступа к серверу DCOM, а затем скомпрометирует его. Патч исправляет и усиливает аутентификацию, используемую между клиентами и серверами DCOM.
Я проверил RDSH хосты и действительно там прилетело данное обновление. Microsoft пока полностью не закрутило данную политику безопасности и ее еще можно обойти, но самое правильное, это доделать приложение, чтобы оно при обращении к серверу и запросе данных выполняло все требования вендора. На текущий момент есть вот такой график внедрения:
- 8 июня 2021 г. — Изменения защиты отключены по умолчанию, но с возможностью включить их с помощью ключа реестра.
- 14 июня 2022 г. — Защитные изменения включены по умолчанию, но с возможностью отключить их с помощью ключа реестра.
- 14 марта 2023 г. — Усиление изменений включено по умолчанию, отключить их невозможно. К этому моменту вы должны решить все проблемы совместимости с усиливающими изменениями и приложениями в вашей среде.
Еще список обновлений несущих данное изменение: Windows Server 2022 — KB5005619, KB5005568. Windows 10, version 2004, Windows 10, version 20H2, Windows 10, version 21H1 — KB5005101. Windows Server 2019, Windows 10, version 1809 — KB5005102. Windows Server 2016, Windows 10, version 1607 — KB5005573. Windows Server 2012 R2 and Windows 8.1 — KB5006714. Данный список всегда меняется, так что смотрите в каталоге центра обновлений, что чем заменяется (https://www.catalog.update.microsoft.com/).
Так же помимо события ID 10036, есть еще два:
ID 10037: «Приложение %1 с PID %2 запрашивает активацию CLSID %3 на компьютере %4 с явно заданным уровнем аутентификации %5. Минимальный уровень аутентификации активации, требуемый DCOM, — 5 (RPC_C_AUTHN_LEVEL_PKT_INTEGRITY). Чтобы повысить уровень аутентификации активации, пожалуйста, обратитесь к поставщику приложения». («Application %1 with PID %2 is requesting to activate CLSID %3 on computer %4 with explicitly set authentication level at %5. The lowest activation authentication level required by DCOM is 5(RPC_C_AUTHN_LEVEL_PKT_INTEGRITY). To raise the activation authentication level, please contact the application vendor.»)
ID 10038: «Приложение %1 с PID %2 запрашивает активацию CLSID %3 на компьютере %4 с уровнем аутентификации активации по умолчанию %5. Минимальный уровень аутентификации активации, требуемый DCOM, — 5 (RPC_C_AUTHN_LEVEL_PKT_INTEGRITY). Чтобы повысить уровень аутентификации активации, пожалуйста, обратитесь к поставщику приложения». («Application %1 with PID %2 is requesting to activate CLSID %3 on computer %4 with default activation authentication level at %5. The lowest activation authentication level required by DCOM is 5(RPC_C_AUTHN_LEVEL_PKT_INTEGRITY). To raise the activation authentication level, please contact the application vendor.»)
- %1 — путь к приложению
- %2 — PID приложения
- %3 — CLSID класса COM, который приложение запрашивает для активации
- %4 — имя компьютера
- %5 — значение уровня аутентификации
💡Как устранить ошибку ID 10036
Первое, что вы должны сделать, это установить все доступные обновления, как на стороне сервера, куда идет подключение, так и на стороне системы откуда идет подключение. Напоминаю, что последнего можно найти в тексте ошибки:
ID 10036: Политика уровня проверки подлинности на стороне сервера не разрешает пользователю ROOTsem SID (S-1-5-21-551888299-3078463796-123456789-46162) с адреса 10.11.11.210 для активации DCOM-сервера. Повысьте уровень проверки подлинности активации, чтобы RPC_C_AUTHN_LEVEL_PKT_INTEGRITY в клиентском приложении.
Тут IP-адрес откуда идет подключение 10.11.11.210, там и нужно установить все возможные обновления безопасности.
Как только я обновился, ошибка EOleException ушла и мой Terminal Services Manager успешно подключился к серверу.
Если по каким, то причинам ваше приложение не заработало, а вам нужно, то есть лазейка до 2023 года в виде ключа реестра, который вы должны добавить на сервере, куда вы пытаетесь производить подключение. Запустите реестр Windows и перейдите в раздел:
HKEY_LOCAL_MACHINESOFTWARE MicrosoftOleAppCompat
И создайте там ключ реестра с типом REG_DWORD (32-бита) с именем RequireIntegrityActivationAuthenticationLevel.
- RequireIntegrityActivationAuthenticationLevel = 0x00000000 выключает политику
- RequireIntegrityActivationAuthenticationLevel = 0x00000001 включает политику
не забываем после создания ключа в реестре Windows произвести перезагрузку сервера
Если и данный метод вам не помог, то как крайняя мера может быть, это удаление обновления. Посмотрите список установленных обновлений командой:
После чего просто прочитайте инструкцию, как это сделать. Надеюсь, что вам оказалась полезна данная статья, и вы устранили ошибку EOleException. Если остались вопросы, то пишите их в комментариях. С вами был Иван Сёмин, автор и создатель IT портала Pyatilistnik.org.
Дополнительные ссылки
- https://docs.microsoft.com/en-us/windows/win32/rpc/authentication-level-constants
- https://support.microsoft.com/en-us/topic/kb5004442-manage-changes-for-windows-dcom-server-security-feature-bypass-cve-2021-26414-f1400b52-c141-43d2-941e-37ed901c769c
- https://msrc.microsoft.com/update-guide/vulnerability/CVE-2021-26414
← →
Василич
(2002-09-19 19:16)
[0]
Здравствуйте ! Подскажите, пожалуйста, вследствие чего появляется ошибка «EOLEException. Не удается найти строку для обновления. Некоторые значения могли быть изменены со времени ее последнего чтения». Ошибка выдается после метода Post или Requery. Везде искал, не могу найти даже описания ошибки.
← →
Василич
(2002-09-20 10:29)
[1]
Ребята, ну неужто никто не знает ?
← →
Johnmen
(2002-09-20 10:40)
[2]
Так поищи в этой конфе…
Данный вопрос задается с завидной регулярностью…:))))
← →
Василич
(2002-09-20 11:35)
[3]
Подобный вопрос отсутствует. Самое интересное, что трассировка запроса с помощью SQL Profiler ничего не дает !
← →
Юрий Жуков
(2002-09-20 13:09)
[4]
Я так понимаю ты на ADO пишеь?
Тогда тебе идти на королевство Дельфи.
Читать здесь:
http://www.delphikingdom.com/helloworld/ado01.htm
http://www.delphikingdom.com/helloworld/ado02.htm
http://www.delphikingdom.com/helloworld/ado03.htm
Тригера в таблицах есть?
← →
Василич
(2002-09-20 15:25)
[5]
Recordset.Properties[«Update Resync»].Value := adResyncNone;;
Recordset.Properties[«Update Criteria»].Value := adCriteriaAllCols;
Все равно не работает !!!
← →
Юрий Жуков
(2002-09-20 16:00)
[6]
А тригера в таблицах есть? А автоинкрементные поля?
А первичный ключ? А подумай сам чего ты еще утаил?
И лучше используй так:
Recordset.Properties[«Update Criteria»].Value := adCriteriaKey
А еще лучше пропиши
Recordset.Properties[«Resync Command»].Value := » бла — бла…»
← →
Василич
(2002-09-20 16:04)
[7]
Триггеров нет, автоинкрементное поле есть. Таблица представляет из себя кучу полей типа ID, связана с другими, дочерними таблицами. Редактирование делается простым присваиванием FieldByName(«FieldName»).AsString :=»бла-бла»
Recordset.Properties[«Update Resync»].Value := adResyncAutoIncrement + adResyncInserts;;
Recordset.Properties[«Update Criteria»].Value := adCriteriaAllCols;
if not InTransaction then
BeginTrans;
Edit;
FieldByName(«Field1»).AsString := ComboBox1.Text;
………………………
Post;
CommitTrans;
Requery();
и после Post вылетает эта ошибка.
← →
Юрий Жуков
(2002-09-20 16:40)
[8]
Ну я тебе почти правильно сказал:
Recordset.Properties[«Update Criteria»].Value := adCriteriaKey
Обовлять запись будет по первичным ключам
Если это не поможет, то ставь
Recordset.Properties[«Resync Command»].Value := » бла — бла…»
Ну если это не поможет то разве что можно на запрос посмотреь..
← →
Василич
(2002-09-20 16:47)
[9]
И что мне писать в это «bla-bla» ?
← →
Василич
(2002-09-20 18:06)
[10]
Это все, к сожалению, не помогает.
← →
Юрий Жуков
(2002-09-20 19:15)
[11]
Хм, ссылку я вроде бы давал, но вдидать ты не очень внимательно прочитал:
http://www.delphikingdom.com/helloworld/ado03.htm
Цитата:
в этом свойстве задается команда, с помощью которой должна быть обновлена текущая строка, основываясь на значении колонок из таблицы, имя которой заданно свойством «Unique Table»
Ну а апдейты к D6 стоят? Что еще посоветовать не знаю, может сам еще чего скажешь?
← →
Василич
(2002-09-23 09:45)
[12]
DataModule1.ADODataset1.Properties["Update Resync"].Value := adResyncInserts + adResyncUpdates;
DataModule1.ADODataset1.Properties["Update Criteria"].Value := adCriteriaKey;
DataModule1.ADODataset1.Properties["Unique Table"].Value := "Computers";
DataModule1.ADODataset1.Properties["Resync Command"].Value := ResyncCommand;
ResyncCommand := "SELECT C.ComputerID AS "
← →
Василич
(2002-09-23 10:40)
[13]
Я немного понял. Для того, чтобы Update отрабатывался нормально,
ВСЕ поля в таблице должны быть заполнены (не равны NULL). Может, следует каким-то образом изменить запрос ?
← →
Василич
(2002-09-23 11:15)
[14]
А это результат трассировки запроса. Никаких ошибок, никаких предупреждений…
exec sp_executesql N"UPDATE "Mspi"."dbo"."Computers" SET "ComputerID"=@P1,"Address"=@P2,"Cabinet"=@P3 WHERE "KeyField"=@P4", N"@P1 bigint,@P2 nvarchar(10),@P3 int,@P4 int", 545445, N"Ленина, 57", 21, 12
go
exec sp_executesql N"UPDATE "Mspi"."dbo"."Xeroxes" SET "Xerox"=@P1 WHERE "XeroxID" IS NULL", N"@P1 varchar(1)", ""
go
exec sp_executesql N"UPDATE "Mspi"."dbo"."Scanners" SET "Scanner"=@P1 WHERE "ScannerID"=@P2", N"@P1 varchar(4),@P2 int", "UMAX", 6
go
exec sp_executesql N"UPDATE "Mspi"."dbo"."Printers" SET "Printer"=@P1 WHERE "PrinterID"=@P2", N"@P1 varchar(29),@P2 int", "Hewlett-Packard LaserJet 1100", 4
go
exec sp_executesql N"UPDATE "Mspi"."dbo"."Monitors" SET "Monitor"=@P1 WHERE "MonitorID"=@P2", N"@P1 varchar(19),@P2 int", "SAMSUNG Samtron 75E", 3
go
exec sp_executesql N"UPDATE "Mspi"."dbo"."EtherCards" SET "EtherCard"=@P1 WHERE "EtherCardID"=@P2", N"@P1 varchar(16),@P2 int", "Surecom 100 Mbit", 2
go
exec sp_executesql N"UPDATE "Mspi"."dbo"."SoundBlasters" SET "SoundBlaster"=@P1 WHERE "SoundBlasterID" IS NULL", N"@P1 varchar(1)", ""
go
exec sp_executesql N"UPDATE "Mspi"."dbo"."CDROMs" SET "CDROM"=@P1 WHERE "CDROMID"=@P2", N"@P1 varchar(8),@P2 int", "ASUS 50x", 2
go
exec sp_executesql N"UPDATE "Mspi"."dbo"."HDDs" SET "HDD"=@P1 WHERE "HDDID"=@P2", N"@P1 varchar(14),@P2 int", "IBM DTLA 30 Gb", 2
go
exec sp_executesql N"UPDATE "Mspi"."dbo"."VideoCards" SET "VideoCard"=@P1 WHERE "VideoCardID"=@P2", N"@P1 varchar(22),@P2 int", "GeForce 4 Ti4600 64 Mb", 2
go
exec sp_executesql N"UPDATE "Mspi"."dbo"."RAMs" SET "RAM"=@P1 WHERE "RAMID"=@P2", N"@P1 smallint,@P2 int", 32, 5
go
exec sp_executesql N"UPDATE "Mspi"."dbo"."Motherboards" SET "Motherboard"=@P1 WHERE "MotherboardID"=@P2", N"@P1 varchar(4),@P2 int", "Abit", 2
go
exec sp_executesql N"UPDATE "Mspi"."dbo"."Processors" SET "Processor"=@P1 WHERE "ProcessorID"=@P2", N"@P1 varchar(35),@P2 int", "Intel Celeron 333 Mhz", 16
go
exec sp_executesql N"UPDATE "Mspi"."dbo"."Faculties" SET "Faculty"=@P1 WHERE "FacultyID"=@P2", N"@P1 nvarchar(29),@P2 int", N"Кафедра, 18
go
SELECT N"Testing Connection..."
go
EXECUTE msdb.dbo.sp_sqlagent_get_perf_counters
go
Блин, что делать-то ?
← →
MOA
(2002-09-23 13:05)
[15]
1.А вот это:
exec sp_executesql N»UPDATE «Mspi».»dbo».»Xeroxes» SET «Xerox»=@P1 WHERE «XeroxID» IS NULL», N»@P1 varchar(1)», «»
нормально («XeroxID» IS NULL)?
2. У Вас действительно при апдейте детайл-таблицы должны обновляться ВСЕ мастер-таблицы? Так и задумано?
← →
Юрий Жуков
(2002-09-23 13:22)
[16]
Ну по крайней мере видно, что вот здесь точно будет ошибка:
exec sp_executesql N»UPDATE «Mspi».»dbo».»Xeroxes» SET «Xerox»=@P1 WHERE «XeroxID» IS NULL», N»@P1 varchar(1)», «»
Да ты прав, в этом результирующем запросе все поля должны быть заполнены, что-бы АДО мог пострить по ним SQL для Update для всех подчиненных таблиц (ты ведь нигде не указал UniqueTable). Насколько я знаю нельзя указать несколько уникальных таблиц для ADODATASET.
Думаю тебе следует исользовать Uniquetable:=»Faculties»;
А редактирование всех остальных датасетов оформить в виде справочников
← →
Василич
(2002-09-23 14:53)
[17]
Редактирование остальных датасетов и так оформлено в виде справочников. Я же на самом деле редактирую не справочник (т.е. не таблицу Xeroxes), а сводную, в которой находится XeroxID.
>MOA
По идее, мастер-таблицы обновляться не должны. Пытался снять у таблицы опцию Enforce relationship for INSERTS and UPDATES, толку никакого.
Как бы там ни было, мне все-таки требуется, чтобы в некоторые поля можно было воткнуть NULL (не во всех кабинетах есть ксероксы, образно говоря). Не подскажете ли Вы, как избавиться от принудительного обновления мастер-таблиц и уничтожить в корне эту проклятую ошибку ?
← →
MOA
(2002-09-23 15:22)
[18]
>уничтожить в корне эту проклятую ошибку
Я бы сделал так:
1.Запрос:
«SELECT C.ComputerID AS «
← →
Юрий Жуков
(2002-09-23 15:42)
[19]
очень странно…
так ты говоришь поставил свойство
Properties[«Unique Table»].Value := «Computers»?
Но судя по логу профайлера ADO все равно пытается апдейтить все таблицы.
← →
Василич
(2002-09-26 14:05)
[20]
Ничего у меня не получается. Для интереса создал уникальный индекс во всех родительских таблицах, последовал всем советам MOA, и ничего не работает !!! Судя по вылетающей в этот раз ошибке («Cannot insert duplicate key») SQL Server действительно пытается засунуть записи в родительские таблицы, хотя ясно указаны все динамические свойства типа Resync Command и Unique Table. Подскажите, как избавиться от этой нездоровой тенденции SQL-сервера апдейтить таблицы, которые совершенно не нужно апдейтить !
← →
Юрий Жуков
(2002-09-26 14:32)
[21]
Эт тебе не SQL сервер надо укрощать, а ADO.
И бороть нужно свойство «Unique table».
Попробуй компонент TBetterAdoDataSet (
http://web.orbitel.bg/vassil/), там можно его disign-time задать.
← →
MOA
(2002-09-26 15:10)
[22]
Может, так:?
1. Если не хочется отказываться от VIEW — добавить отдельные DataSet-ы на вставку — обновление — удаление и перехватывать соответсвующие события, не давая «основному» датасету вставлять-удалять-обновлять
Или
2. В «Основном» датасете обращаться к детайл-таблице, оформив поля из мастер-таблиц как Lookup поля. Понадобится дополнительно столько датасетов, сколько мастер-таблиц — но обновления-удаления-вставки будут работать как ожидается + бонус — автоматом появится возможность юзеру выбирать нужные значения из Lookup-ов.
Любая таблица должна иметь PRIMARY KEY. И мастер — тоже. И это — ключ для ссылки из детайл.
А дублирующиеся ключи — это точно не ключи в детайл-таблице?
Удачи!
← →
MOA
(2002-09-26 15:25)
[23]
И еще.
1.У Вас пользователи вводят НАЗВАНИЯ? Из, возможно, формируемого программой списка? — Если так, то так не надо бы…
2.У Вас стоит у VIEW опция VIEW_METADATA?
Удачи!
← →
MOA
(2002-09-26 16:04)
[24]
Sorry, забыл, что у Вас не VIEW, a SELECT.
НО все же — попробуйте в SELECT выбирать только ссылки на мастер-таблицы (ID), а не названия.
Удачи!
← →
Василич
(2002-09-26 16:08)
[25]
Похоже, этот кошмар никогда не кончится. Сделал все по вашим советам: lookup-поля, куча датасетов, по одному на каждую таблицу, даже не датасеты, а BetterADODataSets, черт бы их побрал. Насмотрелся на кучу новых ошибок, как например, сверхинформативное сообщение «Не удается вставить или обновить столбцы из нескольких таблиц», или, «При вызове ITransaction::Commit или ITransaction::Abort объект не отвечает на запросы». Короче, пора переквалифицироваться в дворники, всем спасибо за оказанную помощь.
← →
MOA
(2002-09-26 16:13)
[26]
Покажите, пожалуйста, Ваш новый «основной» запрос.
← →
Василич
(2002-09-26 16:16)
[27]
>MOA
Не совсем понятно, что в данном контексте означает «Названия» , вот запрос для сводной таблицы:
SELECT TOP 100 PERCENT C.ComputerID AS [Серийный номер компьютера], F.Faculty AS [Факультет/Отдел], P.Processor AS Процессор,
M.Motherboard AS [Материнская плата],
R.RAM AS [Оперативная память], V.VideoCard AS Видеоадаптер,
H.HDD AS [Жесткий диск], D.CDROM AS [Привод компакт-дисков],
S.SoundBlaster AS [Звуковая карта],
E.EtherCard AS [Сетевая карта], O.Monitor AS Монитор,
N.Printer AS Принтер, A.Scanner AS Сканер, X.Xerox AS Ксерокс,
B.Address AS Адрес, Cabinet AS Кабинет
FROM dbo.Computers C LEFT OUTER JOIN
dbo.Faculties F ON F.FacultyID = C.FacultyID LEFT OUTER JOIN
dbo.Processors P ON P.ProcessorID = C.ProcessorID LEFT OUTER JOIN
dbo.Motherboards M ON M.MotherboardID = C.MotherBoardID LEFT OUTER JOIN
dbo.RAMs R ON R.RAMID = C.RAMID LEFT OUTER JOIN
dbo.VideoCards V ON V.VideoCardID=C.VideoCardID LEFT OUTER JOIN
dbo.HDDs H ON H.HDDID = C.HDDID LEFT OUTER JOIN
dbo.CDROMs D ON D.CDROMID = C.CDROMID LEFT OUTER JOIN
dbo.SoundBlasters S ON S.SoundBlasterID = C.SoundBlasterID LEFT OUTER JOIN
dbo.EtherCards E ON E.EtherCardID = C.EtherCardID LEFT OUTER JOIN
dbo.Monitors O ON O.MonitorID = C.MonitorID LEFT OUTER JOIN
dbo.Printers N ON N.PrinterID = C.PrinterID LEFT OUTER JOIN
dbo.Scanners A ON A.ScannerID = C.ScannerID LEFT OUTER JOIN
dbo.Xeroxes X ON X.XeroxID=C.XeroxID LEFT OUTER JOIN
dbo.Addresses B ON B.AddressID = C.AddressID
ORDER BY F.Faculty
Сначала это был VIEW, потом я от него отказался и впихнул этот чудовищный запрос прямо в CommandText. Пытаюсь вставлять/редактировать его обычными методами типа Append/Edit/Post, и вылетают вышеназванные ошибки. От названий полей в данном случае отказаться не могу, а то получится не нормальный пользовательский интерфейс, а черт знает что.
← →
MOA
(2002-09-26 16:35)
[28]
1. Русские названия полей = приключения. Воспользуйтесь Display label в свойстве поля.
2. Попробуйте такой запрос:
SELECT TOP 100 PERCENT C.ComputerID, C.FacultyID, C.ProcessorID,
C.MotherboardID, C.RAMID, C.VideoCardID, C.HDDID, C.CDROMID, C.SoundBlasterID, C.EtherCardID, C.MonitorID, C.PrinterID, C.ScannerID, C.XeroxID, C.AddressID, C.Cabinet
FROM dbo.Computers CORDER BY F.Faculty
Русские названия полей сделайте через Display label. Добавьте в получившийся датасет дополнительно Lookup поля для Faculity, Processor и т.д., поля с ID, соответственно, скройте от юзера (Display=False).
Всё должно поехать. Именно это я и имел в виду.
Удачи!
← →
MOA
(2002-09-26 16:36)
[29]
Русские названия, конечно же, Вам понадобятся только для созданных Вами Lookup полей. Наверное, не нужно юзеру знать русское название поля ProcessorID, например.
Удачи!
I have a Delphi 6 professional program that is calling COM object methods belonging to an MSVC 2008 COM DLL. The DLL’s Type Library imported without error into Delphi. I can call one of the method’s without error, but most of the others lead to an EOleException error with the message «An unexpected exception was raised», which corresponds to the EOleException error code: 0x80040205,
EVENT_E_INTERNALEXCEPTION:
http://msdn.microsoft.com/en-us/library/cc704587(v=prot.10).aspx
I am calling CoInitialize before making the call:
var
intfMsvcComObj: IMsvcComObject;
begin
if not Succeeded(CoInitialize(nil)) then
raise Exception.Create('Coinitialize failed.');
intfMsvcComObj := CoMsvcComObject.Create;
try
// EOleException occurs when I make this call.
intfMsvcComObj.doSomething;
finally
CoUninitialize;
end;
end;
Next I tried turning of FPU exceptions because that sometimes is an issue when calling into MSVC DLLS using Set8087CW($133f) and then I tried again with Set8087CW(Get8087CW or $3f), but neither of those operations helped.
Any ideas on how to fix/diagnose this?
I have a Delphi 6 professional program that is calling COM object methods belonging to an MSVC 2008 COM DLL. The DLL’s Type Library imported without error into Delphi. I can call one of the method’s without error, but most of the others lead to an EOleException error with the message «An unexpected exception was raised», which corresponds to the EOleException error code: 0x80040205,
EVENT_E_INTERNALEXCEPTION:
http://msdn.microsoft.com/en-us/library/cc704587(v=prot.10).aspx
I am calling CoInitialize before making the call:
var
intfMsvcComObj: IMsvcComObject;
begin
if not Succeeded(CoInitialize(nil)) then
raise Exception.Create('Coinitialize failed.');
intfMsvcComObj := CoMsvcComObject.Create;
try
// EOleException occurs when I make this call.
intfMsvcComObj.doSomething;
finally
CoUninitialize;
end;
end;
Next I tried turning of FPU exceptions because that sometimes is an issue when calling into MSVC DLLS using Set8087CW($133f) and then I tried again with Set8087CW(Get8087CW or $3f), but neither of those operations helped.
Any ideas on how to fix/diagnose this?
Я сделал два компонента ActiveX в Delphi XE2 в отдельных проектах. Один из компонентов работает отлично, и каждое исключение, которое он выдает, маскируется как EOleException. На другом компоненте ActiveX исключения не маскируются, они генерируются как исходный тип. Клиент представляет собой программу delphi XE.
Когда компонент ActiveX выдает исходное исключение, следующий вызов любого другого метода из компонента выдает исключение нарушения прав доступа в тех местах, где он не должен, например, установка локальной строковой переменной со значением. Это очень странное поведение.
Я сравнил оба проекта: файл .ridl, параметры компиляции, файл .dproj и не смог найти виновника.
Кто-нибудь знает причину этой разницы/странного поведения?
благодаря
Изменить: какой-то код
Компонент 1, который работает (маскирует все исключения для EOleException)
TspdMyClassX = class(TActiveXComponent, MyInterface)
…
initialization
TActiveXComponentFactory.Create(
ComServer,
TspdMyClassX,
CLASS_spdMyClassX,
1,
'',
0,
tmBoth);
Другой компонент, который не генерирует EOleException, имеет другой интерфейс, но остальная часть кода такая же (инициализация, родительский класс TActiveXComponent).
A Windows service when trying to access the .Body property of a MSMQ message object throws an EOleException — but only when the Xml document contained in this message has an empty list node.
The EOleException message complains about insufficient memory (exception code -2147024882). Since the exception only occurs with the smallest possible Xml document, memory cannot be the real issue. The next thing that comes to mind is a problem with access rights but then again all «good» messages (as described below) are processed without problems.
The exception can be reproduced under any thinkable condition («bad» message first, many «good» messages first — then «bad» message, run in debugger or just logging the exception); it doesn’t matter if the code shown below is run as a service or as a simple excecutable.
Using the same COM object (MSMQ.MSMQQueueInfo) from within a VBScript on the same machine does not produce any errors.
Accessing any other properties apart from .Body doesn’t throw an exception so the message object instance seems to be received sucessfully. Also the transaction receiving the message can be comitted sucessfully if the .Body property is not accessed.
Windows Service code
//...
qInfo := CreateOleObject('MSMQ.MSMQQueueInfo');
qTxDisp := CreateOleObject('MSMQ.MSMQTransactionDispenser');
//...
qTx := qTxDisp.BeginTransaction;
qMessage := qQueue.Receive(qTx, False, True, 0);
//...
sBody := qMessage.Body; //throws EOleException
The qMessage.BodyLength
property returns the value 165 for «bad» messages as shown below.
«Bad» message
<?xml version="1.0" encoding="Windows-1252"?>
<response space="" Message="Entry_7">
<query>
<entrylist count="0">
</entrylist>
</query>
</response>
This message reliably makes the service code throw an EOleExecption.
«Good» message
<?xml version="1.0" encoding="Windows-1252"?>
<response space="" Message="Entry_7">
<query>
<entrylist count="2">
<entry>
<abc>123</abc>
<def>456</def>
</entry>
<entry>
<abc>789</abc>
<def>000</def>
</entry>
</entrylist>
</query>
</response>
This message is reliably processed without problems.
The problem first occured when moving the service from a Win2003 machine to a Win2008 (32-bit Standard).
Эта тема
- Везде
-
- Эта тема
- Этот форум
-
- Расширенный поиск
Поиск
A Windows service when trying to access the .Body property of a MSMQ message object throws an EOleException — but only when the Xml document contained in this message has an empty list node.
The EOleException message complains about insufficient memory (exception code -2147024882). Since the exception only occurs with the smallest possible Xml document, memory cannot be the real issue. The next thing that comes to mind is a problem with access rights but then again all «good» messages (as described below) are processed without problems.
The exception can be reproduced under any thinkable condition («bad» message first, many «good» messages first — then «bad» message, run in debugger or just logging the exception); it doesn’t matter if the code shown below is run as a service or as a simple excecutable.
Using the same COM object (MSMQ.MSMQQueueInfo) from within a VBScript on the same machine does not produce any errors.
Accessing any other properties apart from .Body doesn’t throw an exception so the message object instance seems to be received sucessfully. Also the transaction receiving the message can be comitted sucessfully if the .Body property is not accessed.
Windows Service code
//...
qInfo := CreateOleObject('MSMQ.MSMQQueueInfo');
qTxDisp := CreateOleObject('MSMQ.MSMQTransactionDispenser');
//...
qTx := qTxDisp.BeginTransaction;
qMessage := qQueue.Receive(qTx, False, True, 0);
//...
sBody := qMessage.Body; //throws EOleException
The qMessage.BodyLength
property returns the value 165 for «bad» messages as shown below.
«Bad» message
<?xml version="1.0" encoding="Windows-1252"?>
<response space="" Message="Entry_7">
<query>
<entrylist count="0">
</entrylist>
</query>
</response>
This message reliably makes the service code throw an EOleExecption.
«Good» message
<?xml version="1.0" encoding="Windows-1252"?>
<response space="" Message="Entry_7">
<query>
<entrylist count="2">
<entry>
<abc>123</abc>
<def>456</def>
</entry>
<entry>
<abc>789</abc>
<def>000</def>
</entry>
</entrylist>
</query>
</response>
This message is reliably processed without problems.
The problem first occured when moving the service from a Win2003 machine to a Win2008 (32-bit Standard).
Материал подготовлен совместно с
Петром Федотовым
В этой статье мы постараемся рассмотреть основные ошибки, возникающие при обмене данными через коннектор 1С, способы их расследования и варианты решения.
Иногда возникает ситуация, что коннектор настроен, определены справочники, участвующие в обмене и ключевые реквизиты, настроены фильтры, а обмен не идет. Что делать в такой ситуации? С чего начать? Первым делом нужно проверить
параметры подключения к интегрированной системе:
Убедитесь, что вы правильно указали параметры подключения: имя сервера, имя базы данных, логин, пароль и имя плана обмена. Параметр
InitiateDataExchangeIn1C должен быть установлен в значение «Да», для того чтобы
автоматически запустился процесс обмена данными в системе 1С после формирования файлов с данными по плану, заданному в параметре
ExchangePlan.
Если параметры подключения указаны правильно, а обмен не идет, то стоит проверить настройки плана обмена в конфигураторе 1С:
Убедитесь, что объекты 1С, с которым вы настроили обмен, присутствует в списке выбранных объектов плана обмена. Также убедитесь, чтобы не стояло галочки «Распределенная информационная база». Излишне полный план обмена увеличивает
количество выгружаемых данных, что очень сильно влияет на скорость обмена данными. Поэтому нужно стараться максимально облегчить план обмена только необходимыми объектами. Например, на приведенном выше скриншоте в плане обмена оставлены только необходимые
для интеграции объекты 1С (4 справочника и 1 план видов характеристик).
Еще одной распространенной причиной того, что обмен не работает, является то, что забыли пометить в 1С данные к выгрузке вручную или с помощью сценария «Выполнить подготовку объектов 1С к загрузке в DIRECTUM». Сценарий выполняет
регистрацию изменений всех настроенных объектов для выбранной интегрированной системы 1С. Регистрация изменений всех настроенных объектов 1С необходима для того, чтобы коннектор учитывал все данные этих объектов, в том числе и измененные до создания плана
обмена. Обычно это необходимо при самом первом обмене данными между 1С и DIRECTUM. Если необходимости выгружать все данные нет, то можно просто пересохранить запись справочника 1С или DIRECTUM, чтобы она попала в тестовый обмен.
Иногда после настройки коннектора 1С и попытке провести первый обмен, в логах обмена появляется ошибка вида:
07.04.2011 09:52:12 Начало выгрузки данных справочников системы DIRECTUM
07.04.2011 09:52:13 Экспорт ДГВ 175128 Change
07.04.2011 09:52:13 Экспорт ОРГ 175126 Change
07.04.2011 09:52:14 Завершение выгрузки данных справочников системы DIRECTUM
07.04.2011 09:52:14 Начало загрузки данных объектов в систему "1С81"
07.04.2011 09:52:26 ERROR Ошибка преобразования данных из формата DIRECTUM в формат системы или загрузки данных в интегрированную систему. (Ошибка преобразования данных XML: [file://C:/DIREXCHANGE1C/Message_002_001.xml][2,3861] Функция "Connector1C81ImportDataToIntegratedSystem": ошибка в строке 176.
Функция "ConnectorImportDataToIntegratedSystem": ошибка в строке 3.
Функция "ConnectorImportDataToIntegratedSystem": ошибка в строке 14.)
07.04.2011 09:52:26 Завершение загрузки данных объектов в систему "1С81"
Причина появления данной ошибки в том, что мы пытаемся загрузить в 1С неправильно сформированный XML-файл с данными обмена. Первым делом необходимо проверить настройки обмена на вкладке «Дополнительные настройки»:
Если все настройки сделаны правильно, а ошибка все равно появляется, то попробуем определить ошибочную запись в XML-файле обмена. В нашем случае это файл Message_002_001.xml. Наименование файлов обмена формируется по принципу Message_КодУзлаСистемыИсточника_КодУзлаСистемыПриемника:
У меня, в отличие от приведенного выше скриншота, коды узлов были наоборот (001 — Узел 1С, 002 – Узел DIRECTUM), чтобы вы не путались в дальнейшем. Таким образом, видим, что у нас в качестве источника выступает DIRECTUM, а в качестве
приемника 1С. Откроем этот файл обмена в Visual Studio и отформатируем его:
В результате наш отформатированный XML-файл обмена будет выглядеть так:
Сохраним его и попробуем загрузить в 1С с помощью сценария:
IntegratedSystemCode = "1C81"
FullFileName = "C:/DIREXCHANGE1C/Message_002_001.xml"
V8App = Connector1C81Get1C80Application(IntegratedSystemCode)
// Проверить все ли объекты включены в необходимый план обмена
Object.Environment.SetVar("V8App"; V8App)
ExchangePlanName = GetIntegratedSystemParam(IntegratedSystemCode; "ExchangePlan")
// Создать и проинициализаровать объект ЧтениеХМL
// Используется VBScript, так как на ISBL невозможно вызывать метод V8App.NewObject("XMLReader")
ScriptControl = CreateObject("MSScriptControl.ScriptControl")
ScriptControl.Language = "VBScript"
ScriptControl.Reset
ScriptControl.AddObject("V8App"; V8App)
XMLReader = ScriptControl.Eval('V8App.NewObject("XMLReader")')
XMLReader.OpenFile(FullFileName)
// Создать объект ЧтениеСообшенияОбмена
// и начать чтение сообщения
MessageReader = V8App.ExchangePlans.CreateMessageReader
MessageReader.BeginRead(XMLReader)
V8App.ExchangePlans.DeleteChangeRecords(MessageReader.Sender; MessageReader.ReceivedNo)
// Читаем данные из сообщения
while V8App.CanReadXML(XMLReader)
Data = V8App.ReadXML(XMLReader)
Data.ОбменДанными.Отправитель = MessageReader.Sender
Data.ОбменДанными.Загрузка = TRUE
Data.Write()
endwhile
// Закончить чтение сообщения и чтение XML
MessageReader.EndRead()
XMLReader.Close
V8App = NIL
окно("Загрузка завершена!")
В переменной IntegratedSystemCode нужно указать код интегрированной системы, а в переменной
FullFileName путь до сформированного XML-файла с данными для обмена. Сценарий можно доработать, добавив запрос переменной
IntegratedSystemCode через InputDialog, FullFileName получать из табличной части по коду системы и добавить обработку исключений, т.к. мы ждем, что появится ошибка. Я по своей натуре существо очень ленивое, поэтому оставил его в таком виде.
В результате работы сценария мы получим ошибку:
Теперь мы видим строку и столбец «[4369,2]» с ошибочными данными в XML-файле обмена Message_002_001.xml. Снова открываем этот файл в Visual Studio и переходим к указанной в ошибке строке:
Тут сразу видно, что с этой записью что-то не то, но чтобы убедиться в этом окончательно, выгрузим данные из 1С с помощью внешней обработки ВыгрузкаЗагрузкаДанныхXML.epf, которую можно найти на диске ИТС или в интернете. Для этого
запускаем 1С Предприятие и через пункт меню ФайлОткрыть открываем обработку ВыгрузкаЗагрузкаДанныхXML.epf. Указываем имя файла для выгрузки, отмечаем какой объект 1С необходимо выгрузить и нажимаем кнопку «Выгрузить данные».
На скриншоте не указан период выгрузки, т.к. у меня база 1С была почти пустая. Если у вас в интегрируемых объектах 1С скопилось много данных (например, за несколько лет), то период выгрузки стоит обязательно указать, иначе такой
выгрузкой можно очень сильно подвесить систему. Как правило, чтобы оценить правильность формирования XML-файла с данными, достаточно выгрузить 2-3 записи.
После того, как данные будут выгружены, открываем сформированный XML-файл с выгруженными данными и начинаем сравнивать, чем наша неправильно сформированная запись отличается от выгруженных из 1С. В моем случае правильно сформированная
запись для выгрузки должна выглядеть так:
Сравнив её с ошибочной записью, видим, что почему-то не заполнены некоторые реквизиты значениями по умолчанию:
Для реквизита типа справочник, вместо пустого значения должны были быть нули «00000000-0000-0000-0000-000000000000», для реквизита типа число должен стоять «0», а не пустая строка, для логического реквизита вместо пустой строки
должно быть «true» или «false».
Далее можно действовать исходя из поставленной перед вами задачи:
- Удалить ошибочную запись из XML-файла обмена, провести загрузку данных с помощью сценария указанного выше и скорректировать «Время последней выгрузки» в настройках интегрированной системы на текущее (чтобы эта запись в обмен больше
не попадала). - Дополнить ошибочную запись XML-файла обмена недостающими данными, провести загрузку данных с помощью сценария указанного выше и скорректировать «Время последней выгрузки» в настройках интегрированной системы на текущее (чтобы
эта запись в обмен больше не попадала). - Попытаться найти причину, почему XML-файл сформировался неправильно, и устранить её.
Чтобы найти причину, почему XML-файл формируется неправильно, потребуется добавить отладочную информацию в функции коннектора и в XSL-шаблон преобразования. Об этом поговорим более подробно в следующем материале.
ВыгрузкаЗагрузкаДанныхXML_для_1С81.zip (65,86 Кб)
ВыгрузкаЗагрузкаДанныхXML_для_1С82.zip (67,53 Кб)
Форум программистов Vingrad
Поиск: |
|
EOleException, как перехватить ошибку ? |
Опции темы |
comtat |
|
||
Эксперт Профиль
Репутация: 1
|
Подключаюсь через ADO к MS_Access
Необходимо проводить анализ ошибок таких как неверный путь к БД, неверный логин или пароль и т.д. ——————— Рожденный в СССР !!! |
||
|
|||
ТоляМБА |
|
||
Котэ Профиль
Репутация: 3
|
|
||
|
|||
comtat |
|
||
Эксперт Профиль
Репутация: 1
|
То, что ты написал у меня уже готово. ——————— Рожденный в СССР !!! |
||
|
|||
SergeBS |
|
||
Эксперт Профиль
Репутация: 11
|
comtat, |
||
|
|||
comtat |
|
||
Эксперт Профиль
Репутация: 1
|
SergeBS , ТоляМБА спасибо за помощь !
——————— Рожденный в СССР !!! |
||
|
|||
SergeBS |
|
||
Эксперт Профиль
Репутация: 11
|
comtat, |
||
|
|||
comtat |
|
||
Эксперт Профиль
Репутация: 1
|
SergeBS пасиб Бд и exe писал на своей машине, в чем может быть проблема ?? ——————— Рожденный в СССР !!! |
||
|
|||
SergeBS |
|
||
Эксперт Профиль
Репутация: 11
|
comtat,
Я в таких случаях стряпаю udl-файл и пытаюсь подключиться им. Вообще: Вообще — не советую так делать. Если несколько юзеров одновременно будут одну Access-базу как файл подключать, то рано или поздно произойдет БАХ! И база сдохнет. Возможно — насмерть, т.е. без восстановления даже части данных. |
||
|
|||
comtat |
|
||
Эксперт Профиль
Репутация: 1
|
Трабла была с правами к БД К одной БД базе будет коннектится только одно приложение, т.к. у заказчика нет возможности дылать локалку. А потом данные нуна будет как-то реплицировать. А Access позволяет делать репликации ? ——————— Рожденный в СССР !!! |
||
|
|||
SergeBS |
|
||
Эксперт Профиль
Репутация: 11
|
comtat,
Репликация != объединению. |
||
|
|||
comtat |
|
||
Эксперт Профиль
Репутация: 1
|
Я в курсе ——————— Рожденный в СССР !!! |
||
|
|||
SergeBS |
|
||
Эксперт Профиль
Репутация: 11
|
comtat,
Понятия не имею. Он мне по большому счету неинтересен. Да и в твоей задаче это неважно — сети-то нет. Значит все равно ручками файл тащить, через флэшку/RW-шку и т.п. |
||
|
|||
comtat |
|
||
Эксперт Профиль
Репутация: 1
|
SergeBS , а прав ведь, как сам запамятил . Спасибо !! ——————— Рожденный в СССР !!! |
||
|
|||
Evenstain |
|
||||
Новичок Профиль Репутация: 1
|
такая вот проблема: пытаюсь перехватить ошибки класса EOleException. но delphi ругается, говорит, что
использую код типа:
объясните, что я делаю не так |
||||
|
|||||
pseud |
|
||||||
Экспёрт Тыдыщ Профиль
Репутация: 16
|
Evenstain, смотри свою тему там ответил
——————— Испытание чужого терпения можно считать успешным, если оно лопнуло… |
||||||
|
|||||||
|
Правила форума «Delphi: Базы данных и репортинг» | |
|
Запрещено: 1. Публиковать ссылки на вскрытые компоненты 2. Обсуждать взлом компонентов и делиться вскрытыми компонентами Обязательно указание: 1. Базы данных (Paradox, Oracle и т.п.) 2. Способа доступа (ADO, BDE и т.д.)
FAQ раздела лежит здесь! Если Вам помогли и атмосфера форума Вам понравилась, то заходите к нам чаще! С уважением, Vit, Петрович. |
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей) |
0 Пользователей: |
« Предыдущая тема | Delphi: Базы данных и репортинг | Следующая тема » |