CoCreateInstance调用返回代码0x80040154的一种解决方法

引言

前面的一篇博文中总结了开发Windows Thumbnail Handler的一些经验。在公司实际项目中,需要同时针对图片和视频实现缩略图。同时还要在图片和视频文件的顶部加上LOGO。像如下这样的:

于是考虑了一下实现方案:

(1)LOGO资源采用Base64编码编译到DLL中去

(2)公司自有的图片和视频文件进行全景拼接时依赖一串参数,而这串参数需要从文件中提取。因此采用RecipeThumbnailProvider实现IInitializeWithFile接口比较合适,这样能得到文件路径,具备更灵活的可操作性。

(3)LOGO资源使用Windows自带的解码库来进行解码,也就是Windows Image Component(WIC).

这么一思考,还是挺靠谱的。于是就动手开始编码,编写了一个解码LOGO资源的函数:

/**
 * Decode the Base64-encoded string to get logo resources.
 */
HRESULT RecipeThumbnailProvider::GetLogoFromString(LPCWSTR encodedString, UINT* width, UINT* height, PBYTE* rawPixels)
{
	IStream* pImageStream = NULL;
	HRESULT hr = E_FAIL;
	DWORD dwDecodedImageSize = 0;
	DWORD dwSkipChars = 0;
	DWORD dwActualFormat = 0;

	if (CryptStringToBinary(encodedString, NULL, CRYPT_STRING_BASE64, NULL, &dwDecodedImageSize, &dwSkipChars, &dwActualFormat))
	{
		BYTE* pbDecodedImage = static_cast<BYTE*>(LocalAlloc(LPTR, dwDecodedImageSize));
		if (pbDecodedImage)
		{
			if (CryptStringToBinary(encodedString, lstrlen(encodedString), CRYPT_STRING_BASE64, pbDecodedImage, &dwDecodedImageSize, &dwSkipChars, &dwActualFormat))
			{
				pImageStream = SHCreateMemStream(pbDecodedImage, dwDecodedImageSize);
				if (pImageStream != NULL)
				{
					IWICImagingFactory* pImageFactory;
					hr = CoCreateInstance(CLSID_WICImagingFactory, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&pImageFactory));
					LOGINFO(L"CoCreateIntance() returns 0x%x", hr);
					if (SUCCEEDED(hr))
					{
						IWICBitmapDecoder* pDecoder;
						hr = pImageFactory->CreateDecoderFromStream(pImageStream, &GUID_VendorMicrosoft, WICDecodeMetadataCacheOnDemand, &pDecoder);
						if (SUCCEEDED(hr))
						{
							IWICBitmapFrameDecode* pBitmapFrameDecode;
							hr = pDecoder->GetFrame(0, &pBitmapFrameDecode);
							if (SUCCEEDED(hr))
							{
								IWICBitmapSource* pBitmapSourceConverted = NULL;
								WICPixelFormatGUID guidPixelFormatSource;
								hr = pBitmapFrameDecode->GetPixelFormat(&guidPixelFormatSource);
								if (SUCCEEDED(hr) && (guidPixelFormatSource != GUID_WICPixelFormat24bppBGR))
								{
									IWICFormatConverter* pFormatConverter;
									hr = pImageFactory->CreateFormatConverter(&pFormatConverter);
									if (SUCCEEDED(hr))
									{
										hr = pFormatConverter->Initialize(pBitmapFrameDecode, GUID_WICPixelFormat24bppBGR, WICBitmapDitherTypeNone, NULL, 0, WICBitmapPaletteTypeCustom);
										if (SUCCEEDED(hr))
										{
											hr = pFormatConverter->QueryInterface(&pBitmapSourceConverted);
										}
										pFormatConverter->Release();
									}
								}
								else
								{
									hr = pBitmapFrameDecode->QueryInterface(&pBitmapSourceConverted);
								}
								if (SUCCEEDED(hr))
								{
									hr = pBitmapSourceConverted->GetSize(width, height);
									if (SUCCEEDED(hr))
									{
										WICRect rect = { 0, 0, *width, *height };
										*rawPixels = static_cast<BYTE*>(LocalAlloc(LPTR, (*width)*(*height)*3));
										hr = pBitmapSourceConverted->CopyPixels(&rect, (*width) * 3, (*width)*(*height) * 3, *rawPixels);
									}
									else
									{
										*width = 0;
										*height = 0;
										*rawPixels = NULL;
									}
									pBitmapSourceConverted->Release();
								}
								pBitmapFrameDecode->Release();
							}
							pDecoder->Release();
						}
						pImageFactory->Release();
					}
					pImageStream->Release();
				}
			}
		}

		LocalFree(pbDecodedImage);
	}
	return hr;
}

  当我注册好COM组件开始使用时,在本机上测试简直完美。满以为就这么搞定了,然而并么有。在另外一台Win7机器上测试时,缩略图中并没有出现想象中的LOGO。一看日志文件,发现一直在报:CoCreateInstance()调用返回0x80040154。于是下面的代码都没执行,LOGO资源自然没有加载成功了。那么CoCreateInstance()为啥会返回0x80040154呢?这个代码又意味着什么嗯?从网上的搜索结果来看,0x80040154是表示"Class Not Registered"。也就是说COM类并没有注册,在注册表\HKEY_CLASSES_ROOT\CLSID\下面也就没有类ID了。我们程序中使用了WIC组件来解码图片,那么难道是WIC组件类没有注册吗?

