Suche Datei auch in Unterordner



  • Ich möchte gerne eine Datei auf meinem Rechner suchen, ohne das ich den Pfad kenne und angeben kann. Habe folgenden Quellcode:

    CStringArray &Find(CString strDir, CStringArray &strFiles)
    {
        CFileFind search;
        CString strWildcard
        strWildcard = (strDir + "\\*.*");
    
        BOOL bWorking = search.FindFile(strWildcard);
    
        while (bWorking)
        {
            bWorking = search.FindNExtFile();
    
            if (search.IsDirectory())
            {
                return Find(search.GetFilePath(), strFiles);
            }
            else
                strFiles.Add(search.GetFilePath());
        }
        search.Close();
        return strFiles;
    }
    
    void CDateiSuchenDlg::OnTest()
    {
        CStringArray strFiles;
    
        Find("C:\\", strFiles);
    
        for(unsigned int i = 0; i < strFiles.GetSize(); i++)
            MessageBox(strFiles.GetAt(i), "Found", MB_ICONINFORMATION);
    }
    

    Hier wird aber nicht noch in den Unterverzeichnissen gesucht. Ich möchte einfach ein Code der selbständig nach der Datei "cintools" sucht, egal wo dieser Ordner liegt. Wie kann ich meinen Code dahingehend anpassen?

    Danke



  • Hab auch schonmal danach gesucht und nichts gefunden. Hab dann mit IsDirectory() auf Unterverzeichnisse geprüft und die Funktion dann rekursiv laufen lassen.



  • Ok, und wie würde das in meinem Fall aussehen? Danke 👍



  • Meiner Meinung nach müsste das schon klappen.
    Die if ist in Zeile 13 und der rekursive Aufruf in Zeile 15. 😕

    Hast du das schon mal debugged?



  • CStringArray &Find(CString strDir, /*new*/CString strName, CStringArray &strFiles)
    {
        CFileFind search;
        CString strWildcard
        strWildcard = (strDir + "\\*.*");
    
        BOOL bWorking = search.FindFile(strWildcard);
    
        while (bWorking)
        {
            bWorking = search.FindNextFile();
    
            if (search.IsDirectory())
            {
                return Find(search.GetFilePath(), strFiles);
            }
            else
    /*new*/     if(search.GetFileTitle()==strName)
                    strFiles.Add(search.GetFilePath());
        }
        search.Close();
        return strFiles;
    }
    
    void CDateiSuchenDlg::OnTest()
    {
        CStringArray strFiles;
    
        Find("C:\\",/*new*/ "cintools", strFiles);
    
        for(unsigned int i = 0; i < strFiles.GetSize(); i++)
            MessageBox(strFiles.GetAt(i), "Found", MB_ICONINFORMATION);
    }
    

    (eventuell mußt du den Vergleich dort oben noch an deine Bedürfnisse anpassen, aber das Prinzip sollte klar sein)



  • Vielen Dank für eure schnelle Hilfe. Der Compiler meldet alles in Ordnung. Bei der Ausführung bekomme ich nun eine Unbehandelte Ausnahme:

    (NTDLL.DLL): 0xC0000005: Access Violation.
    


  • Kannst du vielleicht einschränken, wo genau diese Exception fliegt (klick auf "Wiederholen" und schau dir an, was der Debugger ausspuckt).



  • Ich kann nicht Wiederholen klicken. Aber er springt mit dem Debugger hierhin:

    7C91D4E8  call        dword ptr [edx]
    


  • Setz mal an strategischen Stellen Breakpoints und taste dich an die Zeile ran. 🙂



  • Ich würde eventuell CreateProcess() verwenden... Shellexecute ist da meines Wissens nach nicht die beste Lösung. Shellexecute ist eher was, um BIlder mit dem Standard-Bildbetrachter zu öffnen, oder txt-Files mit dem Standart-Texteditor..



  • Ich habe gemerkt das nach dem dritten Funktionsaufruf die strWildcard Variable folgenden Inahlt hat:

    C:\Dokumente und Einstellungen\.\*.*
    

    Danach kommt irgendwann ein Stack Overflow



  • Du musst die Verzeichnisse . und .. ignorieren!
    http://www.c-plusplus.net/forum/viewtopic-var-t-is-39130.html



  • Hmm, das könnte ein Problem sein - das mußt du abfangen, indem du vor/in der isDirectory()-Überprüfung abbrichst, wenn die gefundene Datei "." (eigenes Verzeichnis) oder ".." (Vater-Verzeichnis) heißt:

    while (bWorking)
    {
      bWorking = search.FindNextFile();
    
      if (search.IsDirectory())
      {
        if(search.GetFileName()=="." || search.GetFileName=="..") continue;
        /*return*/ Find(search.GetFilePath(), strFiles);
      }
      else
         if(search.GetFileTitle()==strName) strFiles.Add(search.GetFilePath());
    }
    


  • Falls es jemanden interessiert: CFileFind::IsDots
    (Ist mir mal in dem Zusammenhang über den Weg gelaufen...)



  • estartu schrieb:

    Du musst die Verzeichnisse . und .. ignorieren!
    http://www.c-plusplus.net/forum/viewtopic-var-t-is-39130.html

    isabeau schrieb:

    Falls es jemanden interessiert: CFileFind::IsDots
    (Ist mir mal in dem Zusammenhang über den Weg gelaufen...)

    Vielen Dank, genau das wars. Mit

    if (search.IsDots()) 
        continue;
    

    vor der IsDirectory Abfrage funktionierts einwandfrei.

    Danke für die schnelle Hilfe! 👍



  • Eins wäre noch toll. Er sucht weiter, auch wenn er die Datei schon gefunden hat. Wäre nett wenn er abbrechen würde sobald er die Datei gefunden hat.



  • Ja, die jetzige Variante sucht nach allen Vorkommen der Datei auf deiner Platte und packt sie in dein StrinArray. Wenn du nur das erste Vorkommen finden willst, mußt du beim ersten Treffer mit der Suche abbbrechen (und bei jedem rekursiven Aufruf auswerten, ob auf diesem Weg etwas gefunden wurde).



  • Ist es definitiv nur EINE Datei? Dann mach doch ein return unter Zeile wo du den Dateinamen speicherst.

    Außerdem würde es dann reichen, einen CString zurückzugeben. 😉



  • estartu schrieb:

    Ist es definitiv nur EINE Datei? Dann mach doch ein return unter Zeile wo du den Dateinamen speicherst.

    Außerdem würde es dann reichen, einen CString zurückzugeben. 😉

    Ja, es kann nur eine Datei sein. Und diese existiert nur wenn man LabView installiert hat. Ich bekomme es mit dem Abbrechen der Suche nicht wirklich hin. Wenn ich es so mache:

    if(search.GetFileTitle() == strName)
    {
        strFiles.Add(search.GetFilePath());
    /*new*/    return strFiles;
    }
    

    wird nicht nach dem ersten Treffer beendet. 😕



  • Du mußt auch komplett alle rekursiven Aufrufe abbrechen, wenn von oben "gefunden" zurückkam, sonst wird im nächsten Ordner weitergesucht:

    BOOL Find(CString strDir, CString strName, CString &strFullPath)
    {
        CFileFind search;
        CString strWildcard
        strWildcard = (strDir + "\\*.*");
    
        BOOL bWorking = search.FindFile(strWildcard);
    
        while (bWorking)
        {
            bWorking = search.FindNExtFile();
    
            if(search.IsDots())continue;
            if (search.IsDirectory())
            {
                if(Find(Find(search.GetFilePath(),strName,strFullPath)) return TRUE;
            }
            else if(search.GetFileTitle()==strName)
            {
                strFullPath=GetFilePath());
                return TRUE;
            }
        }
        search.Close();
        return FALSE;
    }
    

Anmelden zum Antworten