2012-12-26 12 views
16

मुझे यह समझाया गया ReadDirectoryChangesW समारोह तो मैं प्रभावी रूप से कई निर्देशिका में सामग्री के परिवर्तन के बारे में सूचित किया जा सकता है (ओवरराइट फ़ाइलें हट फ़ाइलें, नाम, आदि ..) का प्रयास करें।सी ++ WINAPI: ReadDirectoryChangesW() डबल सूचनाएं प्राप्त करना

मेरी हाल ही में टिप्पणियों में से एक, हर फ़ाइल लिखने आपरेशन के लिए, मैं हमेशा प्राप्त होने वाले एकल फाइल के लिए दो सूचनाएं है।

मैंने उस बहुत सावधानी से पता लगाया, और मुझे यकीन है कि अगर मैं एक फ़ाइल को ओवरराइट करता हूं (एक नई सामग्री के साथ एक .txt फ़ाइल कहें - मूल रूप से अतिरिक्त अक्षरों के अंदर जोड़े), ReadDirectoryChangesW() मुझे उस फ़ाइल को बचाने के लिए दो बार सूचित करता है।

यह गंभीर बात है, क्योंकि मुझे प्रति परिवर्तन केवल एक बार अधिसूचित होने की उम्मीद है। मैं अनजाने में ऑपरेशन दोहराना नहीं चाहता हूं जो मेरे आवेदन में केवल एक बार होनी चाहिए।

क्या यह व्यवहार ज्ञात है? क्या प्राप्त करने का कोई तरीका है प्रति एक सूचना, कृपया? क्या प्रभावी ढंग से डबल सूचनाओं से बचने का कोई तरीका है?

मैं का उपयोग करें:

  • अप्रबंधित सी ++
  • Visual Studio 2012
  • विंडोज 7 64

मैं बहुत बुनियादी कोड का उपयोग अपने परीक्षण करने के लिए है, लेकिन आप देखना चाहते हैं जाएगा यह, तो यहां यह है:

HANDLE hDir = CreateFile(
    lpDir, 
    FILE_LIST_DIRECTORY, 
    FILE_SHARE_WRITE | FILE_SHARE_READ | FILE_SHARE_DELETE, 
    NULL, 
    OPEN_EXISTING, 
    FILE_FLAG_BACKUP_SEMANTICS, 
    NULL); 

    int nCounter = 0; 
    FILE_NOTIFY_INFORMATION strFileNotifyInfo[1024]; 
    DWORD dwBytesReturned = 0; 

    while(TRUE) 
    { 
     if(ReadDirectoryChangesW (hDir, (LPVOID)&strFileNotifyInfo, sizeof(strFileNotifyInfo), FALSE, FILE_NOTIFY_CHANGE_LAST_WRITE, &dwBytesReturned, NULL, NULL) == 0) 
     { 
      ErrorCheck(_T("Reading Directory Change")); 
     } 
     else 
     { 
      _tcout << _T("File Modified: ") << strFileNotifyInfo[0].FileName << endl; 
      _tcout << _T("Loop: ") << nCounter++ << endl; 
     } 
    } 
+0

सबसे पहले आप प्रत्येक लेखन ऑपरेशन कहते हैं, लेकिन फिर आपका उदाहरण ओवरराइट हो गया है। मैं अनुमान लगाता हूं कि ओवरराइटिंग में किसी मौजूदा फ़ाइल को लिखने/जोड़ने के विरोध में निर्देशिका के परिप्रेक्ष्य (जैसे कि डिलीट करें) से एक ही ऑपरेशन शामिल हो सकता है। लेकिन मेरे पास इस पर कोई आधिकारिक संदर्भ नहीं है ... – TheUndeadFish

+0

