CoCreateInstance调用返回代码0x80040154的一种解决方法(CoCreateInstance调用返回代码0x80040154的一种解决方法)
CoCreateInstance调用返回代码0x80040154的一种解决方法(CoCreateInstance调用返回代码0x80040154的一种解决方法)那么难道是参数给的不对?以CLSID_WICImagingFactory为关键字一搜索果然搜到了一篇帖子:CLSID_WICImagingFactory在Windows10上被解析为了CLSID_WICImagingFactory2:再一想,开发时采用的一直是Windows10,可以正常运行。到了Windows7上为啥就不行了呢?难道是WIC在Windows7上不支持?这个怀疑显然是不成立的,从MSDN上来看从XP SP2就开始支持了啊:(3)LOGO资源使用Windows自带的解码库来进行解码,也就是Windows Image Component(WIC).这么一思考,还是挺靠谱的。于是就动手开始编码,编写了一个解码LOGO资源的函数:/** * Decode the Base64-encoded string to get logo resources. */ HRESUL
引言前面的一篇博文中总结了开发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了。
参考链接- http://stackoverflow.com/questions/16697112/why-using-wic-in-my-32-bit-application-fails-in-windows-7-32-bit