ReadDirectoryChangesW



  • hallo

    ich habe einen windowsdienst geschrieben (begonnen zu schreiben...) welcher ein bestimmtes
    verzeichnis und dessen unterverzeichnis auf erstellen von dateien überwachen soll um dann aktionen mit diesen auszuführen(kopieren).

    der dienst ist allerdings noch nicht fertig; im moment gibt er nur eine meldung
    in der ereignisanzeige aus, ob eine datei erstellt worden ist. das funktioniert
    soweit auch gut, nur, dass sobald ich die routine ReadDirectoryChangesW(...) aufrufe,
    der dienst beim stop über die dienstkonsole die meldung "...konnte nicht beendet werden ...." + "... der dienst hat keinen fehler zurrückgegeben..." erscheint. wenn ich die routine ReadDirectoryChangesW(...) auskommentiere, dann funktioniert es wieder wunderbar.

    hier der qtext;
    methode einer eigenen klasse, welche mir - wenn sie fertig ist - den pfad\dateinamen der neu erstellten datei zurrückgeben soll:

    AnsiString __fastcall TFunct::watchDir()
     {
    
    	AnsiString *trFile;
    	trFile = new AnsiString;
    
    	FILE_NOTIFY_INFORMATION *inf;
    	inf = new FILE_NOTIFY_INFORMATION;
    
    	DWORD bufLen = pow(2,16);
    	void *pBuf = AllocMem(bufLen);
    	unsigned long *dwRead;
    
    	char *c;
    	c = new char[(*INPATH).Length() + 1];
    	strcpy(c, (*INPATH).c_str());
    
    	HANDLE hNotify = FindFirstChangeNotification(c, true, FILE_NOTIFY_CHANGE_FILE_NAME);
    
    	if (hNotify == INVALID_HANDLE_VALUE) {
    		*trFile = "noHandle";
    	}
    	else {
    
    		if((ReadDirectoryChangesW(hNotify, pBuf, bufLen, true, FILE_NOTIFY_CHANGE_FILE_NAME, dwRead, NULL, NULL)) != 0) {
    
    			//inf = ((FILE_NOTIFY_INFORMATION*) (*inf).FileName); 
    
    			*trFile = "OP";
    
    			}
    			else {
    				*trFile = GetLastError();
    			}
        }
    
    	CloseHandle(hNotify);
    
    	return *trFile;
     }
    

    und der aufruf via ServiceExecute:

    void __fastcall TEFofmngr::ServiceExecute(TService *Sender)
    {
    	if ((!DirectoryExists(PATH2CFG)) || (!FileExists(CFG))) {
    
    		LogMessage("cfg not found!(checkPath and cfg)", EVENTLOG_ERROR_TYPE, 999, 4);
    
    	}
    	else {
    
    		(*f1).pathConfig("C:\\Program Files\\Filemgr\\manCfg.cfg");
    
    		//check if sPath and dPath is available
    		if (DirectoryExists((*f1).getInPath()) && DirectoryExists((*f1).getOutPath())) {
    
    			(*f1).setGo(true);
    			LogMessage("inPath: "+(*f1).getInPath()+"\\\~", EVENTLOG_SUCCESS, 999, 1);
    			LogMessage("outPath: "+(*f1).getOutPath()+"\\\~", EVENTLOG_SUCCESS, 999, 1);
    
    		}
    		else {
    			(*f1).setGo(false);
    			LogMessage((*f1).getInPath()+" or "+ (*f1).getOutPath()+" not found!", EVENTLOG_ERROR_TYPE, 999, 4);
    		}
    
    		//----
    		if ((*f1).getGo()) {
    
    			//-------------------------------------
    
    			while ((*f1).getGo()) {
    
    				LogMessage((*f1).watchDir(), EVENTLOG_SUCCESS, 999, 1);
    				(*ServiceThread).ProcessRequests(false);
    
    			}
    			//------------------------------------
    
    		}
    		else {
    			bool b	=  (*f1).getGo();
                ServiceStop(Sender, b);
    		}
    	}
     }
    

    in der service stop routine steht:

    void __fastcall TEFofmngr::ServiceStop(TService *Sender, bool &Stopped)
    {
    
    	LogMessage("FileManager Stopped", EVENTLOG_INFORMATION_TYPE, 999, 2);
    
    	(*f1).setGo(false);
    
    	ErrCode = 0;
    	Win32ErrCode = 0;
    	Stopped = true;
    
    	(*f1).~TFunct();
    }
    

    die meldung "FileManager Stopped" wird allerdings nie ausgegeben, sobald ich ReadDirectoryChangesW einbinde!

    mein system ist vista 64, codegear c++ 2009 als ide.

    nach ner menge googlerei, welche mir noch nicht die lösung "brachte"
    meine frage nun an euch: kann mir jemand sagen, was ich falsch mache?

    danke für jede hilfe
    peter



  • Du solltest dir nochmal die Doku anschauen. ReadDirectoryChangesW blockiert, die Funktion kehrt also erst zurück, wenn eine Änderung gemeldet wird.

    Abgesehen davon stimmt das sowieso alles nicht so ganz. Ich kenne es so, dass man entweder FindFirst/NextChangeNotification nutzt oder aber ReadDirectoryChangesW, aber nicht beides vermischt.

    Mit FindFirst/NextChangeNotification bekommst du afair nur mit, dass etwas geändert wurde, aber nicht den entsprechenden Pfad. Dafür kannst du bequem mit mit den WaitFor.. -Funktionen darauf warten bzw den Status checken. Das Handle von FindFirstChangeNotification schließt man übrigens mit FindCloseChangeNotification .
    Wenn du ReadDirectoryChanges nutzt, solltest du sie asynchron einsetzen, da du ja regelmäßig deine ProcessRequests -Funktion aufrufen willst.

    Zusätzlich zu Doku und Beispielen in der MSDN gibt's sicherlich auch bei CodeProject ein oder zwei Beispielprogramme.



  • hallo

    ertmal danke für die antwort;
    das "der wurm" drinnen ist hab ich mir schon gedacht, ist das erste mal, dass
    ich mich mit winapi beschäftige.

    frage:
    wie soll ich sonst zum handle auf die (in diesem fall) neu erstellte datei
    kommen, wenn nicht über FindFirstChangeNotification ?
    wie muss ich die WaitFor.. -Funktionen einsetzen?
    (ich vermute, es handelt sich dabei um waitforsingleobject )
    kann ich die anstatt ReadDirectoryChangesW verwenden?

    kannst du mir ein konkretes beispiel nennen?

    sorry für meine <unwissenheit>, aber ich such enur (noch) den faden für den richtigen
    anfang.

    peter


  • Mod

    Hast Du mal in der MSDN die Doku gelesen zu FindFirstChangeNotification?
    http://msdn.microsoft.com/en-us/library/aa364417(VS.85).aspx

    Dort findest Du unten einen Verweis auf ein Sample:
    http://msdn.microsoft.com/en-us/library/aa365261(VS.85).aspx

    Dort werden Deine Fragen beantwortet, oder?



  • oh klar - vor allem der 2. link
    thanx!!!
    peter


Anmelden zum Antworten