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了。

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

  1. python无法使用1号gpu_详解tensorflow2.x版本无法调用gpu的一种解决方法

    最近学校给了一个服务器账号用来训练神经网络使用,服务器本身配置是十路titan V,然后在上面装了tensorflow2.2,对应的python版本是3.6.2,装好之后用tf.test.is_gpu ...

  2. bs4 乱码_Python BeautifulSoup中文乱码问题的2种解决方法

    解决方法一: 使用python的BeautifulSoup来抓取网页然后输出网页标题,但是输出的总是乱码,找了好久找到解决办法,下面分享给大家 首先是代码 复制代码 代码如下: from bs4 im ...

  3. php无限极 left right,php无限极分类实现的两种解决方法

    本篇文章介绍了,在php中无限极分类实现的两种解决方法.需要的朋友参考下 method of classify one<?php /* reader: 这是自己写的无限极分类实现方法 里面的编辑 ...

  4. android中view手势滑动冲突的两种解决方法

    android中view手势滑动冲突的解决方法,主要解决方法有两种,外部和内部拦截.有需要的可以参考下. Android手势事件的冲突跟点击事件的分发过程息息相关,由三个重要的方法来共同完成,分别是: ...

  5. win7 计算机管理的命令,Win7运行cmd命令提示“命令提示符已被系统管理员停用”三种解决方法...

    在运行win7操作系统中,经常使用运行命令对系统进行一些设置.最近有用户在Win7系统下运行CDM命令时,提示"命令提示符已被系统管理员停用"(如图),导致无法正常使用命令功能,遇 ...

  6. ARM32平台系统crash(系统崩溃) 问题定位的一种解决方法

    说明 分享一种crash问题定位的一种解决方法,仅供参考. ARM32平台上通过错误使用内存,触发系统异常,系统崩溃.系统异常被挂起后,能在串口中看到异常调用栈打印信息和关键寄存器信息. 如下所示,e ...

  7. 没有注册类别的一种解决方法

    没有注册类别的一种解决方法 修改以前老的vs程序,其中用到了老的串口控件,MSCOMM32.OCX, 按照要求注册完后,报错"没有注册类别",重启后依然报错, 查找到网友提供的解决 ...

  8. scrapy:Unknown command: crawl 的3种解决方法

    一.报错 报错的界面截图: 报错解析:该报错是找不到配置文件,无法执行douban 项目.可能原因如下: 路径不对:没有切换路径到douban 项目下或没有把douban 文件夹添加到一个sys路径: ...

  9. php取数组中连续数,PHP实现求连续子数组最大和问题2种解决方法

    本文实例讲述了PHP实现求连续子数组最大和问题2种解决方法.分享给大家供大家参考,具体如下: 问题描述 求子数组的最大和 题目描述: 输入一个整形数组,数组里有正数也有负数. 数组中连续的一个或多个整 ...

最新文章

  1. Mozilla 宣布引入二步认证
  2. 图像的打开、修改、显示和保存示例(OpenCV 2.0)
  3. Django MPTT —— 概述
  4. javaweb连接不上mysql怎么办_java web应用连接mysql会突然connection连接失败
  5. redis服务器端和客户端启动
  6. 鸿蒙还是不是安卓,华为捐赠鸿蒙核心架构!是否形成“三足鼎立”?
  7. mysql并发 node_nodejs写入mysql单次数据量过大的解决方法_沃航科技
  8. 泡沫or趋势?我们到底需要什么样的区块链?
  9. 已知若干点求圆心_【求精干货】高中数学知识点总结归纳高一学生必须掌握
  10. Linux安全加固--系统相关
  11. 三、K8s常见操作命令
  12. RCP中如何使用代码安装、运行plugins
  13. 求一个数因数个数c语言,【代码】求一个数的因数和、求优化、顺便也供新人参考算法...
  14. elasticjob 源码分析
  15. 【antdesign】表单布局和校验
  16. VSCode如何更换背景图片
  17. IntelliJ IDEA更换主题样式分享
  18. 如何用手机保存APP上的视频
  19. 网络安全——Burpsuite
  20. 高智商与低智商的区别_体内平衡与智力的定义

热门文章

  1. 常见解压缩软件与其zip格式
  2. db2建库、建表空间基本流程
  3. LINQ语法类似于SQL的语法
  4. 解决 html5 input type='number' 类型可以输入e
  5. OpenStack对象存储——Swift
  6. 转Oracle性能参数—经典常用
  7. 网页设计中时尚​​的下拉菜单案例
  8. html怎么限制密码字母个数字,怎样限制密码长度,并且只能为字母数字及下划线组成?...
  9. 最长上升子序列模板 hdu 1087 Super Jumping! Jumping! Jumping!
  10. 解决ORA-01578错误一例