AXForum  
Вернуться   AXForum > Microsoft Dynamics AX > DAX: Программирование
All
Забыли пароль?
Зарегистрироваться Правила Справка Пользователи Сообщения за день Поиск

 
 
Опции темы Поиск в этой теме Опции просмотра
Старый 30.03.2011, 19:34   #1  
Delfins is offline
Delfins
Участник
 
320 / 39 (2) +++
Регистрация: 20.09.2005
Адрес: Riga, Latvia
Падает Ахапта-2009 при использовании .NET/CLRInterop/Word
Такой вот код (ниже). Ахапта падает именно при вызове функции.. Сам Word то всё делает, открывает фаил, можно закрыть сам Word (без открытия дока).
Сначала была проблема, что подавал NULL в CLRInterop неправильно, но потом нашёл "хияцк" - http://rik-ax.blogspot.com/2008/01/p...lrinterop.html
Вот не понимаю где теперь проблема.. вызов вроде правильный.. может чего забыл? Мистический `missing` то в Quit() работает...

Пробую написать интерфейс для Word/документа-оботрота через .NET/CLR

Падают все тру вызова.. сами обьекты до Open()/Add() существуют
X++:
static public void ESL_word_test(Args _args)
{
    //> Missing hijack
    System.Type                 type = System.Type::GetType("System.Reflection.Missing");
    System.Reflection.FieldInfo info = type.GetField("Value");
    System.Object               missing = info.GetValue(null);
    //< Missing hijack

    str _filename = "C:\\............dot";

    Object clrException;
    Object clrExceptionOwner;

    Microsoft.Office.Interop.Word.ApplicationClass wc;
    Microsoft.Office.Interop.Word.DocumentClass wd;
    Microsoft.Office.Interop.Word.Documents wds;
    Microsoft.Office.Interop.Word.Bookmarks wb;

    System.Object oTrue = true;
    System.Object oFalse = false;
    System.Object oFormat = Microsoft.Office.Interop.Word.WdOpenFormat::wdOpenFormatAuto;
    System.Object oDirection = Microsoft.Office.Interop.Word.WdDocumentDirection::wdLeftToRight;
    System.Object oEmptyStr = "";
    //System.Object oEncoding = Microsoft.Office.Core.MsoEncoding::msoEncodingAutoDetect;
    System.Object oFilename = _filename;
    ;

    try
    {
        wc = new Microsoft.Office.Interop.Word.ApplicationClass();
        wc.set_Visible(true);

        wds = wc.get_Documents();
        if (!wds)
            throw error("no get_Documents");

        if (1)
            wds.Add(byref missing,byref missing,byref missing, byref oTrue);

        if (0)
        wd = wds.Open(
                    byref oFilename,
                    byref missing,
                    byref missing,
                    byref missing,
                    byref missing,
                    byref missing,
                    byref missing,
                    byref missing,
                    byref missing,
                    byref missing,
                    byref missing,
                    byref missing,
                    byref missing,
                    byref missing,
                    byref missing,
                    byref missing
                );

        if (0)
        wd = wds.Open(
                    byref oFilename,
                    byref oFalse,
                    byref oTrue ,
                    byref oFalse,
                    byref oEmptyStr,
                    byref oEmptyStr,
                    byref oFalse,
                    byref oEmptyStr,
                    byref oEmptyStr,
                    byref oFormat,
                    byref missing,
                    byref oFalse,
                    byref oFalse,
                    byref oDirection,
                    byref oTrue,
                    byref missing
                );
    }
    catch (Exception::CLRError)
    {
        setprefix("CLR error");
        clrException = CLRInterop::getLastException();
        if (CLRInterop::isNull(clrException) == false)
        {
            error(clrException.get_Message());
            error(clrException.get_StackTrace());

            clrExceptionOwner = clrException.get_InnerException();
            if (CLRInterop::isNull(clrExceptionOwner) == false)
            {
                error(clrExceptionOwner.get_Message());
            }
        }
    }
    catch
    {
        info("Ax stop...");
    }

    if (wc)
    {
        try
        {
            wc.Quit(byref missing, byref missing, byref missing);
        }
        catch
        {
            setprefix("CLR Word-quit error");
            clrException = CLRInterop::getLastException();
            if (CLRInterop::isNull(clrException) == false)
            {
                error(clrException.get_Message());
            }
        }
    }
}
Старый 31.03.2011, 10:36   #2  
gl00mie is offline
gl00mie
Участник
MCBMSS
Most Valuable Professional
Лучший по профессии 2017
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
Лучший по профессии 2009
 
3,684 / 5798 (201) ++++++++++
Регистрация: 28.11.2005
Адрес: Москва
Записей в блоге: 3
Хм, у меня тоже валится... Может, попробовать ядро поновее? Я проверял на 3968, но сейчас уже какие 43хх-е билды есть. Еще занятно, что Word явно требует передачи параметров по ссылке, а Excel - нет...
Старый 31.03.2011, 11:36   #3  
Delfins is offline
Delfins
Участник
 
