Как я могу возвратить и строку ошибки и код ошибки к VB6 от элемента управления ActiveX ATL?

«Эта функция сохраняет список переходов

fun! Dos2unixFunction()
let _s=@/
let l = line(".")
let c = col(".")
try
    set ff=unix
    w!
    "%s/\%x0d$//e
catch /E32:/
    echo "Sorry, the file is not saved."
endtry
let @/=_s
call cursor(l, c)
endfun
com! Dos2Unix keepjumps call Dos2unixFunction()
5
задан bdonlan 1 July 2009 в 15:09
поделиться

4 ответа

You can't, this appears to be by design. Details further below, but in short you have three options:

  • Return no message and a VB friendly COM error, i.e. one well known by the VB runtime according to this KB article; the VB runtime will translate this 'COM error' to a VB error plus message.
  • Return an error message and DISP_E_EXCEPTION; the VB runtime will pass through this 'Server error' and your custom error message. This is what's implicitly happening on your second example, see below for details.
  • Return no message and any other COM error, i.e. one not known by the VB runtime; the VB runtime will resort to the raw HRESULT plus the generic message "Method '~' of object '~' failed".
    • Please note that this runtime behavior does also apply, if you do supply an error message here, i.e. your message will simply be ignored! This is what's happening on your first example, see below for details.

For the task at hand it boils down to two choices:

  • If you want to supply contextually correct 'COM errors' for automation clients like VB (and likely you should) you must omit custom error messages.
  • If you want to supply custom error messages for 'Server errors' (i.e. a custom error conditions regarding the functionality within your automation server) your only option is DISP_E_EXCEPTION.

Details

The VB runtime seems to offer only very restricted handling in regard to COM errors. This is likely for historic and/or technical reasons specific to the way VB has been implemented and not of particular interest here (keywords would be IDispatch only vs dual interface and ActiveX as a 'subset' of COM).

While I've been unable to surface an explicit specification for the behavior outlined above one can figure it from digging through other sources:

From the KB article justadreamer pointed out already:

[...] звонок в GetErrorInfo для получения доступная информация об ошибках. В затем время выполнения определяет, bstrDescription имеет значение, отличное от ЗНАЧЕНИЕ NULL. Если среда выполнения находит значение кроме NULL, [...], необработанный HRESULT значение используется в этом сценарии. Если среда выполнения находит значение NULL, [...] Visual Basic затем использует HRESULT найти соответствующий Visual Basic error.

This explains the behavior regarding your fist example: you did supply an error message, hence the runtime simply resorts to its generic message "Method '~' of object '~' failed" plus your HRESULT.

The behavior of your second example is also consistent once you look at the definition of the (first listed) constructor for CComCoClass::Error: it has defaults for the non specified parameters, especially 'hRes = 0'. The 'Remarks' section further states that "If hRes is zero, then the first four versions of Error return DISP_E_EXCEPTION.". Consequently this implicitly triggers the 'Server error' pass through behavior.

Finally, for a concrete C++ implementation sample of a VB like automation client behavior see for example paragraphs 'Error handling' and the following 'Exercise 5' in Automating Microsoft Office 97 and Microsoft Office 2000.

5
ответ дан 14 December 2019 в 19:22
поделиться

Наследуйте класс, реализующий ваш COM-открытый интерфейс, от ISupportErrorInfoImpl, вызовите SetErrorInfo, чтобы задать подробное объяснение ошибки, если таковая возникает. Не забудьте включить ISupportErrorInfo в COM_MAP вашего класса.

0
ответ дан 14 December 2019 в 19:22
поделиться

Я тоже борюсь с этим прямо сейчас. Пока мои поиски показывают, что код ошибки действительно является значением HRESULT. VB6 пытается быть умным и интерпретировать HRESULT, но, похоже, имеет довольно ограниченный список значений HRESULT, которые он понимает. Для HRESULT, с которыми VB6 не знаком, он просто помещает HRESULT в свойство Err.Number и надеется, что разработчик достаточно умен, чтобы выяснить, что с ним делать.

Я ближе всего подошел к тому, чтобы вернуть ошибку number заключается в использовании MAKE_SCODE для генерации HRESULT с полем кода HRESULT, установленным на то, что я хочу, установленным флагом серьезности и тем, что, я надеюсь, является правильным средством.

Это в сочетании с CreateErrorInfo и SetErrorInfo дает мне код ошибки и описание ошибки в VB6.

0
ответ дан 14 December 2019 в 19:22
поделиться

Ознакомьтесь с этой статьей http: / /support.microsoft.com/kb/827994. Итак, ваш объект должен реализовывать метод ISupportsErrorInfo :: InterfaceSupportsErrorInfo (), который возвращает S_OK. а затем перед возвратом вы должны вызвать SetErrorInfo с указателем на COM-объект, который реализует IErrorInfo :: GetDescription (). Вот пример: http://msdn.microsoft.com/en-us/library/ms221409.aspx .

Если вы установите SetErrorInfo перед возвратом, VB запросит метод GetDescription для указателя объекта, который вы передали в SetErrorInfo.

Я не слишком глубоко разбираюсь в атрибутивном коде, который вы используете - я бы предпочел протестировать его, используя более чистый COM, который, безусловно, всегда является большим количеством шаблонного кода - но, по крайней мере, он работает, тогда вы можете использовать сложные оболочки вместо это.

0
ответ дан 14 December 2019 в 19:22
поделиться
Другие вопросы по тегам:

Похожие вопросы: