在DLL中考虑这个注册类型库:
[uuid(…), version(1.0)]
library structLib
{
importlib("stdole2.tlb");
[uuid(…)]
typedef struct MyStruct
{
BSTR m_sStr;
} MyStruct;
};
在vb6中,我可以引用这个类型库并在编译的exe(带有按钮的简单形式)中使用UDT / struct,名为 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代码针对未修改的类型库(包含struct)编译成名为 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(找不到元素)
当类型库中缺少struct定义时。
这种行为是否符合vb6设计?原因是什么?是否有可能启动vb6可执行文件并捕获错误信息,即使提取引用结构的类型信息失败也是如此?
答案 0 :(得分:0)
这种行为是否在vb6中设计?
我不这么认为。
原因是什么?
将IDL结构分配给VARIANT时,本质上会使用[uuid]属性。由于它不再存在,你得到一个例外。
在C ++中调用GetRecordInfoFromGuids
时所执行的操作,您明确提供了IDL结构__uuidof(structLib::MyStruct)
的uuid。
即使在提取类型时也可以启动可执行文件 引用结构的信息失败了吗?
我看到了实现这一目标的两种可能性: