Ошибка в ITypeInfo::GetTypeAttr для скомпилированного класса

Программирование на Visual Basic, главный форум. Обсуждение тем программирования на VB 1—6.
Даже если вы плохо разбираетесь в VB и программировании вообще — тут вам помогут. В разумных пределах, конечно.
Правила форума
Темы, в которых будет сначала написано «что нужно сделать», а затем просьба «помогите», будут закрыты.
Читайте требования к создаваемым темам.
ger_kar
Продвинутый гуру
Продвинутый гуру
Аватара пользователя
 
Сообщения: 1957
Зарегистрирован: 19.05.2011 (Чт) 19:23
Откуда: Кыргызстан, Иссык-Куль, г. Каракол

Ошибка в ITypeInfo::GetTypeAttr для скомпилированного класса

Сообщение ger_kar » 11.12.2013 (Ср) 17:31

Вот код, который я использовал, что-бы сделать перечисление методов объекта.
Код: Выделить всё
Private Sub EnumClassMembers(ByRef oObject As olelib.IDispatch)
   
    Dim oTypeInfo   As olelib.ITypeInfo
    Dim stTA(0)     As TYPEATTR, pstTA  As Long
    Dim stFD(0)     As FUNCDESC, pstFD  As Long
    Dim lIndex      As Long
    Dim Name        As String
    Dim Description As String
   
    'Получение ссылки на интерфейс ITypeInfo
    Set oTypeInfo = oObject.GetTypeInfo
    'Получение указателя на структуру TYPEATTR и подмонтирование к ней массива
    pstTA = oTypeInfo.GetTypeAttr:
    Call SaMap(AryPtr(stTA), pstTA)

        'Цикл по всем функциям и получение инфы о каждой
        For lIndex = 0 To stTA(0).cFuncs - 1
           
            'Получение указателя на структуру FUNCDESC и подмонтирование к ней массива
            pstFD = oTypeInfo.GetFuncDesc(lIndex): Call SaMap(AryPtr(stFD), pstFD)
                If stFD(0).invkind = VbGet Then
                    oTypeInfo.GetDocumentation stFD(0).memid, Name, Description, 0, vbNullString
                    Call ViewRest(Name, Description)
                End If
            'Отмонтирование массива и освобождение памяти под структуру FUNCDESC
            Call SaUnmap(AryPtr(stFD)): oTypeInfo.ReleaseFuncDesc pstFD
           
        Next
       
    'Отмонтирование массива и освобождение памяти под структуру TYPEATTR
    Call SaUnmap(AryPtr(stTA)): oTypeInfo.ReleaseTypeAttr pstTA
   
..........

End Sub