320 / 39 (2) +++
Регистрация: 20.09.2005
Адрес: Riga, Latvia
Кстати, wds.Add() с некоторами параматрами всё работает ( в дебагере проходил - Word нормально открылся), но как только вызываешь потом Close(), так падает..
Скорее всего что-то с за/отгрузкой .NET библиотек.. слишком рано или поздно. Черт знает, я не спец по .NET :|
Старый 31.03.2011, 12:28   #4  
someOne is offline
someOne
Участник
Аватар для someOne
 
173 / 429 (15) +++++++
Регистрация: 11.12.2008
Адрес: Москва
Цитата:
Сообщение от Delfins Посмотреть сообщение
Кстати, wds.Add() с некоторами параматрами всё работает ( в дебагере проходил - Word нормально открылся), но как только вызываешь потом Close(), так падает..
Скорее всего что-то с за/отгрузкой .NET библиотек.. слишком рано или поздно. Черт знает, я не спец по .NET :|
На мой взгляд это все же не баг. Класс Microsoft.Office.Interop.Word.ApplicationClass, как описано тут (http://msdn.microsoft.com/ru-ru/libr...ffice.11).aspx)

Цитата:
This method supports the .NET Framework infrastructure and is not intended to be used directly from your code.
Не предназначен для "внешнего" использования.
Думаю, "копать" нужно в сторону
X++:
Microsoft.Office.Interop.Word._Application     word;
Старый 31.03.2011, 17:29   #5  
Delfins is offline
Delfins
Участник
 
320 / 39 (2) +++
Регистрация: 20.09.2005
Адрес: Riga, Latvia
Я склоняюсь, что этот текст был "Копи-Пейст"..
Да и ктому же, методы возвращающие внутренние переменныие "коллекции" идут на свой же интерфеис.


По ходу дела Buffer Overflow Exception ...
скорее всего Ахапта не буделала память, или Word что-то пытается обратно отдать..

Цитата:
Problem signature:
Problem Event Name: BEX
Application Name: Ax32.exe
Application Version: 5.0.1500.3761
Application Timestamp: 4cd58bc2
Fault Module Name: StackHash_0a9e

Последний раз редактировалось Delfins; 31.03.2011 в 17:38.
Старый 07.07.2011, 11:13   #6  
someOne is offline
someOne
Участник
Аватар для someOne
 
173 / 429 (15) +++++++
Регистрация: 11.12.2008
Адрес: Москва
Решением данной проблемы может быть такой вариант:

Написал NET сборку, которая выполняет все необходимые операции с WORD- ом,
и затем уже ее использую в Аксапта.

Минус данного решения таков, что придется подключить в reference Axapta, а также копировать ее на каждого клиента, работающего с WORD - ом.
(В папку BIN клиента. В GAC добавлять не обязательно)
Но другого решения, кажется нет.

- COM технология работы с WORD - не работоспособна в Axapta на последних версиях OS (у нас глючит на WIN SERVER 2008 терминал,
обсуждалось на форуме)
- NET - не работает напрямую из за "падения" Аксапты. (см обсуждение выше)

После такого случая заявления Microsoft о том что ее решения, в т.ч Ax "Хорошо интегрируются с продуктами Office" - звучат слишком самоуверенно


Для того чтобы заработало, написал такой класс на С# в Visual Studio

X++:
namespace AxFunctions
{
    public class word
    {
        Microsoft.Office.Interop.Word.ApplicationClass app;
        Microsoft.Office.Interop.Word.Document doc;

        object missing = System.Reflection.Missing.Value;

        public Microsoft.Office.Interop.Word.Document document()
        {
            return doc;
        }

        public void openFile(System.Object fileName)
        {
            if (app == null)
            {
                app = new Microsoft.Office.Interop.Word.ApplicationClass();
            }

            app.Visible = true;

            doc = app.Documents.Open(ref fileName, ref missing, ref missing, ref missing,
                                    ref missing, ref missing, ref missing, ref missing,
                                    ref missing, ref missing, ref missing, ref missing,
                                    ref missing, ref missing, ref missing, ref missing);

        }
        public void setFieldValue(string fieldName, string fieldValue)
        {
            Microsoft.Office.Interop.Word.FormFields fields = doc.FormFields;

            foreach (Microsoft.Office.Interop.Word.FormField field in fields)
            {
                if (field.Name == fieldName)
                {
                    field.Range.Text = fieldValue;
                }
            }

        }
    }
}
Мне нужны были лишь две функции, так как только они требуются для моих отчетов word:
- открыть документ
- присвоить заданное значение полю документа по его имени.

Если кому то потребуется что то еще - это легко сделать.


Ну а работать с этим в Аксапта очень просто:

X++:
static void Job22(Args _args)
{
    AxFunctions.word word;
    ;

    word = new AxFunctions.word();

    word.openFile("c:\\Contract.doc");

    word.setFieldValue("NumContract", "1043564/03-2010"); // NumContract - это имя поля в шаблоне документа

}
Прилагаю готовую DLL, если кому то этих двух функций будет достаточно.
Вложения
Тип файла: zip AxFunctions.zip (2.1 Кб, 247 просмотров)

Последний раз редактировалось someOne; 07.07.2011 в 11:17. Причина: Файл забыл...
За это сообщение автора поблагодарили: Logger (6), suicest (1).
Старый 20.10.2011, 13:16   #7  
bio_unit is offline
bio_unit
Участник
Аватар для bio_unit
Сотрудники компании GMCS
Ex AND Project
 
119 / 77 (3) ++++
Регистрация: 21.04.2004
Приветсвую!
Ни кто случайно не нашел решение данного вопроса без разработки отдельной dll?
Неужели без dll никак?
Старый 20.10.2011, 13:45   #8  
sukhanchik is offline
sukhanchik
Administrator
Аватар для sukhanchik
MCBMSS
Злыдни
Лучший по профессии 2015
Лучший по профессии AXAWARD 2013
Лучший по профессии 2011
Лучший по профессии 2009
 
3,309 / 3546 (125) ++++++++++
Регистрация: 13.06.2004
Адрес: Москва
Пока только вариант в отдельном потоке работает (класс Thread)
__________________
Возможно сделать все. Вопрос времени
Старый 28.11.2012, 20:03   #9  
MikeR is offline
MikeR
MCT
Аватар для MikeR
MCBMSS
Лучший по профессии 2015
Лучший по профессии 2014
 
1,628 / 627 (24) +++++++
Регистрация: 28.11.2005
Адрес: просто землянин
У меня в офисе 2010 отработал только такой вариант.

X++:
public void setFieldValue(string fieldName, string fieldValue)
        {

            Object oBookMark = fieldName;
            doc.Bookmarks.get_Item(ref oBookMark).Range.Text = fieldValue;

        }
__________________
Axapta book for developer
Старый 02.02.2015, 17:44   #10  
A_BAS is offline
A_BAS
Участник
Аватар для A_BAS
 
77 / 48 (2) +++
Регистрация: 19.04.2012
Эксгумирую тему.
Пробую открыть документ Word через Microsoft.Office.Interop.Word.
Документ открывается, но при этом падает клиент.
Через Thread пробовал, тоже падает... Но не клиент, а поток.
У меня складывается впечатление, что проблема в передаче параметров по ссылке.
Кто-нибудь поборол уже проблему? (dll не предлагать) =)
Старый 07.08.2020, 12:48   #11  
Pustik is offline
Pustik
Участник
 
