【问题标题】:Why am I getting an OutOfMemoryException from the Clipboard class?为什么我从 Clipboard 类中得到 OutOfMemoryException?
【发布时间】:2018-12-19 17:29:33
【问题描述】:

我正在尝试使用System.Windows.Clipboard 类从剪贴板获取图像:

var bitmapSource = System.Windows.Clipboard.GetImage();

当通过 PrintScreen 键复制图像时,它可以正常工作。但是,当从医疗应用程序复制图像时,出现以下异常:

System.OutOfMemoryException: Insufficient memory to continue the execution of the program.
   at System.Runtime.InteropServices.ComTypes.IDataObject.GetData(FORMATETC& format, STGMEDIUM& medium)
   at System.Windows.DataObject.OleConverter.GetDataInner(FORMATETC& formatetc, STGMEDIUM& medium)
   at System.Windows.DataObject.OleConverter.GetDataFromOleOther(String format, DVASPECT aspect, Int32 index)
   at System.Windows.DataObject.OleConverter.GetData(String format, Boolean autoConvert, DVASPECT aspect, Int32 index)
   at System.Windows.DataObject.OleConverter.GetData(String format, Boolean autoConvert)

图像在 Paint 和 Word 上粘贴良好,因此图像被正确复制到剪贴板。这不是一个巨大的图像,所以我绝对没有内存不足。有什么想法吗?

调用Clipboard.GetDataObject().GetFormats() 会返回以下内容:

{string[11]}
    [0]: "Rich Text Format"
    [1]: "MetaFilePict"
    [2]: "PNG+Office Art"
    [3]: "Office Drawing Shape Format"
    [4]: "DeviceIndependentBitmap"
    [5]: "Bitmap"
    [6]: "System.Drawing.Bitmap"
    [7]: "System.Windows.Media.Imaging.BitmapSource"
    [8]: "Format17"
    [9]: "EnhancedMetafile"
    [10]: "System.Drawing.Imaging.Metafile"

我对上述每种格式都尝试了Clipboard.GetData(format),唯一返回非空对象的是“PNG+Office Art”、“Office Drawing Shape Format”、“Format17”和“EnhancedMetafile”。

【问题讨论】:

  • 听起来像是 serialization 的工作(虽然不确定在这种情况下这是一个骗子)。
  • @ChrisW。问题是我的应用程序不会将任何内容复制到剪贴板;它只是粘贴,所以数据应该已经序列化了。
  • 请注意,GDI+ 会给出一个OutOfMemoryException 来表示与实际内存不足完全无关的大量错误。
  • @Nyerguds 是的,我不相信它与内存有关。
  • 你真的添加了对System.Drawing.Image的引用吗?因为,您使用var 作为类型快捷方式并调用变量bitmapSource... 但Clipboard.GetImage() 不返回System.Windows.Media.Imaging.BitmapSource 对象。

标签: c# wpf windows


【解决方案1】:

我相信你的答案是here。简而言之:

结论是,如果您在 WPF 中使用剪贴板,并且您得到的 System.OutOfMemoryExceptions 似乎没有任何意义,那么您可能忘记将 SerializableAttribute 添加到您放置在剪贴板。

那么这个医疗应用程序是您的应用程序吗?因为看起来问题在于如何将图像放入剪贴板,而不是如何检索图像。

更新:既然这不是你的应用程序,那么你可能不得不忍受他们的错误(或Clipboard.GetData() 中的错误)。 The source code of Clipboard.GetImage()是这个:

public static Image GetImage() {
    var dataObject = Clipboard.GetDataObject();
    if (dataObject != null) {
        return dataObject.GetData(DataFormats.Bitmap, true) as Image;
    }

    return null;
}

请注意,您的堆栈跟踪表明异常发生在GetData()。查看源代码,这意味着对GetDataObject() 的调用有效,这意味着您可以(理论上)自己使用GetDataObject() 并将IDataObject 从它转换为您可以使用的东西。

可能需要进行一些探索才能弄清楚发生了什么。您也许可以使用IDataObject.GetFormats() 来检查它是什么,然后使用IDataObject.GetData() 来获取该格式的数据。

更新 2:here 的解决方案为我们指明了正确的方向,但需要一些修改:

var data = Clipboard.GetDataObject();
var ms = (MemoryStream) data.GetData("PNG+Office Art");

var image = Image.FromStream(ms)

【讨论】:

  • 这不是我的医疗应用程序,所以我无法控制它。但我相信图像已正确复制到剪贴板,因为我可以将其粘贴到 Paint 和 Word。
  • 好吧,如果是图像,“添加属性”是无关紧要的,因为Image 是一个框架库。
  • @redcurry 请注意,there are many ways of copying an image to the clipboard... 和 MS Office 更喜欢 PNG MemoryStream 对象,因为经典的 windows 图像剪贴板不支持透明度。您可能需要更深入地了解该剪贴板上的确切内容。
  • 嗯,似乎我链接到了错误的帖子... the one in which I detailed multiple clipboard formats 实际上是在对该答案的评论中提到的。顺便说一句,Bitmap 是抽象Image 类的标准实现,所以这意味着MemoryStream 包含有效图像文件的字节。如果您有一些特定于 WPF 的方式将这些字节作为图像打开,那么直接执行此操作可能会更简单。
猜你喜欢
  • 1970-01-01
  • 2014-08-10
  • 1970-01-01
  • 1970-01-01
  • 2018-09-28
  • 1970-01-01
  • 1970-01-01
  • 2013-12-18
  • 1970-01-01
相关资源
最近更新 更多