我有一些代码可以在几台机器上完美运行(开发,QA,UAT).不幸的是,在生产中我得到"GDI +中出现了一般错误" bmp.Save(ms, ImageFormat.Png);
因此,我假设你无法重现问题,但也许有人可以发现我的错误.
一些注释,我已经搜索了很多常见的解决方案,请注意这是保存到一个MemoryStream
所以大多数人建议不适用的文件权限问题,"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(String text)+383
注意:我的问题已经列举了拟议副本中的解决方案.没有问题.如果它们也会因JPEG而失败.
在.NET参考源代码在这里,在保存到数据流的情况下,会从原生方法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框架.更多细节:
在已知良好的机器和生产机器之间比较%windir%\ system32中该dll的版本.该DLL有数百个依赖项,因此即使文件本身的版本匹配,请参阅修补您的操作系统.
PNG格式的内置编解码器是Windows的WIC组件的一部分,驻留在WindowsCodecs.dll和WindowsCodecsExt.dll中 - 也检查这些库的版本.您提到的注册表项也应指向WindowsCodecsExt.dll.
不是基于recherche,只是想法:您是通过虚拟化/远程桌面连接访问生产服务器吗?如果可以,请尝试控制台会话.尝试不同的屏幕分辨率和颜色深度.尝试调试/发布版本.确保您确实已在发布版本配置中清除了DEBUG检查.尝试构建x64和MSIL.如果您在生产中使用NGEN,请尝试不使用.