2017-02-02 19 views
2

Рассмотрим эту зарегистрированную библиотеку типов в 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, даже если извлечение информации о типе ссылочной структуры не выполняется?

+0

Существует [отдельная ошибка] (http://stackoverflow.com/q/975982/11683) для этого в VB6/A. Это ошибка времени компиляции, поэтому, если вы ее обойдете, это не удивительно, что программа выйдет из строя. – GSerg

+0

Я бы не прочь получить ошибку из-за отсутствия информации о типе UDT. Меня беспокоит то, что vb6 exe даже не запускается. Это не должно происходить, так как фрагмент кода ('vt = obj') находится в обработчике командной строки, который не выполняется во время загрузки формы. Я ожидал поведения, подобного клиенту C++, где код запускается до извлечения информации о типе ('GetRecordInfoFromGuids()'), которая, в свою очередь, сообщает об ошибке. – Aurora

+0

В C++ это не ошибка времени компиляции. В VB это ошибка времени компиляции, и что-то может произойти, если вы обманете программу над ней. – GSerg

ответ

0

Это поведение в vb6 по дизайну?

Я так не считаю.

В чем причина?

Когда вы назначаете структуру IDL для VARIANT, атрибут [uuid] используется по умолчанию. Поскольку он больше не существует, вы получаете исключение.

Это то, что вы делаете при вызове GetRecordInfoFromGuids в C++, вы явно предоставляете uuid структуры IDL __uuidof(structLib::MyStruct).

И можно ли запустить исполняемый файл, даже если извлечение типа информация об упомянутой структуре не удалась?

Я вижу 2 возможности для достижения этой цели:

  1. использование позднего связывания вместо раннего связывания, а также проверить ссылку
  2. обрабатывает исключение, которое брошено
+1

Спасибо за ваши предложения, однако мои вопросы касались исполняемого файла vb6. Проблема в том, что исполняемый файл vb6 (** b.exe **) не запускается; вероятно, потому, что код все еще содержит инструкции для получения информации о типе удаленной структуры. Это не дает мне возможности поймать ошибку. Что касается позднего связывания, я не думаю, что можно создать экземпляр структуры без конкретного типа. – Aurora