Рассмотрим эту зарегистрированную библиотеку типов в DLL:Почему UDT/struct с отсутствующей информацией о типе причины приводит к сбою при запуске в vb6?
[uuid(…), version(1.0)]
library structLib
{
importlib("stdole2.tlb");
[uuid(…)]
typedef struct MyStruct
{
BSTR m_sStr;
} MyStruct;
};
В VB6 я могу ссылаться на эту библиотеку типов и использовать UDT/структуры в скомпилированный ехе (простая форма с кнопкой), названный a.exe : не
Private Sub Command1_Click()
Dim obj As structLib.MyStruct
obj.m_sStr = "Hello"
MsgBox obj.m_sStr
End Sub
Когда я извлекаю из-структуры библиотеки типов и пересобрать, ранее составленный a.exe до сих пор работает, хотя определение структуры больше не присутствует. Я предполагаю, что это удается, потому что определение встроено в исполняемый файл во время процесса компиляции vb6.
Однако, все работает по-другому, когда я скомпилировать следующий код vb6 против библиотеки неизмененном типа (структура включена) в новый исполняемый файл, названный b.exe:
Private Sub Command1_Click()
Dim obj As structLib.MyStruct
obj.m_sStr = "Hello"
MsgBox obj.m_sStr
Dim vt as Variant
vt = obj
MsgBox vt.m_sStr
End Sub
Уведомление о присвоении структуры до Variant
.
Когда я удаляю определение структуры из библиотеки типов еще раз, перекомпилируйте его и попробуйте запустить ранее скомпилированный b.exe, программа молча провалится, так как форма не будет отображаться. Как минимум, я ожидал
- Запуск исполняемого файла загружает форму.
- Щелчок по кнопке вызывает ошибку, из-за назначения структуры с отсутствующей информацией о типе на
Variant
.
Для записи, я попытался воспроизвести это поведение в C++:
structLib::MyStruct obj;
obj.m_sStr = SysAllocString(L"Hello");
MessageBox(GetActiveWindow(), obj.m_sStr, obj.m_sStr, MB_OK);
ATL::CComVariant vtRec;
ATL::CComPtr<IRecordInfo> piRecInfo;
HRESULT hr = GetRecordInfoFromGuids(__uuidof(structLib::__structLib), 1, 0, 0, __uuidof(structLib::MyStruct), &piRecInfo);
vtRec.pRecInfo = piRecInfo;
vtRec.pvRecord = &obj;
PVOID pvItem = vtRec.pvRecord;
CComVariant vtStr;
hr = piRecInfo->GetField(pvItem, L"m_sStr", &vtStr);
MessageBox(GetActiveWindow(), vtStr.bstrVal, vtStr.bstrVal, MB_OK);
Здесь C++ работает клиент и GetRecordInfoFromGuids()
правильно возвращает
0x8002802b (Элемент не найден)
, когда определение структуры отсутствует в библиотеке типов.
Это поведение в vb6 по дизайну? В чем причина? И можно ли запустить информацию об ошибках исполняемого файла vb6 и catch, даже если извлечение информации о типе ссылочной структуры не выполняется?
Существует [отдельная ошибка] (http://stackoverflow.com/q/975982/11683) для этого в VB6/A. Это ошибка времени компиляции, поэтому, если вы ее обойдете, это не удивительно, что программа выйдет из строя. – GSerg
Я бы не прочь получить ошибку из-за отсутствия информации о типе UDT. Меня беспокоит то, что vb6 exe даже не запускается. Это не должно происходить, так как фрагмент кода ('vt = obj') находится в обработчике командной строки, который не выполняется во время загрузки формы. Я ожидал поведения, подобного клиенту C++, где код запускается до извлечения информации о типе ('GetRecordInfoFromGuids()'), которая, в свою очередь, сообщает об ошибке. – Aurora
В C++ это не ошибка времени компиляции. В VB это ошибка времени компиляции, и что-то может произойти, если вы обманете программу над ней. – GSerg