Под olelib.ITypeInfo имеется ввиду TLB Edanmo's OLE interfaces & functions v1.81
При запусках под IDE все работало идеально (да и сейчас работает), но как оказалось в скомпилированном виде такой код не работает. Все валится на строке pstTA = oTypeInfo.GetTypeAttr с ошибкой Ошибка - 445. (Object doesn't support this action) или (Объект не поддерживает данную операцию) в русской интерпретации. Вот так номер!, почему под IDE метод получается есть, а в скомпилированном виде метод пропал.
Последний раз редактировалось ger_kar 12.12.2013 (Чт) 15:13, всего редактировалось 1 раз.
Бороться и искать, найти и перепрятать

Хакер
Телепат
Телепат
Аватара пользователя
 
Сообщения: 16478
Зарегистрирован: 13.11.2005 (Вс) 2:43
Откуда: Казахстан, Петропавловск

Re: Куда делся метод?

Сообщение Хакер » 11.12.2013 (Ср) 17:36

Ну а почему должен? Небось Standard EXE проект и приватный class. TLB в ресурсах нет. Правильно угадываю?
—We separate their smiling faces from the rest of their body, Captain.
—That's right! We decapitate them.

ger_kar
Продвинутый гуру
Продвинутый гуру
Аватара пользователя
 
Сообщения: 1957
Зарегистрирован: 19.05.2011 (Чт) 19:23
Откуда: Кыргызстан, Иссык-Куль, г. Каракол

Re: Куда делся метод?

Сообщение ger_kar » 11.12.2013 (Ср) 18:08

Хакер писал(а):Небось Standard EXE проект и приватный class. TLB в ресурсах нет. Правильно угадываю?
ЯЯ внатуре! Но!
Хакер писал(а):Ну а почему должен?
Ну потому (по моему разумению), что TLB здесь нужна на этапе компиляции, а дальше вызов метода будет жестко вшит в код с конкретным смещением в VTable по типу раннего связывания и все.
Бороться и искать, найти и перепрятать

Хакер
Телепат
Телепат
Аватара пользователя
 
Сообщения: 16478
Зарегистрирован: 13.11.2005 (Вс) 2:43
Откуда: Казахстан, Петропавловск

Re: Куда делся метод?

Сообщение Хакер » 11.12.2013 (Ср) 18:57

ger_kar писал(а):Ну потому (по моему разумению), что TLB здесь нужна на этапе компиляции, а дальше вызов метода будет жестко вшит в код с конкретным смещением в VTable по типу раннего связывания и все.

Ну так он же и вшивается. Вызов идёт к реализации, реализация говорит: «я пасс, я всего лишь заглушка».
—We separate their smiling faces from the rest of their body, Captain.
—That's right! We decapitate them.

ger_kar
Продвинутый гуру
Продвинутый гуру
Аватара пользователя
 
Сообщения: 1957
Зарегистрирован: 19.05.2011 (Чт) 19:23
Откуда: Кыргызстан, Иссык-Куль, г. Каракол

Re: Куда делся метод?

Сообщение ger_kar » 11.12.2013 (Ср) 19:01

Ну а под IDE она получается не заглушка что-ли? Почему под IDE все очень даже замечательно работает и в ус не дует.
Бороться и искать, найти и перепрятать

Хакер
Телепат
Телепат
Аватара пользователя
 
Сообщения: 16478
Зарегистрирован: 13.11.2005 (Вс) 2:43
Откуда: Казахстан, Петропавловск

Re: Куда делся метод?

Сообщение Хакер » 11.12.2013 (Ср) 20:17

Конечно не заглушка.
По-моему это должно быть очевидно.

Под IDE реализация методов ITypeInfo живёт внутри vba6.dll, а в работе скомпилированного файла — внутри msvbvm60.dll. Равно как и все рантаймовые функции (типа MsgBox) и внутренние функции (типа DllFunctionCall).
—We separate their smiling faces from the rest of their body, Captain.
—That's right! We decapitate them.

ger_kar
Продвинутый гуру
Продвинутый гуру
Аватара пользователя
 
Сообщения: 1957
Зарегистрирован: 19.05.2011 (Чт) 19:23
Откуда: Кыргызстан, Иссык-Куль, г. Каракол

Re: Куда делся метод?

Сообщение ger_kar » 11.12.2013 (Ср) 20:59

Да, обидно конечно, что так получилось, знал бы заранее о такой лаже, сделал бы проще. Можно было не парится с перечислением методов класса, а просто сделать внутри класса строку со списком методов через разделитель и дополнительный метод, который будет все это добро через Split выдавать на гора в виде массива. И работать будет быстрее и проблем особо не будет, только при изменении методов не забывать подправить строку список. И что я сразу так не сделал.
Бороться и искать, найти и перепрятать

Хакер
Телепат
Телепат
Аватара пользователя
 
Сообщения: 16478
Зарегистрирован: 13.11.2005 (Вс) 2:43
Откуда: Казахстан, Петропавловск

Re: Куда делся метод?

Сообщение Хакер » 11.12.2013 (Ср) 21:32

Зачем это вообще нужно?
—We separate their smiling faces from the rest of their body, Captain.
—That's right! We decapitate them.

ger_kar
Продвинутый гуру
Продвинутый гуру
Аватара пользователя
 
Сообщения: 1957
Зарегистрирован: 19.05.2011 (Чт) 19:23
Откуда: Кыргызстан, Иссык-Куль, г. Каракол

Re: Куда делся метод?

Сообщение ger_kar » 11.12.2013 (Ср) 21:53

Ну для разных целей, но в основном для сокращения рутинных операций с портянками кода, которые можно сократить. Например есть некий класс с полями свойствами, данные в которые загружаются из рекордсета. Если есть список имен свойств, которые совпадают с именами полей рекордсета, то достаточно в метод передать ссылку на рекордсет и идентификатор записи и получить заполненный данными объект. И все это одна строк кода, а не портянка на десяток другой строк. Или например есть объект системы ограничений на просмотр информации в зависимости от прав пользователя, у него имена совпадают с именами столбцов грида. Можно конечно приспособить свойства с параметром, но это тоже не очень удобно. Классов, где требуется такое заполнение много, придется такой функционал вставлять в кучу мест. А у меня все было все в одной единственной функции. И было очень удобно.
Бороться и искать, найти и перепрятать

Хакер
Телепат
Телепат
Аватара пользователя
 
Сообщения: 16478
Зарегистрирован: 13.11.2005 (Вс) 2:43
Откуда: Казахстан, Петропавловск

Re: Куда делся метод?

Сообщение Хакер » 12.12.2013 (Чт) 0:39

Почему бы не использовать параметрическое свойство и итерацию через список ключей?
—We separate their smiling faces from the rest of their body, Captain.
—That's right! We decapitate them.

ger_kar
Продвинутый гуру
Продвинутый гуру
Аватара пользователя
 
Сообщения: 1957
Зарегистрирован: 19.05.2011 (Чт) 19:23
Откуда: Кыргызстан, Иссык-Куль, г. Каракол

Re: Куда делся метод?

Сообщение ger_kar » 12.12.2013 (Чт) 7:42

Ну коли нельзя использовать перечисление методов, то придется делать отдельный список оных. Т.е. список методов это и будет по сути список ключей. И вся реализация тогда сведется к следующему:
Внутри класса завести константу со списком вида "Key1|Key2|key3|...", ну или через запятую, но мне больше нравится так :)
Свойство например Members или Metods, которое будет выдавать массив с ключами списка через Split и дополнительное свойство с параметром например:
Код: Выделить всё
    Public Property Get Value(ByRef sPropName As String) As Variant
        Value = CallByName(Me, sPropName, VbGet)
    End Property
   
    Public Property Let Value(ByRef sPropName As String, ByVal Value As Variant)
        Call CallByName(Me, sPropName, VbLet, Value)
    End Property

