3,248
社区成员




在已知com组件的函数名并获取到参数的FuncDesc后,可以通过FuncDesc->lprgelemdescParam[i].tdesc去逐层获取到参数的类型。
例如int类型在lprgelemdescParam中会先标识,也就是指针类型,然后再标识int类型。当然如果是自定义类型。则需要判断FuncDesc->lprgelemdescParam[i].tdesc.lptdesc.vt的类型是否为29,vt为29即表示该类型为用户自定义类型。总而言之,当类型不为29时,则可根据variant的枚举去判断类型。当类型为29时,则需要获取FuncDesc->lprgelemdescParam[i].tdesclptdesc->hreftype,并使用GetDocumentation去获取文档中类型的字符。
要获取COM组件中已知函数名和参数名的参数类型,可以使用以下方法:
使用Type Library Viewer工具查看Type Library(TLB)文件。TLB文件包含了COM组件中所有公开接口、方法和参数的信息。你可以从Microsoft Office程序中找到相应的TLB文件,或者使用第三方工具生成。
使用OLE/COM Object Viewer工具查看COM组件的类型库信息。这个工具可以帮助你查看COM组件中的方法、属性和事件等信息。
在代码中使用Type Library Import库来获取参数类型。首先,你需要将Type Library导入到你的项目中,然后使用CoClassInfo函数获取类信息,最后使用DispCallFunc或DispCallFuncI函数调用方法并获取返回值。
以下是一个C++示例,展示了如何使用Type Library Import库获取参数类型:
#import "C:\Program Files (x86)\Common Files\microsoft shared\OFFICE16\MSO.DLL" rename("DialogBox", "MsoDialogBox") rename("RGB", "MsoRGB") rename("DocumentProperties", "MsoDocumentProperties") no_dual_interfaces
#include
#include <Windows.h>
#include <atlbase.h>
#include <atlcom.h>
#include <atlctl.h>
#include <msotlb.h>
int main()
{
HRESULT hr = CoInitialize(NULL);
if (FAILED(hr))
{
std::cerr << "Failed to initialize COM library." << std::endl;
return 1;
}
// 获取类信息
CComPtr<IMsoDispObj> pDispObj;
hr = CComObject<CMsoDialogBox>::CreateInstance(&pDispObj);
if (FAILED(hr))
{
std::cerr << "Failed to create instance of MsoDialogBox." << std::endl;
CoUninitialize();
return 1;
}
// 获取参数类型
CComVariant varParams[2];
varParams[0] = _variant_t("Caption");
varParams[1] = _variant_t("Message");
CComQIPtr<IMsoDispParams> pDispParams = pDispObj;
hr = pDispParams->Invoke(0x00000000, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_PROPERTYPUT, NULL, &varParams, 2, NULL, NULL);
if (FAILED(hr))
{
std::cerr << "Failed to call method." << std::endl;
CoUninitialize();
return 1;
}
// 输出参数类型
CComQIPtr<IDispatch> pDispatch;
hr = pDispObj->QueryInterface(IID_IDispatch, (void**)&pDispatch);
if (SUCCEEDED(hr))
{
CComVariant varResult;
hr = pDispatch->Invoke(0x00000000, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_PROPERTYGET, NULL, &varResult, NULL, NULL);
if (SUCCEEDED(hr))
{
std::cout << "Parameter types:" << std::endl;
for (int i = 0; i < 2; ++i)
{
CComVariant varType;
hr = varResult.GetOneDimArrayInit(&varType);
if (SUCCEEDED(hr))
{
CString strType;
VariantClear(&varType);
strType.Format(L"%ls", varResult.bstrVal);
std::wcout << L"Parameter " << i + 1 << L": " << strType << std::endl;
}
}
}
pDispatch->Release();
}
CoUninitialize();
return 0;
}
请注意,这个示例仅适用于特定版本的Office,你需要根据实际情况修改TLB文件路径和导入语句。