将位图保存到MemoryStream时,GDI +中发生了一般错误

时间:2015-12-06 18:23:58

标签: c# gdi+

我有一些代码可以在几台机器上完美运行(开发,QA,UAT)。不幸的是,在制作过程中我得到了GDI +"发生了一般性错误。 bmp.Save(ms, ImageFormat.Png);上的结果,我假设您无法重现问题,但也许有人可以发现我的错误。

一些注释,我已经搜索了很多常见解决方案,请注意这是保存到MemoryStream所以大多数人建议的文件权限问题不适用,&#34也没有;打开时bmp被锁定"解决方案,因为我再次在其他地方写作。最后,这不是因为png需要可搜索的流,因为MemoryStream是可搜索的。

注意,如果我将其更改为ImageFormat.Jpeg,它可以正常工作。我只对PNG有问题。我发现提及注册表项HKEY_CLASSES_ROOT\CLSID\{FAE3D380-FEA4-4623-8C75-C6B61110B681}可能是由于权限导致的问题。因此,我设置了密钥以允许Everyone具有对此密钥的读取权限,无需更改。

public static MemoryStream GenerateImage(string text)
{
    MemoryStream ms = new MemoryStream();
    using (Bitmap bmp = new Bitmap(400,400))
    {
        bmp.Save(ms, ImageFormat.Png);
        ms.Position = 0;
    }
    return ms;
}

这是完整的堆栈跟踪:

  

[ExternalException(0x80004005):GDI +中发生一般错误。]
  System.Drawing.Image.Save(Stream stream,ImageCodecInfo encoder,   EncoderParameters encoderParams)+616457
  WP.Tools.Img.GenerateImage(字符串   文字)+383

注意:我的问题已经列举了拟议副本中的解决方案。没有问题。如果它们也会因JPEG而失败。

1 个答案:

答案 0 :(得分:5)

.NET参考源代码here,在save-to-stream的情况下,从对本机方法GdipSaveImageToStream的调用中获取状态值:

public void Save(Stream stream, ImageCodecInfo encoder, EncoderParameters encoderParams) {

    ...

    if (!saved)
    {
        status = SafeNativeMethods.Gdip.GdipSaveImageToStream(new HandleRef(this,nativeImage),new UnsafeNativeMethods.ComStreamFromDataStream(stream),ref g,new HandleRef(encoderParams, encoderParamsMemory));
    }

    ...

}

此状态值是用于从该方法引发异常的唯一API返回值。当我们进一步研究StatusException函数时,它根据状态代码决定抛出什么类型的异常,我们只找到一个可能的状态值来导致你得到的ExternalException(来自Gdiplus.cs,第3167行):

switch (status)
{
    case GenericError:
        return new ExternalException(SR.GetString(SR.GdiplusGenericError), E_FAIL);

    ...
}

0x80004005是"未指定错误",SR.GdiplusGenericError是文本" GDI +中发生了一般错误。"你得到了。这排除了我们可能怀疑的其他几种可能性(这将导致不同的例外),即:

  • 内存不足
  • 对象忙
  • 缓冲不足
  • win32error
  • valueoverflow
  • unknownimageformat
  • 未找到/不支持的属性
  • unsupportedgdiplusversion

本机方法驻留在 gdiplus.dll 中。长话短说,修补你的生产服务器,修复.NET框架。更多细节:

  1. 在已知良好的机器和生产机器之间比较%windir%\ system32中该dll的版本。该DLL有数百个依赖项,因此即使文件本身的版本匹配,请参阅修补您的操作系统。
  2. PNG格式的内置编解码器是Windows的WIC组件的一部分,驻留在 WindowsCodecs.dll WindowsCodecsExt.dll 中 - 检查这些的版本图书馆也是如此。您提到的注册表项也应指向WindowsCodecsExt.dll。
  3. 不是基于recherche,只是想法:您是否通过虚拟化/远程桌面连接访问生产服务器?如果可以,请尝试控制台会话。尝试不同的屏幕分辨率和颜色深度。尝试调试/发布版本。确保您确实已在发布版本配置中清除了DEBUG检查。尝试构建x64和MSIL。如果您在生产中使用NGEN,请尝试不使用。