Это имелось ввиду? Мне по крайней мере сейчас видится такой способ реализации, наверное есть и другие.
Бороться и искать, найти и перепрятать

ger_kar
Продвинутый гуру
Продвинутый гуру
Аватара пользователя
 
Сообщения: 1957
Зарегистрирован: 19.05.2011 (Чт) 19:23
Откуда: Кыргызстан, Иссык-Куль, г. Каракол

Re: Куда делся метод?

Сообщение ger_kar » 12.12.2013 (Чт) 7:47

Хакер писал(а):По-моему это должно быть очевидно.Под IDE реализация методов ITypeInfo живёт внутри vba6.dll, а в работе скомпилированного файла — внутри msvbvm60.dll. Равно как и все рантаймовые функции (типа MsgBox) и внутренние функции (типа DllFunctionCall).
А по моему вот нихрена не очевидно. Ну зачем вообще было делать реализациию в vba6.dll и глушить тоже самый, по сути уже реализованный функционал в msvbvm60.dll. Смысла в этом нет никакого.
Бороться и искать, найти и перепрятать

Vi
Постоялец
Постоялец
 
Сообщения: 739
Зарегистрирован: 25.01.2002 (Пт) 11:03
Откуда: Россия, Ижевск

Re: Куда делся метод?

Сообщение Vi » 12.12.2013 (Чт) 10:10

Хакер писал(а):Под IDE реализация методов ITypeInfo живёт внутри vba6.dll, а в работе скомпилированного файла — внутри msvbvm60.dll. Равно как и все рантаймовые функции (типа MsgBox) и внутренние функции (типа DllFunctionCall).

ИМХО, реализация методов интерфейса ITypeInfo живёт в oleaut32.dll и поддерживаются системой, даже если VB нет на машине и в помине. Что-то в ваших рассуждениях непонятно.
Vita
Выше головы не прыгнешь, ниже земли не упадешь, дальше границы не убежишь! (с) КВН

ger_kar
Продвинутый гуру
Продвинутый гуру
Аватара пользователя
 
Сообщения: 1957
Зарегистрирован: 19.05.2011 (Чт) 19:23
Откуда: Кыргызстан, Иссык-Куль, г. Каракол