807 / 372 (14) ++++++
Регистрация: 04.06.2004
вот так работает :
X++:
static public void ESL_word_test(Args _args)
{
    System.Type                 type = System.Type::GetType("System.Reflection.Missing");
    System.Reflection.FieldInfo info = type.GetField("Value");
    System.Object               missing = info.GetValue(null);

    Microsoft.Office.Interop.Word.ApplicationClass wc;
    Microsoft.Office.Interop.Word.Documents wds;
    CLRObject                               wdso;
    ;

    try
    {
        wc = new Microsoft.Office.Interop.Word.ApplicationClass();
        wc.set_Visible(true);

        wds = wc.get_Documents();
        if (!wds)
            throw error("no get_Documents");

        //wds.Add(byref missing,byref missing,byref missing, byref oTrue);
        wdso = wds;
        wdso.Add(missing,missing,missing,true);
        
    }
    catch (Exception::CLRError)
    {
        setprefix("CLR error");
    }
}
все-таки вылетала Аксапта из-за вот такой конструкции :
X++:
wds.Add(byref missing,byref missing,byref missing, byref oTrue);
хотя и при компиляции ошибок не выдает
вот здесь похожая картина: Excel .NET вставка картинки
__________________
-Ты в гномиков веришь?
-Нет.
-А они в тебя верят, смотри, не подведи их.
За это сообщение автора поблагодарили: Logger (3).
Теги
.net, ax2009, clr interop, clrobject, office, word, баг, ошибка, ядро

 

Похожие темы
Тема Автор Раздел Ответов Посл. сообщение
semanticax: Dynamics AX 2009 Installation - Application Blog bot DAX Blogs 0 22.12.2010 08:11
Solutions Monkey: Migrating X++ web forms to AX 2009 EP asp.net framework Blog bot DAX Blogs 0 09.11.2010 19:05
emeadaxsupport: When browsing AX 2009 Role Centers, you get an error: An unexpected error has occurred on systems with .NET Framework v4.0 installed Blog bot DAX Blogs 1 28.07.2010 08:24
emeadaxsupport: List of fixes that improve performance of certain features in Dynamics AX 2009 Blog bot DAX Blogs 0 13.10.2009 19:06
axStart: Microsoft Dynamics AX 2009 Hot Topics Web Seminar Series Blog bot DAX Blogs 0 06.08.2008 12:05

Ваши права в разделе
Вы не можете создавать новые темы
Вы не можете отвечать в темах
Вы не можете прикреплять вложения
Вы не можете редактировать свои сообщения

BB коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.
Быстрый переход

Рейтинг@Mail.ru
Часовой пояс GMT +3, время: 22:37.