.ini Dateien unter Win7



  • Scorcher24 schrieb:

    Ich finde es eine sehr schlechte Gewohnheit wenn man wegen fehlender Rechte einfach nach diesen fragt obwohl man sie nicht braucht. Dateien die vom Nutzer modifiziert werden, gehören nach My Documents oder in den AppPath.

    👍
    Danke



  • @Scorcher24 und hustbaer
    Grundsätzlich vollkommen korrekt 😉

    Nur:

    Aber das Programm schreibt gar nicht in die .ini sondern soll sie nur beim Start lesen.

    Laut dieser Aussage könnte es sich z.B. um eine Konfigurationsdatei handeln, die vom Installer erstellt wird und Grundeinstellungen zum Start beinhaltet.

    Auf programmspezifische Dateien ohne Pfadangabe zuzugreifen, wie Martin Richter es schon sagte, geht meistens in die Hose.



  • -guest- schrieb:

    Nur:

    Aber das Programm schreibt gar nicht in die .ini sondern soll sie nur beim Start lesen.

    Laut dieser Aussage könnte es sich z.B. um eine Konfigurationsdatei handeln, die vom Installer erstellt wird und Grundeinstellungen zum Start beinhaltet.

    Stimmt, ja. Dann gibt es erst recht keinen Grund Admin-Rechte zu verlangen.
    Einfach den korrekten Pfad ermitteln (GetModuleFilename, hat Martin Richter ja schon geschrieben), und aufmachen.

    Die mMn. wichtigen Punkte hier sind:
    * Keine Admin-Rechte verlangen wenn nicht nötig
    * Wenn man Einstellungen/... schreiben will, dann im passenden Verzeichnis (-> AppData)



  • Vielen Dank für die vielen hilfreichen Antworten!

    Es ist also, wenn ich das jetzt richtig verstanden habe, nicht notwendig (und "unschön") nach Adminrechten für das Programm zu verlangen. OK.

    Jetzt muss ich mir also beim Programmstart den Pfad ins aktuelle Verzeichnis besorgen. Das Testprogramm sieht jetzt so aus:

    TCHAR EXEPath[MAX_PATH + 1];
    DWORD nChars = GetModuleFileName( NULL, EXEPath, MAX_PATH + 1 );
    //EXEPath enthält jetzt den Pfad inklusive Dateiname der exe
    
    //hier mache ich nen std::string draus um auf die Konsole auszugeben
    std::string strPath;
    strPath.assign(&EXEPath[0], &EXEPath[nChars]);
    std::cout<<"\n"<<strPath;
    
    std::ifstream CONF;
    CONF.open("startup.ini");
    if(CONF)
    {
        //Inhalt der Datei startup.ini einlesen
        CONF.close();
    }
    else
    {
        std::cout<<"\nstartup.ini not found";
    }
    

    Die Ausgabe auf der Konsole ist jetzt wie erwartet

    D:\EigeneProgramme\Test\bin\Debug\Testprogramm.exe

    Hier muss ja nun noch der Dateiname entfernt und statt dessen der Name der .ini Datei (startup.ini) angefügt werden.
    Gibt es für char-Arrays so etwas wie substring(pos_begin, pos_end) und find_last_of() für strings um den Dateinamen der exe abschneiden zu können?

    Alberich





  • Mit PathRemoveFileSpec kann man den Dateinamen entfernen 😉



  • Alberich schrieb:

    Hier muss ja nun noch der Dateiname entfernt und statt dessen der Name der .ini Datei (startup.ini) angefügt werden.

    Japp.

    Gibt es für char-Arrays so etwas wie substring(pos_begin, pos_end) und find_last_of() für strings um den Dateinamen der exe abschneiden zu können?

    Nö. Aber es gibt ja std::string. Willst du std::string aus irgend einem Grund dafür nicht verwenden?

    Ansonsten...
    PathRemoveFileSpec EDIT: zu langsam *grmpf* /EDIT

    #include <windows.h>
    #include <shlwapi.h> // für PathRemoveFileSpec
    
    #pragma comment(lib, "shlwapi.lib") // für PathRemoveFileSpec
    
    // ...
    
        // TODO: check for errors
    
        TCHAR exeDirectory[MAX_PATH] = {}; // + 1 brauch ma nicht. Das = {} auch nicht, aber naja... hab's mir irgendwann angewöhnt so-gut-wie immer alles zu initialisieren.
                                           // Da hier nicht Performance-kritisch schadet es auch nicht.
        GetModuleFileName(NULL, exeDirectory, MAX_PATH);
        PathRemoveFileSpec(exeDirectory);  // Macht Filenamen inklusive dem letzten "\" weg (modifiziert direkt den übergebenen Puffer)
    
        // Wenn schon TCHAR dann auch bei std::basic_string, sonst kompiliert das ja nichtmal mit UNICODE
        // (ggf. irgendwo in nem .h File ein nettes  typedef std::basic_string<TCHAR> tstring;  machen)
        std::basic_string<TCHAR> configFilePath = std::basic_string<TCHAR>(exeDirectory) + _T("\\startup.ini");
    
        std::ifstream configFile(configFilePath.c_str()); // geht auch ohne extra .open() Zeile
        if (configFile)
        {
            // Inhalt der Datei startup.ini einlesen
            // configFile.close(); // kümmert sich der Destruktor drum, und bei ausschliesslich lesenden Zugriffen ist das auch vollkommen OK
        }
        else
        {
            std::cout<<"\nstartup.ini not found";
        }
    

    Bitte die ganzen zusätzlichen Anmerkungen nicht falsch verstehen. Wenns dich nicht interessiert überlies es einfach, falls doch hast du ein paar Tips was du besser/anders machen kannst.



  • hustbaer schrieb:

    Bitte die ganzen zusätzlichen Anmerkungen nicht falsch verstehen. Wenns dich nicht interessiert überlies es einfach, falls doch hast du ein paar Tips was du besser/anders machen kannst.

    Ganz im Gegenteil! Ich bin dankbar für jede Hilfe und Anmerkung! Dein Codebeispiel finde ich sehr lehrreich, leider spielt der Compiler/Linker nicht mit:

    Zeile 4: warning: ignoring #pragma comment
    Zeile 13: undefined reference to `_imp__PathRemoveFileSpecA@4'

    Ich verwende Code::Blocks (10.05).



  • #pragma comment(lib, "shlwapi.lib") führt bei MS Visual C++ dazu, dass die "shlwapi.lib", die PathRemoveFileSpec enthält automatisch zu deinem Programm gelinkt wird. Bei CodeBlocks musst du sie wohl in den (Projekt-)Einstellungen eintragen.



  • gcc kann mittlerweile afaik das #pragma :).



  • OK, werd ich mir anschauen. Danke!

    Habe noch ein bischen über das "Problem" nachgedacht und dieser Satz von hustbaer hat mich in die (hoffentlich 🙂 ) richtige Richtung geschubst:

    hustbaer schrieb:

    [...] Aber es gibt ja std::string. Willst du std::string aus irgend einem Grund dafür nicht verwenden?

    Es ist ja eigentlich schon alles da was ich brauche...

    TCHAR EXEPath[ MAX_PATH ];
    DWORD nChars = GetModuleFileName( NULL, EXEPath, MAX_PATH );
    
    //in einen string schreiben
    std::basic_string<TCHAR> strPath;
    strPath.assign( &EXEPath[0], &EXEPath[nChars] );
    //den Namen der .exe abschneiden
    strPath=strPath.substr( 0, strPath.find_last_of(_T("/\\")) );
    //den Namen der .ini stattdessen anfügen
    strPath=strPath + _T("\\startup.ini");
    
    //und wieder einen C-string draus machen
    std::ifstream configFile( strPath.c_str() );
    if(configFile)
    {
        //lesen
        //configFile.close(); //Aber schaden würde das explizite schliessen auch nicht, oder doch?
    }
    

    Gibt es gegen diese Lösung Einwände?

    Alberich



  • //edit: Chupa Chups, LLLLösch mich!



  • Alberich schrieb:

    std::basic_string<TCHAR> strPath;
    strPath.assign( &EXEPath[0], &EXEPath[nChars] );
    

    Warum nicht gleich

    [cpp]std::basic_string<TCHAR> strPath( EXEPath );
    

    ?



  • In der Kürze liegt die Würze! 🙂
    Danke für den Hinweis, ich wusste nicht dass man das auch so zuweisen kann!


Anmelden zum Antworten