Re: Куда делся метод?

Сообщение ger_kar » 12.12.2013 (Чт) 10:10

Vi писал(а):А почему бы не использовать обычный IDispatch, который поддерживается системой?
Каким образом его использовать? Как IDispatch может дать список свойств? Он может только проверить наличие метода и вызвать метод по имени если таковой есть и все.
Бороться и искать, найти и перепрятать

Vi
Постоялец
Постоялец
 
Сообщения: 739
Зарегистрирован: 25.01.2002 (Пт) 11:03
Откуда: Россия, Ижевск

Re: Куда делся метод?

Сообщение Vi » 12.12.2013 (Чт) 10:20

ger_kar писал(а):
Vi писал(а):А почему бы не использовать обычный IDispatch, который поддерживается системой?
Каким образом его использовать? Как IDispatch может дать список свойств? Он может только проверить наличие метода и вызвать метод по имени если таковой есть и все.

Я уже понял, что интересует не IDispatch, а ITypeInfo, который не предоставляется для работы в VB. Но та библиотека, о которой ты говоришь, должна предоставить работу с этим интерфейсом или его аналогом для VB клиента. Поэтому дело вообще не в ITypeInfo или его суррогатах.

oObject.GetTypeInfo (а такой метод есть и у стандартного IDispatch) возвращает ошибку или пустой объект, я так понимаю проблему?
Vita
Выше головы не прыгнешь, ниже земли не упадешь, дальше границы не убежишь! (с) КВН

ger_kar
Продвинутый гуру
Продвинутый гуру
Аватара пользователя
 
Сообщения: 1957
Зарегистрирован: 19.05.2011 (Чт) 19:23
Откуда: Кыргызстан, Иссык-Куль, г. Каракол

Re: Куда делся метод?

Сообщение ger_kar » 12.12.2013 (Чт) 10:27

Vi писал(а):oObject.GetTypeInfo (а такой метод есть и у стандартного IDispatch) возвращает ошибку или пустой объект, я так понимаю проблему?
Нет с этим проблем нет, ссылка на ITypeInfo возвращается, проблема начинается дальше, при вызове методов самого ITypeInfo, т.е. обламывается здесь pstTA = oTypeInfo.GetTypeAttr. Причем под IDE все работает без сучка и задоринки, а в скомпилированном виде получается, что интерфейс есть, а метода нет.
Бороться и искать, найти и перепрятать

ger_kar
Продвинутый гуру
Продвинутый гуру
Аватара пользователя
 
Сообщения: 1957
Зарегистрирован: 19.05.2011 (Чт) 19:23
Откуда: Кыргызстан, Иссык-Куль, г. Каракол

Re: Куда делся метод?

Сообщение ger_kar » 12.12.2013 (Чт) 10:40

На всякий случай дополнительно убедился:
Код: Выделить всё
Set oTypeInfo = oObject.GetTypeInfo
    If oTypeInfo Is Nothing Then MsgBox "Приплыли..." Else MsgBox "Все ок... " & Hex$(ObjPtr(oTypeInfo))

oObject.GetTypeInfo Возвращает валидную ссылку на интерфейс ITypeInfo. И как спрашивается это понимать, если есть этот конкретно взятый интерфейс, то и все соответствующие методы ему присущие тоже должны быть, а иначе тогда это должен быть другой интерфейс. А тут такая лажа.
Бороться и искать, найти и перепрятать

Vi
Постоялец
Постоялец
 
Сообщения: 739
Зарегистрирован: 25.01.2002 (Пт) 11:03
Откуда: Россия, Ижевск

Re: Куда делся метод?

Сообщение Vi » 12.12.2013 (Чт) 10:44

ger_kar писал(а):
Vi писал(а):oObject.GetTypeInfo (а такой метод есть и у стандартного IDispatch) возвращает ошибку или пустой объект, я так понимаю проблему?
Нет с этим проблем нет, ссылка на ITypeInfo возвращается, проблема начинается дальше, при вызове методов самого ITypeInfo, т.е. обламывается здесь pstTA = oTypeInfo.GetTypeAttr. Причем под IDE все работает без сучка и задоринки, а в скомпилированном виде получается, что интерфейс есть, а метода нет.

