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

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上为啥就不行了呢?难道是WICWindows7上不支持?这个怀疑显然是不成立的,从MSDN上来看从XP SP2就开始支持了啊:

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

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

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

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
调用 COM 组件的方法有多种方法,下面是其中的几种示例代码: 1. 使用 CreateInstance 函数创建 COM 对象并调用方法: ``` CoInitialize(NULL); // 初始化 COM 组件 ISomeInterface* pSomeInterface = NULL; HRESULT hr = CoCreateInstance(CLSID_SomeComponent, NULL, CLSCTX_ALL, IID_ISomeInterface, (void**)&pSomeInterface); if (SUCCEEDED(hr)) { pSomeInterface->SomeMethod(); pSomeInterface->Release(); } CoUninitialize(); // 释放 COM 组件 ``` 2. 使用 IDispatch 接口调用 COM 对象的方法: ``` CoInitialize(NULL); // 初始化 COM 组件 IDispatch* pDispatch = NULL; HRESULT hr = CoCreateInstance(CLSID_SomeComponent, NULL, CLSCTX_ALL, IID_IDispatch, (void**)&pDispatch); if (SUCCEEDED(hr)) { VARIANTARG varg1, varg2, varg3; VariantInit(&varg1); VariantInit(&varg2); VariantInit(&varg3); // 设置参数 varg1.vt = VT_I4; varg1.lVal = 1; varg2.vt = VT_BSTR; varg2.bstrVal = SysAllocString(L"Hello"); varg3.vt = VT_BOOL; varg3.boolVal = VARIANT_TRUE; DISPPARAMS dispparams = { &varg1, &varg2, &varg3, 3, 0 }; // 调用方法 VARIANT variantResult; VariantInit(&variantResult); hr = pDispatch->Invoke(DISPID_SomeMethod, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_METHOD, &dispparams, &variantResult, NULL, NULL); // 处理返回值 if (SUCCEEDED(hr)) { // do something with variantResult VariantClear(&variantResult); } VariantClear(&varg1); VariantClear(&varg2); VariantClear(&varg3); pDispatch->Release(); } CoUninitialize(); // 释放 COM 组件 ``` 3. 使用 ATL 的 CComPtr 类模板调用 COM 对象的方法: ``` CoInitialize(NULL); // 初始化 COM 组件 CComPtr<ISomeInterface> pSomeInterface; HRESULT hr = pSomeInterface.CoCreateInstance(CLSID_SomeComponent); if (SUCCEEDED(hr)) { pSomeInterface->SomeMethod(); } CoUninitialize(); // 释放 COM 组件 ``` 以上示例仅供参考,具体实现方式可能因 COM 组件的实现方式和语言而有所不同。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值