ATL attributed проект
От: Щербатов Евгений  
Дата: 29.12.04 10:04
Оценка:
Господа, подскажите в чем дело?

1. Создаю на VS.NET проект С++ вида ATL Project с поддержкой атрибутного программирования (attributed крыжик).
2. Затем в проекте создаю ATL Simple Object.
3. Помимо опций предлагаемых мастером по-умолчанию добавляю поддержку ISupportErrorInfo (атрибут support_error_info).
4. В созданном объекте добавляю метод Test :

STDMETHODIMP CTest::Test(void)
{
return Error("test", __uuidof( this ), E_FAIL );
}

Все.

Теперь делаю клиента на VB6 и пытаюсь вызвать метод Test. У меня Васик ловит исключение E_FAIL, но описания ошибки нет!

Подобное поведение одинаково как для EXE , так и для DLL АТЛ видов проектов.

Если же при создании АТЛ проекта я убираю крыжик Attributed, то все работает как надо...

Подскажите плиз, где я прокололся? Ведь не может быть, что в МС добавили поддержку атрибутов, а генерация ошибок у них работать перестала?
ATL attributed проект и генерация ошибок
От: lkurts Россия http://lktalks.blogspot.com
Дата: 31.12.04 00:12
Оценка: 37 (8)
#Имя: FAQ.atl.attributed.errgen
Здравствуйте, Щербатов Евгений, Вы писали:

ЩЕ>Подскажите плиз, где я прокололся? Ведь не может быть, что в МС добавили поддержку атрибутов, а генерация ошибок у них работать перестала?


Нигде не прокололся. Таки перестала работать генерация ошибок.

Что собственно происходит?

При компиляции "attributed" проекта на компилятор вставляет в твой код некоторые вставки
на основании тех атрибутов которые ты ему прописал. Эти вставки можно просмотреть,
если указать опцию /Fx. При указанииэтой опции тебе компилятор для каждого файла f.x в который
он вставлял код сгенерирует файл f.mrg.x (то есть между именем и расширением файла добавляется mrg), в котором будут аккуратно помечены все вставки которые он за тебя сделал. Так вот — посмотрим что же он там нагенерил. Заметим что поскольку твой выызов идет из VB, то ты неявно пользуешься функцией Invoke интерфейса IDispatch, поскольку больше ничем бейсик пользоваться не умеет. Как раз Invoke и вставляет
тебе компилятор (помимо всего прочего). Вот прирмерно как она выглядит:

    //+++ Start Injected Code For Attribute 'support_error_info'
#injected_line 32 "l:\\work\\projects\\coding\\attributedtest\\errtest.h"
    virtual HRESULT STDMETHODCALLTYPE IErrTest::Invoke(
                /* [in] */ DISPID dispIdMember,
                /* [in] */ REFIID riid,
                /* [in] */ LCID lcid,
                /* [in] */ WORD wFlags,
                /* [out][in] */ DISPPARAMS *pDispParams,
                /* [out] */ VARIANT *pVarResult,
                /* [out] */ EXCEPINFO *pExcepInfo,
                /* [out] */ UINT *puArgErr) 
    {
        (void) riid;
        (void) dispIdMember;
        (void) lcid;
        (void) wFlags;
        (void) pExcepInfo;
        (void) puArgErr;
        HRESULT hr = S_OK;
        if (pDispParams == 0) {
            return DISP_E_BADVARTYPE;
        }
        if (pDispParams->cArgs > 0) {
            return DISP_E_BADPARAMCOUNT;
        }
        if (pVarResult != 0) {
            ::VariantInit(pVarResult);
        }
        switch (dispIdMember) {
        case 1:
            {
                if (pDispParams->cArgs != 0) {
                    return DISP_E_BADPARAMCOUNT;
                }
                hr = ((::IErrTest*) this)->MakeError();
                break;
            }
        default:
            return DISP_E_MEMBERNOTFOUND;
        }
        return hr;
    }


Обрати внимание на кусок которыый я пометил курсивом — в нем и есть ошибка. Для того
чтобы в VB пришла твоя ошибка должна быть заполнена EXCEPINFO *pExcepInfo, а она нигде
не заполняется — поэтому ошибка и не проходит. Там должно было бы быть что-то вроде

IErrorInfo* ErrorInfo; 
GetErrorInfo(0, &ErrorInfo);
ErrorInfo->GetDescription(&pExcepInfo->bstrDescription);
pExcepInfo->wCode = hr;



Как же с этим бороться?
Самый простой способ борьбы вглядит примерно так:
у тебя в .h файле где-то написано примерно так:

class  CErrTest : public IErrTest


вместо этого надо написать так:
class  CErrTest : public IDispatchImpl<IErrTest>


В этом случае код для Invoke вставляться не будет, а будет взят из IDispatchImpl,
а там он правильный
Re: ATL attributed проект и генерация ошибок
От: lkurts Россия http://lktalks.blogspot.com
Дата: 30.03.06 13:05
Оценка: 6 (1)
Здравствуйте, lkurts, Вы писали:

ЩЕ>>Подскажите плиз, где я прокололся? Ведь не может быть, что в МС добавили поддержку атрибутов, а генерация ошибок у них работать перестала?


L>Нигде не прокололся. Таки перестала работать генерация ошибок.


<-------skipped-------->

L>Обрати внимание на кусок которыый я пометил курсивом — в нем и есть ошибка. Для того

L>чтобы в VB пришла твоя ошибка должна быть заполнена EXCEPINFO *pExcepInfo, а она нигде
L>не заполняется — поэтому ошибка и не проходит. Там должно было бы быть что-то вроде

<-------skipped-------->


Хотел обновить информацию. В VS 2005 описанная проблема исправлена. Теперь в Injected код
компилятор вставляет следующее (в самый конец сгенерированного Invoke):


if (FAILED(hr) && pExcepInfo != NULL)
        {
            AtlExcepInfoFromErrorInfo(hr, pExcepInfo);
        }


Как видно, здесь вызывается новая функция (вроде бы ранее не существовашая) : AtlExcepInfoFromErrorInfo.
Она находится в файле: atlevent.h и выглядит так:


inline HRESULT AtlExcepInfoFromErrorInfo(HRESULT hrInvoke, EXCEPINFO *pExcepInfo)
    {
        if (pExcepInfo == NULL)
        {
            return E_POINTER;
        }
        pExcepInfo->pfnDeferredFillIn = NULL;
        pExcepInfo->scode = hrInvoke;
        CComPtr<IErrorInfo> spErrInfo;
        HRESULT hr = GetErrorInfo(0, &spErrInfo);
        if (SUCCEEDED(hr))
        {
            // Set up ErrInfo object
            // Ignore any errors. If additional error information is not
            // available then corresponding pointer will be NULL or 0
            spErrInfo->GetSource(&pExcepInfo->bstrSource);
            spErrInfo->GetDescription(&pExcepInfo->bstrDescription);
            spErrInfo->GetHelpFile(&pExcepInfo->bstrHelpFile);
            spErrInfo->GetHelpContext(&pExcepInfo->dwHelpContext);
        }
        return hr;
    }


Заметим что в двух выделенных строчках ошибка, поскольку GetErrorInfo может выдавать S_FALSE,
и тогда случится обращение к нулевому указателю. Об этом существует соответствующая KB artice:
http://support.microsoft.com/default.aspx?scid=kb;en-us;913940

Вот такие дела. Будьте бдительны!
Re: ATL attributed проект и генерация ошибок
От: Left2 Украина  
Дата: 30.03.06 13:47
Оценка:
да...
может, всё же стоит вынести диагноз "в морг" для attributed ATL?
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.