Похоже, Хакер как всегда прав. Возвращается объект из этой твоей Edanmo's OLE interfaces & functions v1.81 библиотеки, хотя в данном случае он должен его не возвращать, потому что объекту, который поддерживает IDispatch, позволительно не возвращать ITypeInfo, который описывает работу с его членами. Поэтому должен обламываться Set oTypeInfo = oObject.GetTypeInfo, а не последующие обращения к его методам. Это скорее бага Edanmo.

Поэтому в режиме IDE библиотека типов одна, а во время компиляции библиотека другая. В одной поддерживается локальные классы, в другой - нет.

Так переведи класс из локального в публичный без возможности его создания.
Vita
Выше головы не прыгнешь, ниже земли не упадешь, дальше границы не убежишь! (с) КВН

Хакер
Телепат
Телепат
Аватара пользователя
 
Сообщения: 16478
Зарегистрирован: 13.11.2005 (Вс) 2:43
Откуда: Казахстан, Петропавловск

Re: Куда делся метод?

Сообщение Хакер » 12.12.2013 (Чт) 12:49

ger_kar писал(а):А по моему вот нихрена не очевидно. Ну зачем вообще было делать реализациию в vba6.dll и глушить тоже самый, по сути уже реализованный функционал в msvbvm60.dll. Смысла в этом нет никакого.

