Problem mit FindFirst und FindNext ...



  • Ich habe folgendenden Code in meiner Funktion ....

    bool __fastcall TFrmMain::SearchLanguages()
    {
        AnsiString SearchDir;
        AnsiString Temp;
        AnsiString Langname;
    
        int LangCount=0;
        SearchDir = GetAppDir() + "lang\\*.*";
    
        ClearTempLangDB();
    
        WIN32_FIND_DATA fd;
        HANDLE hFind=FindFirstFile(SearchDir.c_str(),&fd);
        if(hFind!=INVALID_HANDLE_VALUE)
        {
            ShowMessage(Format("Suche in %s", ARRAYOFCONST((SearchDir))));
            if(!DirectoryExists(ExtractFilePath(SearchDir)))
            {
                ShowMessage("Suchpfad scheint nicht zu existieren !!!");
                return false;
            }
    
            do
            {
                //ShowMessage("Suche nach Sprachendateien");
                if(fd.dwFileAttributes==FILE_ATTRIBUTE_DIRECTORY)
                {
                    if((strcmp(fd.cFileName,"."))!=NULL && (strcmp(fd.cFileName,".."))!=NULL)
                    {
                        Temp = GetAppDir()+"lang\\"+fd.cFileName+"\\language.ini";
                        if(FileExists(Temp))
                        {
    
                            ShowMessage(Format("Sprache %s gefunden", ARRAYOFCONST((fd.cFileName))));
                            Langname = AddLanguagesToMenu(Temp,LangCount+1);
                            if(!Langname.IsEmpty())
                            {
                                ShowMessage(Format("Sprache %s, %s wird gespeichert", ARRAYOFCONST((fd.cFileName, Langname))));
                                AddLanguageToTempDB(fd.cFileName,Langname);
                                LangCount++;
                            }
                        }
                        else
                            ShowMessage(Format("Sprache in %s nicht gefunden", ARRAYOFCONST((Temp))));
                    }
                }
            }
            while(FindNextFile(hFind,&fd));
            FindClose(hFind);
        }
        if(LangCount > 0)
            ShowMessage("Anzahl gefundener Sprachen : " + IntToStr(LangCount));
        else
            ShowMessage("Keine Sprachen gefunden");
    
        return (LangCount>0) ? true:false;
    }
    

    Bei mir auf dem Rechner Funktioniert alles einwandfrei (Win XP SP1).
    Kurz zur Erklärung was passieren soll.
    Diese Funktion soll im Unterverzeichnis "Lang" nach weiteren Unterverzeichnissen suchen und innerhalb dieser nach einer Datei mit dem Namen language.ini.

    Wird diese Datei gefunden wird in einer weiteren Funktion der Name der Sprache in einem Menü angehängt. Das ganze soll dazu dienen das vom Benutzer selbstangelegte Übersetzungen vom Programm ohne Aufwand gefunden und angezeigt werden.

    Nun zum Problem. Ich habe meine kleine Programm von mehreren Leuten testen lassen. Und in diser Funktion gabs Probs. Wie man sieht habe ich einige ShowMessage() aufrufe drinne um zu schauen wo denn nun Fehler auftretten. Diese gehören natürlich eigentlich nicht dazu. Also 2 von 3 Leuten haben in dieser Funktion das Problem das die FindForst / FindNext aufrufe nicht korrekt funktionieren. Ich habe das SP2 in Verdacht. Allerdings hat die 3. Person ebenfalls SP2 drauf.

    Bei den Leuten wo es nicht Funktioniert kommt am Ende der Funktion die Meldung "keine Sprache gefunden". Am nicht existierenden Pfad kann es nicht liegen, denn dann sollte ja die Meldung "Suchpfad scheint nicht zu existieren" gleich zu begin erscheinen, diese ist aber nicht der Fall.

    Wäre dankbar für jeden Tip warum es mal funzt und mal nicht.

    Fox



  • Bei den Leuten wo es nicht Funktioniert kommt am Ende der Funktion die Meldung "keine Sprache gefunden". Am nicht existierenden Pfad kann es nicht liegen, denn dann sollte ja die Meldung "Suchpfad scheint nicht zu existieren" gleich zu begin erscheinen, diese ist aber nicht der Fall.

    Kann ja auch nicht, da du erst u.U. mit einem "illegalen" Pfad suchen lässt

    HANDLE hFind=FindFirstFile(SearchDir.c_str(),&fd);

    und dann ggf. ein Null-Handle bekommst und erst nach dem der Pfad exisitiert, du also KEIN Null-Handle bekommen hast, prüfst ob das Verzeichnis existiert.

    if(!DirectoryExists(ExtractFilePath(SearchDir)))



  • Eigentlich muss dieser Pfad immer existieren. Denn das Verzeichnis wird vom Programm nirgends selber angelegt. Somit wäre dies ausgeschlossen. Allerdings hast Du recht ich bekomme u.U. zuerst ein Null Handle und prüfe erst dann ob der Pfad existiert, werde das ändern.

    Fox



  • Vielleicht noch ein Hinweis auf die VCL Funktionen

    FindFirst,FindNext,FindClose,SearchRec



  • So, erstmal danke für deine Tipps. Ich habe diese befolgt und meine Funktion jetzt so verändert.
    1. Prüfen ob Pfad besteht vorher
    2. VCL Funktionen benutzt

    bool __fastcall TFrmMain::SearchLanguages()
    {
        AnsiString SearchDir;
        AnsiString Temp;
        AnsiString Langname;
    
        int LangCount=0;
        SearchDir = GetAppDir() + "lang\\*.*";
    
        ClearTempLangDB();
        TSearchRec sr;
        int iAttributes = 0;
    
        iAttributes |= faDirectory;
    
        ShowMessage(Format("Suche in %s", ARRAYOFCONST((SearchDir))));
        if(!DirectoryExists(ExtractFilePath(SearchDir)))
        {
            ShowMessage("Suchpfad scheint nicht zu existieren !!!");
            return false;
        }
    
        if(FindFirst(SearchDir,iAttributes, sr)==0)
        {
            ShowMessage("Beginne Suche nach Sprachen");
            do
            {
                if((sr.Attr & iAttributes) == sr.Attr)
                {
                    Temp = sr.Name.SubString(1,1);
                    ShowMessage("Verzeichnis "+sr.Name+ " Gefunden");
                    if((Temp != ".") && (Temp != ".."))
                    {
                        Temp = GetAppDir()+"lang\\"+sr.Name+"\\language.ini";
    
                        ShowMessage("Identifiziere Sprache in \n"+ Temp);
                        if(FileExists(Temp))
                        {
    
                            ShowMessage(Format("Sprache %s gefunden", ARRAYOFCONST((sr.Name))));
                            Langname = AddLanguagesToMenu(Temp,LangCount+1);
                            if(!Langname.IsEmpty())
                            {
                                ShowMessage(Format("Sprache %s, %s wird gespeichert", ARRAYOFCONST((sr.Name, Langname))));
                                AddLanguageToTempDB(sr.Name,Langname);
                                LangCount++;
                            }
                        }
                        else
                            ShowMessage(Format("Sprache in %s nicht gefunden", ARRAYOFCONST((Temp))));
                    }
                }
                else
                    ShowMessage("Suchpparameter stimmen nicht überein");
            }
            while(FindNext(sr)==0);
            FindClose(sr);
        }
        if(LangCount > 0)
            ShowMessage("Anzahl gefundener Sprachen : " + IntToStr(LangCount));
        else
            ShowMessage("Keine Sprachen gefunden");
    
        return (LangCount>0) ? true:false;
    }
    

    Ich habe es auch nochmals mit jemanden zusammen probiert und den Fehler weiter eingrenzen können. Der Fehler liegt innerhalb der do Schleife und zwar bei

    if((sr.Attr & iAttributes) == sr.Attr)
    

    Hier kommt das Programm nicht weiter und geht ans Ende und gibt eben aus das keien Sprachen gefunden wurde. Bei mir auf dem Rechner funktionierts aber weiterhin tadellos. Ich habe mich hierbei ans Beispiel aus der BCB Hilfe zu den Funktionen gehalten.

    Falls jemand mein Problem mal nachvollziehen möchte sollte er die Funktiosnaufrufe :

    ClearTempLangDB();
    AddLanguagesToMenu();
    AddLanguageToTempDB(sr.Name,Langname);
    

    Die Funktion AddLanguagesToMenu() liest eigentlich nur den Namen aus der Ini Datei aus und würde in meinem Fall diesen ans Menü anhängen was aber zum ausprobieren egal ist.

    Löschen. Und die Funktion GetAppDir(), gibt einfach nur den aktuellen Pfad des Programms zurück. Also

    return ExtractFilePath(Application->ExeName);
    

    Es sollten weiterhin im Unterverzeichnis noch die Unterordner und die Datei existieren

    -lang
        -de (hier für Deutsch)
            language.ini
    

    In der Language.ini sollte noch folgendes minimum drinne stehen.

    [language]
    name=deutsch
    

    Mit diesen kleinen Änderungen sollte meine Funktion dann ohne weiteres laufen.

    Ich bin weiterhin dankbar für jede Hilfe oder jeden Vorschlag woran es denn liegen könnte. Denn wie schon geschrieben bei mir auf dem Rechner läuft es so wie ich es mir gedacht habe.

    Ich hoffe mal ich habe ausführlich genug mein Problem geschildert und bekomme noch den einen oder anderen tip von euch.

    Fox



  • lass doch den ganzen quatsch mit den unterverzeichnissen weg und packe die sprach-dateien in ein verzeichnis und benamse sie mit dem namen der sprache oder der abkürzung dazu (alla top-level-domain).

    warum fragst du Directory nicht direkt ab, sondern machst den umweg ueber ne zusätzliche variable?

    if (sr.Attr & faDirectory)
    

    was heisst programm geht nicht weiter? geh das doch mal mit dem debugger durch und schaue, was überall so drinsteht und ob das sinn macht.

    der zweite test klappt nie!

    Temp = sr.Name.SubString(1,1);
    
    if ((Temp != ".") && (Temp != ".."))
    

    in der FAQ dürfte ausserdem ein funktion stehen, die dir rekursiv durch alle unterverzeichnisse geht.

    zur mehrsprachigkeit siehe auch hier: http://www.del-net.com/delphi/delphimultilan.html



  • Mit dem Debugger bringt mir ja herzlich wenig wenn es auf meinem Rechner immer geht: Auf den Rechnern wo es nicht geht habe ich nunmal keine möglichkeit den Debugger zu nutzen.

    Meine Mehsprachigkeit funktioniert sonst eigentlich ganz gut und ich hatte bisher auch noch keine Probleme. In diesem Programm habe ich nun zum erstenmal das eingefügt mit dem Menü.

    Ich habe ja nicht nur eine Datei in den Sprachenordnern und so macht es dem Benutzer einfacher selber Übersetzungen anzulegen, indem er einfach einen Ordner kopiert und die Dateien übersetzt, danach noch neustart des Programms und seine Sprache ist drinne.

    Das mit den Attributen habe ich so aus dem Hilfe Beispiel übernommen. Klar macht es sinn das direkt zu machen. Der Vorteil mit der Variablen liegt darin das ich wenn ich müsste/wollte im Debugger schauen kann ob es das richtige ist.

    Deinen Link werde ich mir heute abend mal anschauen. Aber wie schon gesagt meine Variante funktioniert bisher so wie ich es mir vorstelle.

    Fox



  • Jetzt wäre natürlich der genaue Inhalt der Verglaichsvariablen wirklich interessant.

    C ist bei Vergleichen ja viel pingeliger als als z.B. SQL oder Pascal.

    Es unterscheidet zum Bleistift zwischen Groß- und Kleinschreibung und ein == zwischen zwei Duoble-Werten ist ohne Angabe der Präzision fas Glückssache.

    Kannst Du denn die Werte nicht vorher testweise mal anzeigen lassen(MsgBox) ?

    z.B. MessageDlg(1.Variable + " "+ 2.Variable,mtWarning,TMsgDlgButtons()<<mbOK, 0)

    - falls keine Typumwandlungen dafür notwendig sind



  • Ich verstehe das ganze Programm überhaupt nicht:

    Du willst ein Verzeichnis durchsuchen. Gut. Jedoch nicht rekurisv?? Stattdessen wühlst du in dem vorgegebenen Verzeichnis herum bis du ein (irgendein) anderes Verzeichnis findest. Dann unterstellst du, das IN diesem Verzeichnis dann eine language.ini liegt. Somit ist der Sprachaufbau bei dir - wenn ich es richtig verstanden habe - so:

    Ordner Deutsch mit language.ini
    Ordner Spanisch mit language.ini
    ...

    Das ist ungewöhnlich. Was für ein Grund besteht den nur, dass ausgerechnet ein Programmverzeichnis einen nichtbekannten Namen hat?? Das wäre ja so, als wenn ein Spiel seine Grafikdateien erst suchen müßte, weil die irgendwo liegen könnten. Packe alle deine Sprchdateien in einen Ordner nach dem Motto

    Deutsch.ini
    Spanisch.ini

    Des Weiteren die Zeile

    if((sr.Attr & iAttributes) == sr.Attr)

    Was soll sie bewirken. Da nur ein einziges Attribut in Frage kommen kann, kann dieses direkt eingetragen werden
    if((sr.Attr & faDirectory) == sr.Attr)

    faDirectory ist 16

    Wir haben also nun das Attribut der Datei sr.Attr & 16. Was kann rauskommen? sr.Attr??



  • http://www.marquardtnet.info/cecke/dlls.3/3_index.html

    Kannst gerne den Quelltext anfordern


Anmelden zum Antworten