[फाइलसिस्टमवॉचर डबल प्रविष्टियों] के संभावित डुप्लिकेट (http://stackoverflow.com/questions/9902758/filesystemwatcher- डबल-entries) –

+0

@TheUndeadFish, हाय और धन्यवाद आपके विचार के लिए। यह वास्तव में बहुत चालाक है। मैंने अपने परीक्षणों को एक और झंडे के साथ करने की कोशिश की। मैं कह सकता हूं, उदाहरण के लिए ** FILE_NOTIFY_CHANGE_ATTRIBUTES ** दो सूचनाएं भी देता है। यह समझाया जा सकता है कि फ़ाइल ओवरराइट पर, एक से अधिक विशेषता सामान्य रूप से बदल जाती है? –

उत्तर

18

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

तो आप फ़ाइल डेटा के लिए लिखते हैं। लेकिन आप भी इसे निर्देशिका प्रविष्टि को बदलते देखते हैं। विशेष रूप से फ़ाइल आकार में, जब आप फ़ाइल लिखते हैं और फ़ाइल में डेटा जोड़ते हैं तो बदल सकते हैं। और निर्देशिका प्रविष्टि में दर्ज अंतिम लेखन और अंतिम-पहुंच टाइमस्टैम्प। एपीआई अन्यथा बदलाव के प्रकार के लिए अंधेरा है, यह केवल निम्न स्तर के लेखन को देखता है। यह भी पूरी तरह से अनजान है कि लेखन के लिए किस विशेष प्रक्रिया से पूछा गया है।

यह कुछ ऐसा है जो आपको सौदा करना होगा, इन लेखनों को अलग करने का कोई तरीका नहीं है। जो कुछ आप जानते हैं वह है "फाइल बदल दी गई थी"। कैसे, क्यों, किसके द्वारा और कितनी बार पूरी तरह से अनदेखा है।

कुछ और आपको इससे निपटना होगा कि, जब अधिसूचना उत्पन्न होती है, तो फाइल लिखने वाली प्रक्रिया में अभी भी फ़ाइल पर लॉक होने की संभावना है। जो आपको फ़ाइल के साथ कुछ भी उपयोगी करने से रोकता है। फ़ाइल पढ़ने या कॉपी करने की तरह यह असफल होने की संभावना है। आपको फ़ाइल के साथ प्रक्रिया पूरी होने तक पर प्रतीक्षा करें और फ़ाइल को अपना हैंडल बंद कर दिया है। फ़ाइल को स्वयं खोलने और किसी भी साझाकरण से इनकार करने की कोशिश करने के अलावा, इसे खोजने का कोई तरीका नहीं है। इसके लिए एक टाइमर की आवश्यकता होती है, जो समय-समय पर फ़ाइल पर लॉक प्राप्त करने का प्रयास करती है। एक बार जब आप उस नलसाजी को जगह ले लेंगे, तो फ़ाइल के लिए एक से अधिक परिवर्तन अधिसूचना प्राप्त करने से कोई फर्क नहीं पड़ता।

+2

+1 और आपके उत्तर के लिए धन्यवाद। आपने समाधान के लिए प्रस्तावित विचार के साथ, बहुत अच्छे तरीके से समझाया। मैं टाइमर आधारित निगरानी लागू करेगा। आपका और सर्गमत के जवाब दोनों बहुत अच्छे हैं। यह तय करना मुश्किल है कि कौन से * स्वीकृत उत्तर * के रूप में चिह्नित किया जाए, लेकिन, जैसा कि आप अतिरिक्त जानकारी प्रदान करते हैं, मैं आपका उत्तर चिह्नित कर रहा हूं। एक बार फिर धन्यवाद। –

6

यह नोटपैड में फ़ाइल सहेजने के बाद प्रोमोमन लॉगिंग के साथ-साथ चल रहे कोड का परिणाम ऑपरेशन है। ReadDirectoryChangesW() से दो अधिसूचनाएं हैं और दो प्रोमोमन से अधिसूचित हैं। 2 IRP_MJ_WRITE 1 नोटपैड (WriteFile) 1 से सिस्टम कैश प्रबंधक (CcWriteBehind) procmon

+0

यह उचित लगता है लेकिन मुझे यकीन नहीं है ... http://msdn.microsoft.com/en-us/library/windows/desktop/aa365465(v=vs.85).aspx पर 'FILE_NOTIFY_CHANGE_LAST_WRITE' के लिए दस्तावेज़ कहता है "देखे गए निर्देशिका या उपट्री में फ़ाइलों के आखिरी लेखन-समय में कोई भी परिवर्तन एक परिवर्तन अधिसूचना प्रतीक्षा ऑपरेशन को वापस करने का कारण बनता है। * ऑपरेटिंग सिस्टम डिस्क पर लिखे जाने पर केवल अंतिम लेखन समय में परिवर्तन का पता लगाता है * ऑपरेटिंग सिस्टम के लिए जो व्यापक कैशिंग का उपयोग करते हैं, पहचान तब होती है जब कैश पर्याप्त रूप से फ़्लश हो जाता है। " –

+0

@sergmat: +1 हेलो और आपकी व्याख्या के लिए धन्यवाद। आपका विश्लेषण महान है और पूरी तरह से इस मुद्दे को समझाता है। मुझे खेद है, मैं अपने आप को जवाब नहीं ढूंढ पाया। ऐसा लगता है कि Sysinternals.com से प्रक्रिया मॉनिटर बहुत शक्तिशाली उपकरण है। –

+0

@NikBougalis, हाय निक, हाँ, मैंने प्रलेखन से अनुच्छेद पढ़ा है। ऐसा लगता है कि सर्गामत ने समझाया कि, और मुझे समय-समय पर आधारित सभी अधिसूचनाओं की निगरानी करनी होगी, इसलिए मैं उन युगल से बचूंगा। –

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