IDE не использует msvbvm60.dll никак. Ибо в этом нет смысла. vba6.dll и msvbvm60.dll — они скомпилированы из одного и того же кода, но с разными ключами условной компиляции (#if...#endif). И по-разному слинкованы. Всё. В рантайме боевые, облегчённые и отуплённые варианты функций. В vba6 — полные, нацеленные на использования при отладке проектов. Тот же обработчик ошибок в рантайме завершает проект, а под IDE — выдаёт диалог с Continue/End кнопками. Именно из-за этой разницы мой кирпич для вызова по указателям имеет две почти не пересекающихся ветки в коде.

ger_kay писал(а):И как спрашивается это понимать, если есть этот конкретно взятый интерфейс, то и все соответствующие методы ему присущие тоже должны быть, а иначе тогда это должен быть другой интерфейс.

Я не понимаю. Вернее, похоже ты до сих пор не понимаешь. Судя по этому тексту, ты думаешь, что нужного тебе метода там нет вообще? Нет реализации? Нет ячейки в VTable? И VB не найдя ячейку в VTable жалуется? И недоумеваешь, как же, мол, так: интерфейс тот же, а набор методов отличается?

Да есть там метод. Есть ячейка в VTable, и реализация есть... примерно такая:
Код: Выделить всё
HRESULT CVbClassTypeInfo::GetTypeAttr(TYPEATTR** ppTypeAttr)
{
     return E_NOTIMPL;
}


А вот уже VB получив HRESULT с кодом E_NOTIMPL (not implemented) возвращает ту красноречивую ошибку, что ты видишь.

Vi писал(а):ИМХО, реализация методов интерфейса ITypeInfo живёт в oleaut32.dll и поддерживаются системой, даже если VB нет на машине и в помине. Что-то в ваших рассуждениях непонятно.

Нет, интерфейс — он на то и интерфейс, что может существовать десяток разных классов, его поддерживающих, имеющих разные реализации.

Убедиться в том, что я прав — легко. Достаточно посмотреть потроха интерфейса и VTable под отладчиком.

При работе под IDE:
vb_itypeinfo_impl_rev_eng_vba.png
vb_itypeinfo_impl_rev_eng_vba.png (47.86 Кб) Просмотров: 9737

Хорошо видно: интерфейс живёт в куче, VTable для интерфейса — в секции данных VBA6.DLL, реализации методов — в секции кода VBA6.DLL



То же самое, но запускаю скомпилированный вариант:
vb_itypeinfo_impl_rev_eng_vbrt.png
vb_itypeinfo_impl_rev_eng_vbrt.png (39.13 Кб) Просмотров: 9737

Здесь у меня уже есть отладочные символы для рантайма, так что наглядность существенно увеличивается.

Итак: сам интерфейс живёт в секции данных (ахтунг! ger_kar, это как раз тот случай, о котором я тебе когда-то говорил) нашего EXE-файла, VTable для интерфейса — внутри рантайма, реализации методов интерфейса — внутри рантайма.

Но если приглядеться, то в VTable вместо некоторых методов стоят какие-то не те имена. Что это, битые символы? На самом деле — нет.

Если мы посмотрим на объявление ITypeInfo, то увидим, что он унаследован от IUnknown и первым же методом идёт как раз проблемный GetTypeAttr:
vb_itypeinfo_impl_rev_eng_methods_order.png
vb_itypeinfo_impl_rev_eng_methods_order.png (8.97 Кб) Просмотров: 9737


Теперь сравним вывод OleView и ту vtbl, которую мы видим под отладчиком:
vb_itypeinfo_impl_rev_eng_vbrt_strange_entries.png
vb_itypeinfo_impl_rev_eng_vbrt_strange_entries.png (51.7 Кб) Просмотров: 9737


Итак, вместо ожидаемого CEcTypeInfo::GetTypeAttr мы видим CTL::EnumConnectionPoints. Что это? Баг? Битые отладочные символы?

На самом неделе — нет, всё нормально, ни багов, ни битых символов. Это просто результат оптимизации, проделанной сишным компилятором при компиляции рантайма в недрах MS. Компиляция проходилась без отладочных опций, поэтому компилятор взял пачку дублирующихся процедур с абсолютно идентичным телом, но разными именами, и заменил их все на одну единственную. Соответственно, имя она получила, видимо, то, которое шло последним по алфавиту из списка дубликатов.

Пойдём и посмотрим, какая же там реализация?
vb_itypeinfo_impl_rev_eng_gettypeattr_impl.png
vb_itypeinfo_impl_rev_eng_gettypeattr_impl.png (1.79 Кб) Просмотров: 9737


Не нужно быть экспертом, чтобы понять, что реализация предельно простая: она просто возвращает HRESULT с кодом 0x80004001, а сама процедура принимает два параметра (this и ещё один).

Я думаю, все уже догадались, что 0x80004001 это и есть E_NOTIMPL, а я наверху правильно предугадал реализацию метода GetTypeAttr.

Таки да, и CEcTypeInfo::GetTypeAttr, и CTL::EnumConnectionPoints имели эквивалентный код:
Код: Выделить всё
HRESULT _stdcall CEcTypeInfo::GetTypeAttr(TYPEATTR** ppTypeAttr)
{
    return E_NOTIMPL;
}

Код: Выделить всё
HRESULT _stdcall CTL::EnumConnections(IEnumConnections** ppenum)
{
     return E_NOTIMPL;
}

поэтому компилятор слил их все в одно целое.

Все остальные методы, которые там выше видно, и которые выбиваюттся их темы (типа Scroll) — это тоже заглушки с E_NOTIMPL, которые использовались в чёрт знает скольки местах, и компилятор их все сгруппировал по принципу (принимает N-аргументов, возвращает E_NOTIMPL).

Конечно же, я не делал всех этих исследований при изначальном ответе, но моё представление о сути вещей были в абсолютной точности таким, каким оно оказалось. Так что да, Хакер оказался как всегда прав :)


Ну и кстати, насчёт того, что реализация ITypeInfo должна жить в oleaut32.dll. Оно так и есть, если ссылка на интерфейс получена от LoadTypeLib, LoadTypeLib, CreateTypeLib, CreateTypeLibEx, которые в этой библиотеке живут.
—We separate their smiling faces from the rest of their body, Captain.
—That's right! We decapitate them.

Хакер
Телепат
Телепат
Аватара пользователя
 
Сообщения: 16478
Зарегистрирован: 13.11.2005 (Вс) 2:43
Откуда: Казахстан, Петропавловск

Re: Ошибка в ITypeInfo::GetTypeAttr для скомпилированного кл

Сообщение Хакер » 12.12.2013 (Чт) 13:46

Вот если тип проекта поменять c Standard EXE на ActiveX EXE, тогда внутри проекта (в ресурсах) появляется TLB и рантайм может загрузить это TLB из самого себя при помощи LoadTypeLib(Ex).

И тогда-то реализация интерфейса ITypeInfo находится уже внутри oleaut32.dll, а значит должна быть полноценной:
vb_itypeinfo_impl_rev_eng_vbrt_and_actxexe.png
vb_itypeinfo_impl_rev_eng_vbrt_and_actxexe.png (22.84 Кб) Просмотров: 9732
—We separate their smiling faces from the rest of their body, Captain.
—That's right! We decapitate them.

