gpt4 book ai didi

c# - 剪贴板在 .NET 3.5 和 4 中的行为不同,但为什么呢?

转载 作者:IT王子 更新时间:2023-10-29 04:22:03 25 4
gpt4 key购买 nike

我们最近将一个非常大的项目从 .NET Framework 3.5 升级到 4,最初一切似乎都一样。但是现在错误已经开始出现在复制粘贴操作上。我设法制作了一个可重现的小型应用程序,它显示了 .NET 3.5 和 4 中的不同行为。我还找到了一个解决方法(手动将数据序列化到剪贴板),但我仍然需要知道“为什么”在行为上存在差异。

这是我制作的小型测试应用:

using System;
using System.Collections.Generic;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;
using System.Windows.Forms;

namespace ClipboardTest
{
public class Program
{
[Serializable]
public class Element
{
public Element(string name)
{
this.name = name;
}

public string name;
}

public static List<Element> TestSerializer(List<Element> obj)
{
var memoryStream = new MemoryStream();
var formatter = new BinaryFormatter();
formatter.Serialize(memoryStream, obj);
return (List<Element>)formatter.Deserialize(new MemoryStream(memoryStream.GetBuffer()));
}

public static List<Element> TestClipboard(List<Element> obj)
{
Clipboard.SetDataObject(obj);
return (List<Element>)Clipboard.GetDataObject().GetData(typeof(List<Element>));
}

public static void DumpObject(string testName, List<Element> obj)
{
if (obj == null)
{
Console.WriteLine("{0} : List is null", testName);
return;
}
foreach (var prop in obj)
{
Console.WriteLine("{0} : {1}", testName, prop.name);
}
}

[STAThread]
static void Main()
{
var copyData = new List<Element> { new Element("all good") };
DumpObject("Serializer", TestSerializer(copyData));
DumpObject("Clipboard", TestClipboard(copyData));
}
}
}

.NET 3.5 输出:
序列化程序:一切都很好
剪贴板:一切正常

.NET 4 输出:
序列化程序:一切都很好
剪贴板:列表为空

我查看了 Clipboard 和 DataObject 类的 .NET 源代码,但看不到使用了什么序列化程序。 MSDN 文档说类型必须是可序列化的,在本例中 List<> 和 Element 类都是。复制一个 Element 对象工作得很好,但一旦我复制了一个元素列表,它就会中断。

为了测试,我在 Visual Studio 2010 SP1 中创建了 2 个 C#“控制台应用程序”项目。我留下的第一个项目使用“.NET Framework 4 Client Profile”的默认“Target framework”设置。我修改为使用“.NET Framework 3.5 Client Profile”的第二个项目。

有关我的 Forms DLL 版本的其他信息:
原始文件名:System.Windows.Forms.dll
文件版本/产品版本:4.0.30319.235
语言:英语(美国)
修改日期:16-02-2012 22:50

最佳答案

我复制。您可以使用 Debug + Exceptions 更深入地了解错误,勾选 CLR 异常的 Thrown 复选框。当框架中的剪贴板代码抛出内部异常时,这将停止程序。 IDataObject.GetDataHere() 实现方法失败,出现 COM 异常,“无效的 FORMATETC 结构(HRESULT 异常:0x80040064 (DV_E_FORMATETC))”。

格式有问题。当您在 Clipboard.SetDataObject(obj) 语句之后设置断点时,这一点就变得很清楚了。并将 Clipboard.GetDataObject().GetFormats() 放在调试器监视表达式中。我明白了:

"System.Collections.Generic.List`1[[ClipboardTest.Program+Element, ConsoleApplication1, Version=1.0.0.0, Culture=neutral, Public"

请注意字符串是如何被截断的,PublicKeyToken 部分被破坏了。您可以通过更改命名空间名称和项目名称来任意更改此截断的字符串。让它们足够短,程序就不会失败。

显然这是问题的原因。字符串长度被限制为 127 个字符,任何全名超过此长度的类型都会导致此失败。这很有可能是通用类型,因为它们的名称很长。

请在 connect.microsoft.com 报告此错误。您的代码很好地演示了错误,只需在您的错误报告中发布指向它的链接就足够了。我没有很好的解决方法,确保名称足够短不是很实用。但是您可以使用这样的代码:

        // Put it on the clipboard, use a wrapper type with a short name
var envelope = new List<object>();
envelope.AddRange(obj);
Clipboard.SetDataObject(envelope);

// Retrieve from clipboard, unwrap back to original type
envelope = (List<object>)Clipboard.GetDataObject().GetData(typeof(List<object>));
var retval = new List<Element>();
retval.AddRange(envelope.Cast<Element>());
return retval;

更新:据报告此错误已在 VS2013 中修复。

关于c# - 剪贴板在 .NET 3.5 和 4 中的行为不同,但为什么呢?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9452802/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com