c++调用COM组件的坑

c++调用COM组件的坑

最近在工作中,需要用到COM组件来完成任务。再调用过程中,遇到一些平常容易忽略的错误,记录一下,避免自己再犯同样的错误。
首先来看一段代码:

// 查找桌面文件视图
bool FindDesktopFolderView(REFIID riid, void **ppv)

{
	CComPtr<IShellWindows> spShellWindows;
	HRESULT hr = spShellWindows.CoCreateInstance(CLSID_ShellWindows);
	if (!SUCCEEDED(hr))
	{
		*ppv = NULL;
		return false;
	}
	CComVariant vtLoc(CSIDL_DESKTOP);
	CComVariant vtEmpty;
	long lhwnd;
	CComPtr<IDispatch> spdisp;

	hr = spShellWindows->FindWindowSW(
		&vtLoc, &vtEmpty,
		SWC_DESKTOP, &lhwnd, SWFO_NEEDDISPATCH, &spdisp);
	if (!SUCCEEDED(hr))
	{
		*ppv = NULL;
		return false;
	}

	CComPtr<IShellBrowser> spBrowser;
	hr = CComQIPtr<IServiceProvider>(spdisp)->
		QueryService(SID_STopLevelBrowser,
		IID_PPV_ARGS(&spBrowser));
	if (!SUCCEEDED(hr) || NULL == spBrowser)
	{
		*ppv = NULL;
		return false;
	}
	
	CComPtr<IShellView> spView;
	hr = spBrowser->QueryActiveShellView(&spView);
	if (!SUCCEEDED(hr) || NULL == spView)
	{
		*ppv = NULL;
		return false;
	}

	hr = spView->QueryInterface(riid, ppv);
	if (!SUCCEEDED(hr))
	{
		*ppv = NULL;
		return false;
	}
	return true;
}

上面这段代码的功能是查找桌面视图。咋一看,没什么问题,它确实能在大部分情况下工作。但是当桌面窗口未初始化完成时,问题就出现了(这个也是我们在线上实实在在遇到的问题)。
当执行spShellWindows->FindWindowSW()函数时,返回的HRESULT结果是S_OK。那么照理说,这次查找桌面窗口应该是成功的。但是实际上,spdisp这个指针是空的!!!这里没有判断空指针,导致程序崩溃。屋漏偏逢连夜雨!由于,我们的项目是将该工程以动态库的方式提供给golang调用(有点绕了),用c++ dump方式无法定位崩溃原因。用golang 的recover()捕获panic同样无法定位崩溃原因(大哭)。
后面将加上空指针判断以后, 程序终于正常工作了。修复代码如下:

// 查找桌面文件视图
bool FindDesktopFolderView(REFIID riid, void **ppv)

{
	CComPtr<IShellWindows> spShellWindows;
	HRESULT hr = spShellWindows.CoCreateInstance(CLSID_ShellWindows);
	if (!SUCCEEDED(hr))
	{
		*ppv = NULL;
		return false;
	}
	CComVariant vtLoc(CSIDL_DESKTOP);
	CComVariant vtEmpty;
	long lhwnd;
	CComPtr<IDispatch> spdisp;

	hr = spShellWindows->FindWindowSW(
		&vtLoc, &vtEmpty,
		SWC_DESKTOP, &lhwnd, SWFO_NEEDDISPATCH, &spdisp);
		// 这里既要判断hr 又要判断空指针
	if (!SUCCEEDED(hr) || NULL == spdisp)
	{
		*ppv = NULL;
		return false;
	}

	CComPtr<IShellBrowser> spBrowser;
	hr = CComQIPtr<IServiceProvider>(spdisp)->
		QueryService(SID_STopLevelBrowser,
		IID_PPV_ARGS(&spBrowser));
		// 这里既要判断hr 又要判断空指针
	if (!SUCCEEDED(hr) || NULL == spBrowser)
	{
		*ppv = NULL;
		return false;
	}

	CComPtr<IShellView> spView;
	hr = spBrowser->QueryActiveShellView(&spView);
	// 这里既要判断hr 又要判断空指针
	if (!SUCCEEDED(hr) || NULL == spView)
	{
		*ppv = NULL;
		return false;
	}

	hr = spView->QueryInterface(riid, ppv);
	if (!SUCCEEDED(hr))
	{
		*ppv = NULL;
		return false;
	}
	return true;
}

这里提醒一下自己,不要被SUCCEEDED(hr)接口麻痹,写c++任何时候都要判断空指针!!!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值