Vi
Постоялец
Постоялец
 
Сообщения: 739
Зарегистрирован: 25.01.2002 (Пт) 11:03
Откуда: Россия, Ижевск

Re: Ошибка в ITypeInfo::GetTypeAttr для скомпилированного кл

Сообщение Vi » 12.12.2013 (Чт) 14:41

:king: :cheers:
Vita
Выше головы не прыгнешь, ниже земли не упадешь, дальше границы не убежишь! (с) КВН

Хакер
Телепат
Телепат
Аватара пользователя
 
Сообщения: 16478
Зарегистрирован: 13.11.2005 (Вс) 2:43
Откуда: Казахстан, Петропавловск

Re: Ошибка в ITypeInfo::GetTypeAttr для скомпилированного кл

Сообщение Хакер » 12.12.2013 (Чт) 14:55

К слову, информация об именах методов в EXE-файла всё-таки есть (иначе IDispatch не имел бы способа, чтобы работать). Выудить её можно, но это уже будет черная магия. С другой стороны, с учётом того, что VB уже не поменяется, это может быть приемлемым в некоторых случаях.

Удобнее всего это будет сделать, написав свою реализацию ITypeInfo, которая будет использовать в только в рантайме.
—We separate their smiling faces from the rest of their body, Captain.
—That's right! We decapitate them.

ger_kar
Продвинутый гуру
Продвинутый гуру
Аватара пользователя
 
Сообщения: 1957
Зарегистрирован: 19.05.2011 (Чт) 19:23
Откуда: Кыргызстан, Иссык-Куль, г. Каракол

Re: Ошибка в ITypeInfo::GetTypeAttr для скомпилированного кл

Сообщение ger_kar » 12.12.2013 (Чт) 15:06

Хакер писал(а):Так что да, Хакер оказался как всегда прав :)
Это точно :) . Получается, что в момент отладки для реализации методов ITypeInfo VBA6.DLL черпает информацию прямо из отлаживаемого проекта, а рантайм этого уже сделать не может по понятным причинам. А как же тогда работает функция CallByName, ведь она без всякой TLB знает, есть или нет нужный метод по имени, что-бы затем его вызвать. Получается имена методов можно добыть и другим способом, не за действуя ITypeInfo? А зачем делать свою реализацию ITypeInfo если можно и так добыть информацию, пусть даже посредством самой чернющей маггии (эх знать бы куда колдовать :) ) Видимо надо посмотреть как работает CallByName в отладчике?
Последний раз редактировалось ger_kar 12.12.2013 (Чт) 15:12, всего редактировалось 1 раз.
Бороться и искать, найти и перепрятать

Хакер
Телепат
Телепат
Аватара пользователя
 
Сообщения: 16478
Зарегистрирован: 13.11.2005 (Вс) 2:43
Откуда: Казахстан, Петропавловск

Re: Ошибка в ITypeInfo::GetTypeAttr для скомпилированного кл

Сообщение Хакер » 12.12.2013 (Чт) 15:12

ger_kar писал(а):А как же тогда работает функция CallByName, ведь она без всякой TLB знает, есть или нет нужный метод по имени, что-бы затем его вызвать. Получается имена методов можно добыть и другим способом, не за действуя ITypeInfo?Хакер

Я уже написал выше. CallByName — обёртка над IDispatchh::Invoke. Реализация этого метода живёт в рантайме (BASIC_CLASS_Invoke, даже экспортируется насколько я помню) и использует таблицы соответствия, вшитые в сам exe-шник.
—We separate their smiling faces from the rest of their body, Captain.
—That's right! We decapitate them.

ger_kar
Продвинутый гуру
Продвинутый гуру
Аватара пользователя
 
Сообщения: 1957
Зарегистрирован: 19.05.2011 (Чт) 19:23
Откуда: Кыргызстан, Иссык-Куль, г. Каракол

Re: Ошибка в ITypeInfo::GetTypeAttr для скомпилированного кл

Сообщение ger_kar » 12.12.2013 (Чт) 15:17

