2010-07-08 19 views
5

अब .NET CLR 4.0 साइड बाय साइड (एसएक्सएस) ऑपरेशन का समर्थन करता है, अब प्रबंधित कोड में खोल एक्सटेंशन लिखना संभव होना चाहिए। मैंने इसका प्रयास किया है और एक संपत्ति हैंडलर सफलतापूर्वक कोड किया है जो आईप्रॉपर्टीस्टोर, IInitializeWithStream और IPropertyStoreCapabilities लागू करता है।प्रबंधित संपत्ति हैंडलर शैल एक्सटेंशन को लागू करने का सही तरीका क्या है?

हैंडलर ठीक काम करता है और एक्सप्लोरर के माध्यम से फ़ाइलों को ब्राउज़ करते समय अपेक्षित कहा जाता है। यह पूर्वावलोकन पैनल में कस्टम गुणों और फ़ाइल गुणों "विवरण" पैनल को प्रदर्शित करने में भी ठीक काम करता है।

हालांकि, जब मैं को पूर्वावलोकन पैनल में एक संपत्ति संपादित करने का प्रयास करता हूं, और उसके बाद "सहेजें" पर क्लिक करें, तो मुझे "फ़ाइल उपयोग में" त्रुटि मिलती है, यह कहते हुए कि फ़ाइल Windows Explorer में खुलती है।

कुछ छोटी-मोटी बातें:

  1. जब एक्सप्लोरर कॉल IInitializeWithStream.Initialize STGM संपत्ति STGM_SHARE_DENY_WRITE को तैयार है।
  2. और किसी भी समय एक्सप्लोरर को IPropertyStore.SetValue या IPropertyStore.Commit कॉल नहीं किया गया।
  3. मुझे एक ही फ़ाइल गुणों के लिए अलग-अलग धागे पर मेरे हैंडलर को दोहराया गया कॉल दिखाई देता है।

तो संपत्ति को काम करने के लिए मुझे क्या बदलने की आवश्यकता है (या रजिस्टर में सेट)?

अद्यतन:

बेन के लिए धन्यवाद मैं काम कर रहा यह मिल गया है। "कठिन हिस्सा" (कम से कम मेरे लिए) यह समझ रहा था कि COM इंटरऑप कभी भी मेरे प्रॉपर्टी हैंडलर पर निपटान या अंतिम रूप देने को कॉल नहीं करेगा। यह उन फ़ाइलों को छोड़ रहा था जिन्हें मैंने जीसी चलाने तक संसाधित किया था।

सौभाग्य से, "प्रॉपर्टी हैंडलर प्रोटोकॉल" इस तरह काम करता है कि जब IInitializeWithSream.Initialize() को ReadValue() के लिए बुलाया जाता है तो स्ट्रीममोड केवल पढ़ने के लिए कहा जाता है, और जब इसे SetValue() के लिए कहा जाता है तो स्ट्रीममोड ReadWrite और Commit () अंत में बुलाया जाएगा।

int IInitializeWithStream.Initialize(IStream stream, uint grfMode) 
{ 
    _stream = stream; 
    _streamMode = (Stgm)grfMode; 

    Load(); 

    // We release here cause if this is a read operation we won't get called back, 
    // and our finializer isn't called. 
    if ((_streamMode & Stgm.ReadWrite) != Stgm.ReadWrite) 
    { 
     Marshal.ReleaseComObject(_stream); 
     _stream = null; 
    } 
    return HResult.S_OK; 
} 

int IPropertyStore.Commit() 
{ 
    bool result = false; 

    if (_stream != null) 
    { 
     result = WriteStream(_stream); 
     Marshal.ReleaseComObject(_stream); 
     _stream = null; 
    } 

    return result ? HResult.S_OK : HResult.E_FAIL; 
} 

उत्तर

3

हाँ, आप इसे खुला रखने के लिए और संदर्भ जिंदा सही ढंग से रखने के लिए AddRef() धारा के लिए है।

ध्यान दें कि सूचकांक फ़ाइल को खोलने के लिए आपके प्रॉपर्टी हैंडलर का भी उपयोग करेगा। तो यदि आप स्ट्रीम ऑब्जेक्ट को रिसाव करते हैं, तो फ़ाइल खुली रहेगी। आप sysinternals procexp का उपयोग यह बताने के लिए कर सकते हैं कि फ़ाइल किस प्रक्रिया में खुलती है, या यह बताए कि कौन से कॉल और पैरामीटर इसका इस्तेमाल करते हैं।

1

एक्सप्लोरर सुनिश्चित करने के लिए है कि यह अन्य अनुप्रयोगों है कि फ़ाइल खुला हो सकता है के साथ हस्तक्षेप नहीं करता है की कोशिश करता है। क्या फ़ाइल किसी अन्य एप्लिकेशन द्वारा वैध रूप से उपयोग में लाई जा सकती है? क्या कोई पूर्वावलोकन हैंडलर खुला है?

कभी-कभी, हम संपत्ति हैंडलर देखते हैं जो अपनी स्ट्रीम को आवश्यक से अधिक लंबे समय तक खोलते हैं (या फ़ाइल-आधारित हैंडलर जो फ़ाइल को प्रतिबंधित अनुमतियों के साथ खोलते हैं)। क्या आप सत्यापित कर सकते हैं कि क्या आप समय पर स्ट्रीम जारी कर रहे हैं?

अंत में, मुझे नहीं लगता कि यह आपकी तत्काल समस्या से संबंधित है, लेकिन .NET खोल एक्सटेंशन का उपयोग असमर्थित है। हम अनुशंसा करते हैं कि इसे किसी भी उत्पाद में शामिल न किया जाए।

बेन

+0

कोई पूर्वावलोकन हैंडलर नहीं है, लेकिन Windows खोज सेवा कभी कभी हैंडलर लोड करने के लिए लगता है। लेकिन यह फ़ाइल को लॉक नहीं करना चाहिए? इसके अलावा, मैं IInitializeWithFile का उपयोग करने के लिए स्विच करके संपादन कार्य कर सकता हूं, और मेरे SaveValue() और Commit() को अपेक्षित के रूप में कॉल किया जा सकता है। वैसे भी, यहां तक ​​कि जब मैं IInitializeWithStream बाहर ठूंठ इतना है कि यह कभी नहीं धारा का उपयोग करता है (और getValue() वापसी डिफ़ॉल्ट खाली मान हैं) यह अभी भी जब एक संपत्ति संपादन एक ही त्रुटि देता है। एक्सप्लोरर कभी भी SaveValue() या Commit() को कॉल नहीं करता है। –

+0

क्या मुझे Addref() ISTream की आवश्यकता है जिसे मैं प्रारंभ() में प्राप्त करता हूं? और फिर Commit() के बाद इसे रिलीज़()? मैंने माना था कि मैंने नहीं किया था। आपके आखिरी मुद्दे के अनुसार मैंने सोचा कि पक्ष में साइड मोड में .NET 4.0 का उपयोग करके सीएलआर संस्करण को हल एक्सटेंशन के साथ हल किया गया है। मैंने सत्यापित किया है कि सही सीएलआर मेरा कोड चला रहा है। –