|
24.08.2011, 15:00 | #1 |
Участник
|
Переодически вылетает выгрузка в Excel
Добрый день. Столкнулся с интересной проблемой. Есть выгрузка отчёта в Excel. Есть 2 AOS-а на одном этот очёт выходит без проблем чтобы мы не делали. На втором же периодический, вылетает. Например когда мы сворачиваем все окна(во время формирования отчёта в фоновом режиме) или разворачиваем(хотя как это может влиять???).Либо когда мы что нить копируем в буфер во время выгрузки. И ошибки типа "Метод Insert в COM-объекте классавозвратилкод ошибки....". Разница межу Приложениями лишь в лицензиях...на одном которое нормально работает и ни в какую не вылетает стоит лицензия на разработку. Во втором приложении разработки нет. Запускаю на третьем приложении тоже где отсутствует лицензия на разработку и приложение также вылетает. Странно как это может влиять на стабильность? И как сворачивание всех окон или разворачивание может влиять на работу AX-Excel(к томуже когда Excel в фоновом режиме)???
Аксапта 2009-ой версии. Excel любой. Операционка как ХР так и 7-ка. |
|
24.08.2011, 15:18 | #2 |
MS Dynamics AX 2012 R3
|
Как я понимаю аксапта у Вас работает просто с машины, т.е. не через терминальный сервер, если да, то попробуйте через него, это самый лёгкий способ решения проблемы. Если нет, отчётом пользуются на одинаковых слоях?
Вы запускаете его на разных машинах под разными аосами? Проверьте версии клиентов на машинах, по хорошему они должны быть одинаковыми с версией на основном сервере.
__________________
"Человек человеку волк, а зомби зомби зомби." (с) С Уважением, Алексей Кабанов Последний раз редактировалось ZornFire; 24.08.2011 в 15:20. Причина: орфография |
|
24.08.2011, 15:19 | #3 |
Участник
|
1. Какой способ выгрузки в Excel используется? Поячеечная вставка, буфер обмена, ADO RecordSet?
2. Работа ведется в терминальной сессии? |
|
24.08.2011, 16:38 | #4 |
Участник
|
Цитата:
Ошибка времени выполнения в ComExcelDocument_RU.findRange() Ошибка чтения файлов XLS под Windows 7 - тут предложено решение: переписать взаимодействие с Excel на использование .NET вместо COM. К слову, тут вот предлагают запускать клиента на терминальном сервере, так я по своему скромному опыту скажу, что это лишь усугубит ситуацию, потому что на настольном компе у вас несколько десятков процессов и 300-800 потоков, и все вылетает из-за этих <censored> таймаутов, а на терминальном сервере будет несколько сотен процессов и эдак под 4-5 тысяч потоков, так что вылетать будет куда чаще. Цитата:
Сообщение от gl00mie
Переписал семейство классов SysExcel на .NET, по ходу дела пришлось добавить несколько новых оберток для интерфейсов Excel, чтобы избавиться от необходимости работать напрямую через COM. Пока повсеместно включать не решился, но результат превзошел все ожидания! При запуске на терминальном сервере с полусотней параллельно работающих пользовательских сессий импорт из Excel через .NET несмотря на нещадные переключения между окнами (которые раньше валили импорт на раз) не только стабильно завершался без ошибок, но и отрабатывал при этом достаточно шустро - в отличие от "залатанного" импорта через COM, где за счет дополнительных try/catch/retry ошибки вроде как маскировались, но приводили к очень ощутимому замедлению работы.
|
|
24.08.2011, 17:22 | #5 |
Участник
|
2 gl00mie
Можете поподробней рассказать, что значить переписать на .NET ? Проблема взаимодействия Axapta c com-объектами под Windows7 и Winserver 2008 общеизвестна и на сколько я знаю в Microsofte пытаются ее решить, но как то не очень удачно (заплатки с периодическим обращением к объектами и т.д.) |
|
25.08.2011, 14:15 | #6 |
Участник
|
Взять классы-обертки для работы с Excel и переделать их как-то так (на примере SysExcelCells):
X++: public static client SysExcelCells construct(MSOfficeVersion _version, COM _cells, Microsoft.Office.Interop.Excel.Range _cells_net = null) { if (_cells_net) { return SysExcelCells_NET::construct( _version, _cells_net ); } return new SysExcelCells(_cells, _version); } /////////////////////////////////////////////////////////////////////////////// // реализация обертки для работы с Excel через Microsoft.Office.Interop.Excel class SysExcelCells_NET extends SysExcelCells { Microsoft.Office.Interop.Excel.Range cells_net; } // возвращает ClrObject из пространства имен Microsoft.Office.Interop.Excel, оберткой для которого является экземпляр класса // это часть внутренней инфраструктуры семейства классов SysExcel*, реализующих работу через .NET protected CLRObject clrObject() { return cells_net; } public final COM comObject() { // copy-paste кода метода-обработчика comObject(), общего для классов SysExcel*, реализующих работу через .NET str methodName = strfmt( '%1.%2', classid2name( classidget( this ) ), methodstr(SysExcel, comObject) ); throw error( strfmt( "@SYS75628", methodName, "@SYS95798" ) ); } // способ, которым класс взаимодействует с Excel // это часть внутренней инфраструктуры семейства классов SysExcel* для реализации кое-каких проверок protected final InteropKind getXlInteropKind() { return InteropKind::ClrInterop; } public SysExcelCell item(int _row, int _column) { // предполагаем, что класс может работать и на сервере, при этом вызывающий код не должен знать детали взаимодействия с Excel new InteropPermission( InteropKind::ClrInterop ).assert(); // BP deviation documented return SysExcelCell::construct( version, null, cells_net.get_Item( _row, _column ) ); } protected void new(Microsoft.Office.Interop.Excel.Range _cells_net, MSOfficeVersion _version) { super( null, _version ); cells_net = _cells_net; } public SysExcelRange range(str _range = '') { SysExcelRange ret; ; if (_range != '') { new InteropPermission( InteropKind::ClrInterop ).assert(); // BP deviation documented ret = SysExcelRange::construct( version, null, cells_net.get_Range( _range, this.getClrMissingArg() ) ); } else { ret = SysExcelRange::construct( version, null, cells_net ); } return ret; } public static SysExcelCells_NET construct(MSOfficeVersion _version, Microsoft.Office.Interop.Excel.Range _cells_net) { return new SysExcelCells_NET( _cells_net, _version ); } Последний раз редактировалось gl00mie; 25.08.2011 в 14:20. Причина: очепятки |
|
|
За это сообщение автора поблагодарили: Stainless (1). |
25.08.2011, 23:33 | #7 |
Участник
|
Да уж, тема грустная для АХ2009, на АХ4 не было таких явных проблем при шевелении мышкой или кликом на запуск другой проги в момент построения Ехель отчетов.
Мы переписали на .НЕТ проблема снялась, но возникла несовместимость с разными офисами на клиентских местах - решение обсуждалось в какой-то теме, нужно ДЛЛ от офиса 2007 засунуть в БИН на клиенте, тогда на Офис2003 заработает. А тут начала сбоить даже стандартная выгрузка формы (фича АХ2009) в Ехель по кнопочке на форме или Ctrl-E Она ж тоже СОМ и ее наш перепис не коснулся.... и чинят это в МС, судя по году возникновения темы, давно... точнее вообще не чинят, тк потуги try-catch 4 раза - это бутафория, пробовали, фигня-с Вторая панацея помимо .НЕТ, это запуск в потоках (для Ворда решили именно так, так на .Нет он не пошел, лезли неисправимые баги). С потоками все ок, там никто мышкой не пошевелит и не поломает хрупкую конструкцию СОМ вызова. Минус - проблемы с выводом инфолога, тк строится все это "где-то там". |
|
25.08.2011, 23:56 | #8 |
Участник
|
Вроде в отдельном потоке можно "вырезать" выведенные в нем сообщения через infolog.cut(), вернуть его через Thread.setErrorLog(), и потом вывести это все в основном потоке через infolog.view(). По-моему, куда больше проблем в случае отдельного потока с созданием "обертки" для запуска куска функционала в отдельном потоке, передачи нужных ему данных, etc...
|
|
26.08.2011, 00:08 | #9 |
Administrator
|
Это скажем так - не проблема. Это особенность, про которую не нужно забывать и выводить надо через Thread.setoutputParm()
Эта проблема одноразовая - один раз сделал, а потом забыл. Правда один раз сделать надо.
__________________
Возможно сделать все. Вопрос времени |
|
24.08.2011, 17:13 | #10 |
Участник
|
Ну да. Выполняется всё на локальной машине(не терминалка). Приложение одно и тоже, просто на 2 стоят лицензии без разработки, а на одном(на котором всё ок.) с разработкой. Вот вся разница. Слои работы идентичны. Выгрузка идёт поячеечно через COM-объекты.
Самое интересное, что это работает на приложении с лицензией на разработку! |
|
24.08.2011, 17:42 | #11 |
Участник
|
Делайте не прямые вызовы методов com-объектов, а через обертку ComDispFunction - получите значительно более стабильную работу
__________________
Axapta v.3.0 sp5 kr2 |
|
26.08.2011, 09:25 | #12 |
Участник
|
sukhanchik а можно поподробнее, либо ссылку на пример?
Спасибо! |
|
26.08.2011, 10:00 | #13 |
Administrator
|
Цитата:
Сообщение от raniel
sukhanchik а можно поподробнее, либо ссылку на пример?
Спасибо!
__________________
Возможно сделать все. Вопрос времени |
|
26.08.2011, 14:21 | #14 |
Участник
|
|
|
26.08.2011, 14:41 | #15 |
Administrator
|
По аналогии с импортом: Ошибка времени выполнения в ComExcelDocument_RU.findRange()
Или Вы столкнулись с тем, что импорт работает, а экспорт как раз-таки нет? Было бы весьма странно
__________________
Возможно сделать все. Вопрос времени |
|
|
За это сообщение автора поблагодарили: raniel (1). |
26.08.2011, 14:55 | #16 |
Участник
|
Единственная, может, особенность (или это мне так повезло): объект Thread должен по возможности явно создаваться на клиенте, например, через classFactory::makeObjectOnClient()
|
|
26.08.2011, 15:16 | #17 |
Administrator
|
Цитата:
Я действительно создавал объект Thread на клиенте, ибо там же создавал экземпляр COMExcelDocument_RU (или Word). Но у меня была реализована более сложная схема. Фактически, я продублировал (неполностью конечно) классы COMExcel/WordDocument_RU. Т.е. создал класс, у которого сделал параметр - требуется ли запускать код в потоке или нет. Для Word запуск в потоке обязателен, а для Excel - нет (ибо можно сделать через .NET). Но можно и Excel запустить в потоке - ограничений нет. А дальше - этот класс-обертка запускает начальный метод, строящий отчет. Собственно - все. Все расчеты при желании - всегда можно сделать и на сервере.
__________________
Возможно сделать все. Вопрос времени |
|
26.08.2011, 15:28 | #18 |
Участник
|
У меня в ходе экспериментов вообще не получилось запустить дополнительный поток на сервере - даже с простеньким тестовым статическим серверным методом, не то что с каким-то рабочим кодом Что характерно, при реализации класса TutorialThread, похоже, эти попытки тоже остались безуспешными.
Цитата:
С SysExcel* в этом плане куда проще, потому что классы написаны "прямее", и достаточно заложить нужную логику принятия решения о том, как работать с Excel (через COM или .NET) в одно-единственное место - SysExcelApplication::construct(). Хотя предварительно, разумеется, нужно вычистить в коде "нарушения абстракции" - работу напрямую с COM-объектами, обертками для которых выступают классы в приложении Аксапты. |
|
|
За это сообщение автора поблагодарили: sukhanchik (2). |
26.08.2011, 16:30 | #19 |
Участник
|
Цитата:
Сообщение от gl00mie
Вот чем мне не нравятся классы ComExcel/WordDocument_RU - это что они везде в коде создаются через new(), а не через статический construct(), как следствие, просто так подменить штатный класс таким вот, к примеру, наследником, реализующим работу в отдельном потоке, уже не получится - придется править все места, в которых создаются экземпляры этих классов,
Делается проект с нужным набором классов-отчктов. Выгружается в ХРО Заменой текста по заменяемым названиям Загрузка ХРО Проверка компилом - правки. Мы так 60 классов оптом меняли, иначе, конечно, озвереть |
|
26.08.2011, 17:20 | #20 |
Участник
|
Цитата:
|
|
Теги |
ax2009, excel |
|
|