Хакер писал(а):Реализация этого метода живёт в рантайме (BASIC_CLASS_Invoke, даже экспортируется насколько я помню) и использует таблицы соответствия, вшитые в сам exe-шник.
Т.е. нужно найти и посмотреть эти таблицы в отладчике, узнать как там это все устроено и пробовать добыть имена методов оттуда?
Бороться и искать, найти и перепрятать

Vi
Постоялец
Постоялец
 
Сообщения: 739
Зарегистрирован: 25.01.2002 (Пт) 11:03
Откуда: Россия, Ижевск

Re: Ошибка в ITypeInfo::GetTypeAttr для скомпилированного кл

Сообщение Vi » 12.12.2013 (Чт) 15:21

Хакер писал(а):
ger_kar писал(а):А как же тогда работает функция CallByName, ведь она без всякой TLB знает, есть или нет нужный метод по имени, что-бы затем его вызвать. Получается имена методов можно добыть и другим способом, не за действуя ITypeInfo?Хакер

Я уже написал выше. CallByName — обёртка над IDispatch::Invoke. Реализация этого метода живёт в рантайме (BASIC_CLASS_Invoke, даже экспортируется насколько я помню) и использует таблицы соответствия, вшитые в сам exe-шник.

CallByName — обёртка над двумя функциями IDispatch::GetIDsOfNames и IDispatch::Invoke, т.е. GetIDsOfNames+Invoke. Определение наличия имени в списке методов - это GetIDsOfNames, вызов же этого метода уже по номеру(ID) - это Invoke. Поэтому некоторые надстройки над IDispatch разделяют эту магию на два этапа для ускорения: GetIDsOfNames+Invoke+Invoke+Invoke...

Можно запустить [A-Za-z0-9_]+ цикл для определения всех имён объекта. Вот только что с ними делать - параметры ведь неизвестны.
Vita
Выше головы не прыгнешь, ниже земли не упадешь, дальше границы не убежишь! (с) КВН

Хакер
Телепат
Телепат
Аватара пользователя
 
Сообщения: 16478
Зарегистрирован: 13.11.2005 (Вс) 2:43
Откуда: Казахстан, Петропавловск

Re: Ошибка в ITypeInfo::GetTypeAttr для скомпилированного кл

Сообщение Хакер » 12.12.2013 (Чт) 15:27

Vi писал(а):Вот только что с ними делать - параметры ведь неизвестны.

Я думаю, что то же, что и раньше. Сомневаюсь, что ger_kar, получив список методов, ещё и интересовался, какие у них аргументы. У него, скорее всего, куча методов с одинаковым прототипом, и засчёт этого: некий полиморфизм на уровне методов.

Поэтому ему только список необходим, так как все методы вызываются одинаковым образом. Я угадал?

Вообще, конечно, с точки зрения ООП и COM в частности — это очень грязный и противоестественный подход.

Если есть особые классы, с какими-то динамическими наборами методов, то им следует поддерживать особый общий интерфейс, предоставляющий наружу способ получения информации о наборах уницифированных методов. А может быть — и способ их вызова.
—We separate their smiling faces from the rest of their body, Captain.
—That's right! We decapitate them.

ger_kar
Продвинутый гуру
Продвинутый гуру
Аватара пользователя
 
Сообщения: 1957
Зарегистрирован: 19.05.2011 (Чт) 19:23
Откуда: Кыргызстан, Иссык-Куль, г. Каракол

Re: Ошибка в ITypeInfo::GetTypeAttr для скомпилированного кл

Сообщение ger_kar » 12.12.2013 (Чт) 15:38

Хакер писал(а):Поэтому ему только список необходим, так как все методы вызываются одинаковым образом. Я угадал?
Конечно, так и есть. Мне нужны только названия.
Хакер писал(а):Если есть особые классы, с какими-то динамическими наборами методов, то им следует поддерживать особый общий интерфейс, предоставляющий наружу способ получения информации о наборах уницифированных методов.
Вот тут и встает вопрос где эту информацию взять. Либо опросить сам класс, и узнать что он содержит (чистая автоматизация :) ) либо дополнительно нужно вести отдельный список.
Бороться и искать, найти и перепрятать


Вернуться в Visual Basic 1–6

Кто сейчас на конференции

Сейчас этот форум просматривают: Google-бот и гости: 56

    TopList