2012-02-26 8 views
25

हमने हाल ही में .NET फ्रेमवर्क 3.5 से 4 तक एक बहुत बड़ी परियोजना को अपग्रेड किया है, और शुरुआत में सब कुछ एक ही काम करने लग रहा था। लेकिन अब कॉपी पेस्ट ऑपरेशंस पर बग दिखने लगे हैं। मैंने एक छोटा प्रतिलिपि बनाने वाला ऐप बनाने में कामयाब रहा है, जो .NET 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 उत्पादन:
Serializer: सब अच्छा
क्लिपबोर्ड: सब अच्छा

.NET 4 उत्पादन:
Serializer : सभी अच्छे
क्लिपबोर्ड: सूची शून्य है

मैंने क्लिपबोर्ड & डेटाऑब्जेक्ट क्लास के लिए .NET स्रोत को देखा है, लेकिन मुझे नहीं पता कि सीरिएलाइज़र का उपयोग किस प्रकार किया गया था। एमएसडीएन दस्तावेज कहता है कि प्रकार क्रमबद्ध होना चाहिए, जो इस मामले में सूची <> और तत्व वर्ग दोनों हैं। एलिमेंट ऑब्जेक्ट की प्रतिलिपि बनाना ठीक है, लेकिन जैसे ही मैं तत्वों की एक सूची कॉपी करता हूं, यह टूट जाता है।

परीक्षण करने के लिए, मैंने विजुअल स्टूडियो 2010 एसपी 1 में 2 सी # "कंसोल एप्लिकेशन" परियोजनाएं बनाई हैं। ".NET Framework 4 क्लाइंट प्रोफाइल" की डिफ़ॉल्ट "लक्ष्य ढांचे" सेटिंग के साथ मैंने पहली परियोजना छोड़ी है। दूसरी परियोजना जिसे मैंने ".NET Framework 3.5 क्लाइंट प्रोफाइल" का उपयोग करने के लिए संशोधित किया है।

मेरी फार्म DLL संस्करण के बारे में अतिरिक्त जानकारी:
मूल फ़ाइल का नाम: System.Windows.Forms.dll
फ़ाइल संस्करण/prouct संस्करण: 4.0.30319.235
भाषा: अंग्रेजी (संयुक्त राज्य)
संशोधन की तिथि: 16 -02-2012 22:50

+0

मेरे लिए यह .NET 4 के साथ ठीक काम करता है ... यह दोनों मशीनों के लिए "सभी अच्छे" प्रिंट करता है –

+0

एचएम, मेरी मशीन पर, यह 3.5 के साथ ठीक काम करता है और ओपी की तरह लक्ष्य ढांचे के रूप में 4.0 सेट पर विफल रहता है राज्यों (यह क्लिपबोर्ड में एक अवैध अमान्य FORMATETC संरचना "COM अपवाद फेंकता है। GetDataObject()। GetData())। साथ ही, मुझे यहां एक समान समस्या मिली: https://connect.microsoft.com/VisualStudio/feedback/details/488627/comexception-invalid-formatetc-structure-while-pasting-marshalbyref-data-from-datagridview – Alan

+0

(VS2010 का उपयोग करना एक्सपी एसपी 3 पर एसपी 1) – Alan

उत्तर

26

मैं repro। आप डीबग + अपवादों के साथ बग में अधिक अंतर्दृष्टि प्राप्त कर सकते हैं, सीएलआर अपवादों के लिए थ्रो हुए चेकबॉक्स पर निशान लगाएं। फ्रेमवर्क में क्लिपबोर्ड कोड द्वारा एक आंतरिक अपवाद फेंकने पर यह प्रोग्राम को रोक देगा। IDataObject.GetDataHere() कार्यान्वयन विधि COM अपवाद के साथ विफल हो जाती है, "अमान्य FORMATETC संरचना (HRESULT से अपवाद: 0x80040064 (DV_E_FORMATETC))"।

प्रारूप में कुछ गड़बड़ है। जब आप Clipboard.SetDataObject (obj) कथन के बाद ब्रेकपॉइंट सेट करते हैं तो यह स्पष्ट हो जाता है। और क्लिपबोर्ड। गेटडेटा ऑब्जेक्ट()। GetFormats() को डीबगर घड़ी अभिव्यक्ति में रखें। मैं देख रहा हूँ:

"System.Collections.Generic.List`1 [[ClipboardTest.Program + तत्व, ConsoleApplication1, संस्करण = 1.0.0.0, संस्कृति = तटस्थ, सार्वजनिक"

नोट कैसे स्ट्रिंग काटा जाता है, पब्लिककेट टोकन हिस्सा उलझा हुआ है। आप नामस्थान नाम और प्रोजेक्ट नाम बदलकर मनमाने ढंग से इस कटा हुआ स्ट्रिंग को बदल सकते हैं। उन्हें काफी छोटा बनाएं और कार्यक्रम असफल नहीं होगा।

स्पष्ट रूप से यह समस्या का कारण है। स्ट्रिंग लम्बाई 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 में ठीक किया गया।

+0

आह .. अब यह और अधिक समझ में आता है। और यह भी बताता है कि क्यों मेरे मैन्युअल क्रमबद्धता काम करता है। बहुत बहुत धन्यवाद। – bitmonk8

+0

कनेक्ट पर दायर: https://connect.microsoft.com/VisualStudio/feedback/details/726652/clipboard-truncates-type-name-to-127-characters –

+0

हूप्स .. ऐसा लगता है कि हम दो बार दायर किए गए हैं। https://connect.microsoft.com/VisualStudio/feedback/details/726654/clipboard-has- अलग-undocumented-behavior-in-net-3-5-and-4 – bitmonk8

संबंधित मुद्दे