首页 > 解决方案 > 为什么我从 Clipboard 类中得到 OutOfMemoryException?

问题描述

我正在尝试使用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”。

标签: c#wpfwindows

解决方案


我相信你的答案就在这里。简而言之:

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

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

更新:由于这不是您的应用程序,那么您可能不得不忍受他们的错误(或 中的错误Clipboard.GetData())。的源代码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:此处的解决方案为我们指明了正确的方向,但需要进行一些修改:

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

var image = Image.FromStream(ms)

推荐阅读