分析:
从dump和log看到是:
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.GetDataFromOleHGLOBAL(String format, DVASPECT aspect, Int32 index)
at System.Windows.DataObject.OleConverter.GetDataFromBoundOleDataObject(String format, DVASPECT aspect, Int32 index)
at System.Windows.DataObject.OleConverter.GetData(String format, Boole 1448086091814
调查:
我们的TextBox实现了Behavior,其中需要对粘贴的东西进行校验, 因此注册了Paste事件
DataObject
.
AddPastingHandler
(
this
.
AssociatedObject
,
OnClipboardPaste
);
OnClipboardPaste方法中获取剪贴板内容如下
if
(
e
.
SourceDataObject
.
GetDataPresent
(
DataFormats
.
UnicodeText
,
false
))
{
text
=
e
.
SourceDataObject
.
GetData
(
DataFormats
.
UnicodeText
)
as
string
;
}
查看各种资料,有人说是SetData的类没有加[Serializable]标记, 如: http://stackoverflow.com/questions/6999142/wpf-insufficient-memory-when-doing-copy-paste-vs-drag-drop-with-view-model-dat
[SecurityCritical]
void System.Runtime.InteropServices.ComTypes.IDataObject.GetData(ref FORMATETC formatetc, out STGMEDIUM medium)
{
if (this ._innerData is DataObject.OleConverter)
{
((DataObject.OleConverter) this._innerData).OleDataObject.GetData(ref formatetc, out medium);
}
else
{
int num = -2147221399;
medium = new STGMEDIUM();
if (this .GetTymedUseable(formatetc.tymed))
{
if ((formatetc.tymed & TYMED.TYMED_HGLOBAL) != TYMED.TYMED_NULL)
{
medium.tymed = TYMED.TYMED_HGLOBAL;
medium.unionmember = DataObject.Win32GlobalAlloc(8258, (IntPtr) 1);
num = this.OleGetDataUnrestricted(ref formatetc, ref medium, false);
if (MS.Win32.NativeMethods.Failed(num))
DataObject.Win32GlobalFree( new HandleRef((object ) this, medium.unionmember));
}
else if ((formatetc.tymed & TYMED.TYMED_ISTREAM) != TYMED.TYMED_NULL)
{
if (SecurityHelper.CheckUnmanagedCodePermission())
{
medium.tymed = TYMED.TYMED_ISTREAM;
System.Runtime.InteropServices.ComTypes.IStream istream = (System.Runtime.InteropServices.ComTypes.IStream) null ;
num = DataObject.Win32CreateStreamOnHGlobal(IntPtr.Zero, true, ref istream);
if (MS.Win32.NativeMethods.Succeeded(num))
{
medium.unionmember = Marshal.GetComInterfaceForObject(( object) istream, typeof (System.Runtime.InteropServices.ComTypes.IStream));
Marshal.ReleaseComObject(( object) istream);
num = this.OleGetDataUnrestricted(ref formatetc, ref medium, false);
if (MS.Win32.NativeMethods.Failed(num))
Marshal.Release(medium.unionmember);
}
}
else
num = -2147467259;
}
else
{
medium.tymed = formatetc.tymed;
num = this.OleGetDataUnrestricted(ref formatetc, ref medium, false);
}
}
if (!MS.Win32.NativeMethods.Failed(num))
return;
medium.unionmember = IntPtr.Zero;
Marshal.ThrowExceptionForHR(num);
}
}
[SecurityCritical]
private void GetDataInner(ref FORMATETC formatetc, out STGMEDIUM medium)
{
new SecurityPermission(SecurityPermissionFlag.UnmanagedCode).Assert();
try
{
this._innerData.GetData(ref formatetc, out medium);
}
finally
{
CodeAccessPermission.RevertAssert();
}
}
[SecurityCritical]
private object GetDataFromOleHGLOBAL(string format, DVASPECT aspect, int index)
{
FORMATETC formatetc = new FORMATETC();
formatetc.cfFormat = ( short) DataFormats.GetDataFormat(format).Id;
formatetc.dwAspect = aspect;
formatetc.lindex = index;
formatetc.tymed = TYMED.TYMED_HGLOBAL;
object obj = (object ) null;
if (this .QueryGetDataInner(ref formatetc) == 0)
{
STGMEDIUM medium;
this.GetDataInner(ref formatetc, out medium);
try
{
if (medium.unionmember != IntPtr.Zero)
{
if (medium.tymed == TYMED.TYMED_HGLOBAL)
obj = this.GetDataFromHGLOBAL(format, medium.unionmember);
}
}
finally
{
MS.Win32.UnsafeNativeMethods.ReleaseStgMedium( ref medium);
}
}
return obj;
}
[SecurityCritical]
private int OleGetDataUnrestricted(ref FORMATETC formatetc, ref STGMEDIUM medium, bool doNotReallocate)
{
if (!(this ._innerData is DataObject.OleConverter))
return this .GetDataIntoOleStructs(ref formatetc, ref medium, doNotReallocate);
((DataObject.OleConverter) this._innerData).OleDataObject.GetDataHere(ref formatetc, ref medium);
return 0;
}
[SecurityCritical]
private int GetDataIntoOleStructs(ref FORMATETC formatetc, ref STGMEDIUM medium, bool doNotReallocate)
{
int num = -2147221399;
if (this .GetTymedUseable(formatetc.tymed) && this.GetTymedUseable(medium.tymed))
{
string name = DataFormats.GetDataFormat((int) formatetc.cfFormat).Name;
num = -2147221404;
if (this .GetDataPresent(name))
{
object data = this .GetData(name);
num = -2147221399;
if ((formatetc.tymed & TYMED.TYMED_HGLOBAL) != TYMED.TYMED_NULL)
num = this.GetDataIntoOleStructsByTypeMedimHGlobal(name, data, ref medium, doNotReallocate);
else if ((formatetc.tymed & TYMED.TYMED_GDI) != TYMED.TYMED_NULL)
num = this.GetDataIntoOleStructsByTypeMediumGDI(name, data, ref medium);
else if ((formatetc.tymed & TYMED.TYMED_ENHMF) != TYMED.TYMED_NULL)
num = this.GetDataIntoOleStructsByTypeMediumEnhancedMetaFile(name, data, ref medium);
else if ((formatetc.tymed & TYMED.TYMED_ISTREAM) != TYMED.TYMED_NULL)
num = this.GetDataIntoOleStructsByTypeMedimIStream(name, data, ref medium);
}
}
return num;
}
[SecurityCritical]
private int GetDataIntoOleStructsByTypeMedimHGlobal(string format, object data, ref STGMEDIUM medium, bool doNotReallocate)
{
int num;
if (data is Stream)
num = this.SaveStreamToHandle(medium.unionmember, (Stream) data, doNotReallocate);
else if (DataObject.IsFormatEqual(format, DataFormats.Html) || DataObject.IsFormatEqual(format, DataFormats.Xaml))
num = this.SaveStringToHandleAsUtf8(medium.unionmember, data.ToString(), doNotReallocate);
else if (DataObject.IsFormatEqual(format, DataFormats.Text) || DataObject.IsFormatEqual(format, DataFormats.Rtf) || (DataObject.IsFormatEqual(format, DataFormats.OemText) || DataObject.IsFormatEqual(format, DataFormats.CommaSeparatedValue)))
num = this.SaveStringToHandle(medium.unionmember, data.ToString(), false, doNotReallocate);
else if (DataObject.IsFormatEqual(format, DataFormats.UnicodeText) || DataObject.IsFormatEqual(format, DataFormats.ApplicationTrust))
num = this.SaveStringToHandle(medium.unionmember, data.ToString(), true, doNotReallocate);
else if (DataObject.IsFormatEqual(format, DataFormats.FileDrop))
num = this.SaveFileListToHandle(medium.unionmember, (string[]) data, doNotReallocate);
else if (DataObject.IsFormatEqual(format, DataFormats.FileName))
{
string[] strArray = (string []) data;
num = this.SaveStringToHandle(medium.unionmember, strArray[0], false, doNotReallocate);
}
else if (DataObject.IsFormatEqual(format, DataFormats.FileNameW))
{
string[] strArray = (string []) data;
num = this.SaveStringToHandle(medium.unionmember, strArray[0], true, doNotReallocate);
}
else
num = !DataObject.IsFormatEqual(format, DataFormats.Dib) || !SystemDrawingHelper.IsImage(data) ? (!DataObject.IsFormatEqual(format, typeof (BitmapSource).FullName) ? (!DataObject.IsFormatEqual(format, "System.Drawing.Bitmap" ) ? (DataObject.IsFormatEqual(format, DataFormats.EnhancedMetafile) || SystemDrawingHelper.IsMetafile(data) ? -2147221399 : (DataObject.IsFormatEqual(format, DataFormats.Serializable) || data is ISerializable || data != null && data.GetType().IsSerializable ? this.SaveObjectToHandle(medium.unionmember, data, doNotReallocate) : -2147221399)) : this.SaveSystemDrawingBitmapToHandle(medium.unionmember, data, doNotReallocate)) : this.SaveSystemBitmapSourceToHandle(medium.unionmember, data, doNotReallocate)) : -2147221399;
if (num == 0)
medium.tymed = TYMED.TYMED_HGLOBAL;
return num;
}
[SecurityCritical]
private int SaveStringToHandle(IntPtr handle, string str, bool unicode, bool doNotReallocate)
{
if (handle == IntPtr.Zero)
return -2147024809;
if (unicode)
{
int minimumByteCount = str.Length * 2 + 2;
int hr = this .EnsureMemoryCapacity(ref handle, minimumByteCount, doNotReallocate);
if (MS.Win32.NativeMethods.Failed(hr))
return hr;
IntPtr pdst = DataObject.Win32GlobalLock( new HandleRef((object ) this, handle));
try
{
char[] psrc = str.ToCharArray(0, str.Length);
MS.Win32.UnsafeNativeMethods.CopyMemoryW(pdst, psrc, psrc.Length * 2);
Marshal.Copy( new char [1], 0, (IntPtr) ((long) pdst + ( long) psrc.Length * 2L), 1);
}
finally
{
DataObject.Win32GlobalUnlock( new HandleRef((object ) this, handle));
}
}
else
{
int cb = str.Length <= 0 ? 0 : DataObject.Win32WideCharToMultiByte(str, str.Length, (byte[]) null, 0);
byte[] numArray = new byte[cb];
if (cb > 0)
DataObject.Win32WideCharToMultiByte(str, str.Length, numArray, numArray.Length);
int hr = this .EnsureMemoryCapacity(ref handle, cb + 1, doNotReallocate);
if (MS.Win32.NativeMethods.Failed(hr))
return hr;
IntPtr pdst = DataObject.Win32GlobalLock( new HandleRef((object ) this, handle));
try
{
MS.Win32.UnsafeNativeMethods.CopyMemory(pdst, numArray, cb);
Marshal.Copy( new byte [1], 0, (IntPtr) ((long) pdst + ( long) cb), 1);
}
finally
{
DataObject.Win32GlobalUnlock( new HandleRef((object ) this, handle));
}
}
return 0;
}
[SecurityCritical]
private int EnsureMemoryCapacity(ref IntPtr handle, int minimumByteCount, bool doNotReallocate)
{
int num = 0;
if (doNotReallocate)
{
if (MS.Win32.NativeMethods.IntPtrToInt32(DataObject.Win32GlobalSize(new HandleRef(( object) this , handle))) < minimumByteCount)
{
handle = IntPtr.Zero;
num = -2147286928;
}
}
else
{
handle = DataObject.Win32GlobalReAlloc( new HandleRef((object ) this, handle), (IntPtr) minimumByteCount, 8258);
if (handle == IntPtr.Zero)
num = -2147024882;
}
return num;
}
[SecurityCritical]
internal static IntPtr Win32GlobalReAlloc(HandleRef handle, IntPtr bytes, int flags)
{
IntPtr num = MS.Win32.UnsafeNativeMethods.GlobalReAlloc(handle, bytes, flags);
int lastWin32Error = Marshal.GetLastWin32Error();
if (num == IntPtr.Zero)
throw new Win32Exception(lastWin32Error);
return num;
}
https://msdn.microsoft.com/en-us/library/windows/desktop/aa366590(v=vs.85).aspx
https://msdn.microsoft.com/en-us/library/windows/desktop/aa366574(v=vs.85).aspx
https://msdn.microsoft.com/zh-cn/library/system.windows.dataobject(v=vs.110).aspx
http://referencesource.microsoft.com/#PresentationFramework/src/Framework/System/windows/Documents/TextEditorCopyPaste.cs,956