再一想,开发时采用的一直是Windows10,可以正常运行。到了Windows7上为啥就不行了呢?难道是WIC在Windows7上不支持?这个怀疑显然是不成立的,从MSDN上来看从XP SP2就开始支持了啊:

那么难道是参数给的不对?以CLSID_WICImagingFactory为关键字一搜索果然搜到了一篇帖子CLSID_WICImagingFactory在Windows10上被解析为了CLSID_WICImagingFactory2:

而这个GUID在Windows7上是不存在的(搜索注册表即可看到结果):

自然CoCreateInstance()调用就会返回0x80040154了。解决方案就是传递CLSID_WICImagingFactory1给CoCreateInstance()。这样就能同时兼容Windows10和Windows7了。

参考链接

  1. http://stackoverflow.com/questions/16697112/why-using-wic-in-my-32-bit-application-fails-in-windows-7-32-bit
时间: 2024-11-06 10:22:44

CoCreateInstance调用返回代码0x80040154的一种解决方法的相关文章

mysql主从数据库不同步的2种解决方法(转)

今天发现Mysql的主从数据库没有同步 先上Master库: mysql>show processlist; 查看下进程是否Sleep太多.发现很正常. show master status; 也正常. mysql> show master status; +-------------------+----------+--------------+-------------------------------+ | File | Position | Binlog_Do_DB | Binlo

iOS Mac忘记登录密码的4种解决方法

4种方法: 一.使用Apple ID重置用户账户密码 使用这个方法有一个前提 如上图红框,此项必须勾选,否则无法使用Apple ID重置密码.(如果你不记得有没有勾选,则你起码要记得首次启动 OS X 或装有 OS X Lion 或更高版本的全新 Mac 时,你会进入“OS X 设置助理”,其中需要你输入 Apple ID.输入 Apple ID 后,请在“创建您的帐户”阶段选择“允许我的 Apple ID 重设此用户的密码”选项.) 好了,来说下具体实现的方法: 如果您在登录窗口错误输入帐户密

OGG的Director web hang住的两种解决方法

OGG的Director web hang住的两种解决方法: OGG的Director web hang住的解释:是指web界面能登陆进去,但是看得刷新日期是很久之前的日期,并且该日期不变化. OGG的Director web hang住 的情况之一: 参考如下的mos文章: Director web displaying "Error 500-Internal Server Error". Domain log has Cannot open paging store. (Doc I

WORD Application.Documents.Open函数返回null的一种解决方法

DCOM Config Setting for "Microsoft Office Word 97 - 2003 Document" 内部配置一切正常,但Application.Documents.Open函数还是返回null.下面是一个解决方法: "C:\Windows\SysWOW64\config\systemprofile\"目录下创建一个"Desktop"目录. WORD Application.Documents.Open函数返回nu

php:undefined index的几种解决方法

平时用$_post[''],$_get['']获取表单中参数时会出现Notice: Undefined index: --------: 虽然可以通过设置错误显示方式来隐藏这个提示,但是这样也有隐患,就是在服务器的日志中会记录这些提示,导致日志文件异常庞大. 通过在网上搜索和自己自身的实战总结几种解决方法: 方法1:服务器配置修改 修改php.ini配置文件,error_reporting = E_ALL & ~E_NOTICE 方法2:对变量进行初始化. 方法3:做判断isset($_post

.NET中TextBox控件设置ReadOnly=true后台取不到值三种解决方法

.NET中TextBox控件设置ReadOnly=true后台取不到值三种解决方法 当TextBox设置了ReadOnly=true后要是在前台为控件添加了值,后台是取不到的,值为空,多么郁闷的一个问题经过尝试,发现可以通过如下的方式解决这个问题.感兴趣的朋友可以了解下 当TextBox设置了ReadOnly="true" 后,要是在前台为控件添加了值,后台是取不到的,值为“空” 原理没想通,说不清楚微软是出于什么考虑的,不过有时是要我们能通过前台脚本来填充值,并不希望用户修改其控件内

SVN被锁定的几种解决方法

用SVN经常出现被锁定而无法提交的问题,选择解锁又提示没有文件被锁定,很是头疼. 这里整理了一下SVN 被锁定的几种解决方法: 1.出现这个问题后使用"清理"即"Clean up"功能,如果还不行,就直接到上一级目录,再执行"清理",然后再"更新". 2.有时候如果看到某个包里面的文件夹没有SVN的标志,直接用"Ctrl+Delete"手工删除,然后"清理",最后"更新&quo

ASP+中文显示之两种解决方法

作者刚开始写ASP+程序时候碰到的第一个比较大的问题就是中文显示问题,运行后发现ASP+从数据库中读 取出来的中文全部变成了?????,有点类似jsp中的这个频率出现最高的中文显示问题了,查了资料发现有 两种方法可以轻松解决中文问题. 方法一: 在翻阅了微软NGWS文档后发现在文档的常见问题部分有提到要添加一个config.web文件到 web目录下,试了一下,中文显示果然OK了. 方法如下: 建立一个文件config.web,内容如下,放在WEB目录下 <configuration> <

解决jquery中动态新增的元素节点无法触发事件的问题有两种解决方法

解决jquery中动态新增的元素节点无法触发事件的问题有两种解决方法,如下: 为了达到更好的演示效果,假设在某个页面的body下有以下结构的代码: ? 1 2 3 4 5 6 7 8 9 10 11 <p id="pLabel">新加一条</p> <ul id="ulLabel">  <li class="liLabel">aaa1</li>  <li class="li