ini-Datei: wohin

Für alles, was in den übrigen Lazarusthemen keinen Platz, aber mit Lazarus zutun hat.
mschnell
Beiträge: 3444
Registriert: Mo 11. Sep 2006, 10:24
OS, Lazarus, FPC: svn (Window32, Linux x64, Linux ARM (QNAP) (cross+nativ)
CPU-Target: X32 / X64 / ARMv5
Wohnort: Krefeld

ini-Datei: wohin

Beitrag von mschnell »

In Win98 war alles klar: die Ini-Date hat den Dateinamen und das Directory des Programms mit der Endung .ini .

In Win XP und in Linux gibt es wechselnde Benutzer, die jeweils bestimmte Reche haben. In dem Directory wo das Executable steht, hat ein Benutzer keine Schreibrechte.

Außerdem gibt es (mindestens) drei unterschiedliche Arten von Information, die in ini-Dateien gehalten werden soll:

(a) nur vom Adminsistrator / root veränderbar
(b) vom Benutzer im Programmablauf änderbar und nur für diesen Benutzer gültig
(c) vom Benutzer im Programmablauf änderbar und für alle Benutzer gültig

Mir ist klar, dass diese Informationen in drei ini-Dateien verschiedenen Directories gehalten werden müssen: z.B.: in XP deutsch Standard-Installation:
alle heißen wie das Programm mit der Endung .ini
(a) wie gewohnt in dem Directory wo das Executable steht,
(b) in "Dokumente und Einstellungen\%username%\Anwendungsdaten"
(b) in "Dokumente und Einstellungen\All Usres\Anwendungsdaten"

Fragen:
- Wie sieht das in Linux aus ?
- Wie kommt man an die richtigen Directory-Namen, unabhängig von Installation und Art des OS und vom aktuellen User ?
- gibt es eine OS-Unabhängige INI-Dateien- Verwaltungs-unit und wenn nein warum nicht.

-Michael

Christian
Beiträge: 6079
Registriert: Do 21. Sep 2006, 07:51
OS, Lazarus, FPC: iWinux (L 1.x.xy FPC 2.y.z)
CPU-Target: AVR,ARM,x86(-64)
Wohnort: Dessau
Kontaktdaten:

Beitrag von Christian »

Hier die zumindest unter windows korrekte und auch für vista gültige antwort.

GetConfigDir liefert unter windows z.b. C:\Dokumente und Einstellungen\[Benutzername]\Lokale Einstellungen\Anwendungsdaten\[app] zurück

Unter Linux /hone/[Benutzername]/.[app]

das ist soweit alles korrekt

GetGlobalConfigDir liefert unter Windows D:\Dokumente und Einstellungen\All Users\Anwendungsdaten\[app] zurück

unter linux das programmverzeichnis ich bin mir beim linux nicht ganz sicher ob man dort nicht /etc/[app] nehmen sollte allerdings ist das anwendungsverzeichnis eventuell noch beschreibbar mit normalen benutzerrechten zumindest wenn man die anwendung aus dem homeverzeichnis aufruft /etc mit sicherheit nicht mehr.

falls jemand ne idee hat wie man aud diesen routinen nen dialog aufrufen kann in dem man das root passwort eingeben kann und dann in das globale programmverzeichnis schreiben kann wäre das eine schöne erweiterung.
oder als seperate Funktion GetRootRights oder so

ausserdem würd ich nicht unbedingt ini files benutzen xml ist genau so einfach und macht unter linux nicht so einen basteleindruck :)

Code: Alles auswählen

function GetConfigDir(app : string) : string;
begin
{$IFDEF MSWINDOWS}
  Result := copy(GetAppConfigDir(False),0,length(GetAppConfigDir(False))-length(ApplicationName))+app;
{$ELSE}
  Result:=GetEnvironmentVariable('HOME');
  If (Result<>'') then
    Result:=IncludeTrailingPathDelimiter(Result)+'.'+app;
{$ENDIF}
  Result := IncludeTrailingPathDelimiter(result);
end;
 
function GetGlobalConfigDir(app : string) : string;
{$IFDEF MSWINDOWS}
const
  CSIDL_COMMON_APPDATA  = $0023; // All Users\Application Data
  CSIDL_FLAG_CREATE     = $8000; { (force creation of requested folder if it doesn't exist yet)     }
var
  Path: array [0..1024] of char;
  P : Pointer;
  SHGetFolderPath : PFNSHGetFolderPath = Nil;
  CFGDLLHandle : THandle = 0;
{$ENDIF}
begin
{$IFDEF MSWINDOWS}
  CFGDLLHandle:=LoadLibrary('shell32.dll');
  if (CFGDLLHandle<>0) then
    begin
    P:=GetProcAddress(CFGDLLHandle,'SHGetFolderPathA');
    If (P=Nil) then
      begin
      FreeLibrary(CFGDLLHandle);
      CFGDllHandle:=0;
      end
    else
      SHGetFolderPath:=PFNSHGetFolderPath(P);
    end;
  If (P=Nil) then
    begin
    CFGDLLHandle:=LoadLibrary('shfolder.dll');
    if (CFGDLLHandle<>0) then
      begin
      P:=GetProcAddress(CFGDLLHandle,'SHGetFolderPathA');
      If (P=Nil) then
        begin
        FreeLibrary(CFGDLLHandle);
        CFGDllHandle:=0;
        end
      else
        ShGetFolderPath:=PFNSHGetFolderPath(P);
      end;
    end;
  Result := ExtractFilePath(Application.Exename);
  If (@ShGetFolderPath<>Nil) then
    if SHGetFolderPath(0,CSIDL_COMMON_APPDATA or CSIDL_FLAG_CREATE,0,0,@PATH[0])=S_OK then
      Result:=IncludeTrailingPathDelimiter(StrPas(@Path[0]))+app;
{$ELSE}
{$ENDIF}
  Result := IncludeTrailingPathDelimiter(result);
end;

mschnell
Beiträge: 3444
Registriert: Mo 11. Sep 2006, 10:24
OS, Lazarus, FPC: svn (Window32, Linux x64, Linux ARM (QNAP) (cross+nativ)
CPU-Target: X32 / X64 / ARMv5
Wohnort: Krefeld

Re: ini-Datei: wohin

Beitrag von mschnell »

In einem Delphi Forum fand ich folgendes

Joseph Donnelly hat geschrieben:ISTR the way I test for folders (I use D4 and D5 mostly) may be
deprecated in D6 or D7 and above, but here it is anyway:
DirectoryExists

You can cause a directory to exist with the ForceDirectories procedure,
but verify it exists after doing that.

Here is the source to a unit ever so graciously provided by Peter Below
with such a function to find the folder name. There may be a later
version with more location aliases defined. The ones I think you are
after are CSIDL_COMMON_APPDATA (for all users), and CSIDL_APPDATA (for
individual users):

{== Unit ShellUtils
===================================================}
{: Collects some helper routines for access to Windows Shell objects
@author Dr. Peter Below
@desc Version 1.0 created 4 August 2000

Current revision 1.01

Last modified 16.02.2001



}{======================================================================
}

unit ShellUtils;
interface

uses ShlObj;

const
{ Aliases for ShlObj constants, so client need not use ShlObj }
CSIDL_DESKTOP = ShlObj.CSIDL_DESKTOP;
CSIDL_INTERNET = ShlObj.CSIDL_INTERNET;
CSIDL_PROGRAMS = ShlObj.CSIDL_PROGRAMS;
CSIDL_CONTROLS = ShlObj.CSIDL_CONTROLS;
CSIDL_PRINTERS = ShlObj.CSIDL_PRINTERS;
CSIDL_PERSONAL = ShlObj.CSIDL_PERSONAL;
CSIDL_FAVORITES = ShlObj.CSIDL_FAVORITES;
CSIDL_STARTUP = ShlObj.CSIDL_STARTUP;
CSIDL_RECENT = ShlObj.CSIDL_RECENT;
CSIDL_SENDTO = ShlObj.CSIDL_SENDTO;
CSIDL_BITBUCKET = ShlObj.CSIDL_BITBUCKET;
CSIDL_STARTMENU = ShlObj.CSIDL_STARTMENU;
CSIDL_DESKTOPDIRECTORY = ShlObj.CSIDL_DESKTOPDIRECTORY;
CSIDL_DRIVES = ShlObj.CSIDL_DRIVES;
CSIDL_NETWORK = ShlObj.CSIDL_NETWORK;
CSIDL_NETHOOD = ShlObj.CSIDL_NETHOOD;
CSIDL_FONTS = ShlObj.CSIDL_FONTS;
CSIDL_TEMPLATES = ShlObj.CSIDL_TEMPLATES;
CSIDL_COMMON_STARTMENU = ShlObj.CSIDL_COMMON_STARTMENU;
CSIDL_COMMON_PROGRAMS = ShlObj.CSIDL_COMMON_PROGRAMS;
CSIDL_COMMON_STARTUP = ShlObj.CSIDL_COMMON_STARTUP;
CSIDL_COMMON_DESKTOPDIRECTORY = ShlObj.CSIDL_COMMON_DESKTOPDIRECTORY;
CSIDL_APPDATA = ShlObj.CSIDL_APPDATA;
CSIDL_PRINTHOOD = ShlObj.CSIDL_PRINTHOOD;
CSIDL_ALTSTARTUP = ShlObj.CSIDL_ALTSTARTUP;
CSIDL_COMMON_ALTSTARTUP = ShlObj.CSIDL_COMMON_ALTSTARTUP;
CSIDL_COMMON_FAVORITES = ShlObj.CSIDL_COMMON_FAVORITES;
CSIDL_INTERNET_CACHE = ShlObj.CSIDL_INTERNET_CACHE;
CSIDL_COOKIES = ShlObj.CSIDL_COOKIES;
CSIDL_HISTORY = ShlObj.CSIDL_HISTORY;
CSIDL_COMMON_APPDATA = $0023;
CSIDL_WINDOWS = $0024;
CSIDL_SYSTEM = $0025;
CSIDL_PROGRAM_FILES = $0026;
CSIDL_MYPICTURES = $0027;
CSIDL_PROFILE = $0028;
CSIDL_SYSTEMX86 = $0029;
CSIDL_PROGRAM_FILESX86 = $002A;
CSIDL_PROGRAM_FILES_COMMON = $002B;
CSIDL_PROGRAM_FILES_COMMONX86 = $002C;
CSIDL_COMMON_TEMPLATES = $002D;
CSIDL_COMMON_DOCUMENTS = $002E;
CSIDL_COMMON_ADMINTOOLS = $002F;
CSIDL_ADMINTOOLS = $0030;
CSIDL_CONNECTIONS = $0031;
CSIDL_COMMON_MUSIC = $0035;
CSIDL_COMMON_PICTURES = $0036;
CSIDL_COMMON_VIDEO = $0037;
CSIDL_RESOURCES = $0038;
CSIDL_RESOURCES_LOCALIZED = $0039;
CSIDL_COMMON_OEM_LINKS = $003A;
CSIDL_CDBURN_AREA = $003B;
CSIDL_COMPUTERSNEARME = $003D;
CSIDL_FLAG_PER_USER_INIT = $00800;
CSIDL_FLAG_NO_ALIAS = $001000;
CSIDL_FLAG_DONT_VERIFY = $004000;
CSIDL_FLAG_CREATE = $008000;
CSIDL_FLAG_MASK = $00FF00;

function GetShellFoldername(folderID: Integer): string;

implementation

uses Windows, SysUtils, ActiveX, ShellAPI;

function GetShellFoldername(folderID: Integer): string;
var
pidl: PItemIDList;
buf: array[0..MAX_PATH] of Char;
begin
Result := '';
if Succeeded(ShGetSpecialFolderLocation(GetActiveWindow, folderID,
pidl)) then
begin
if ShGetPathfromIDList(pidl, buf) then
Result := buf;
CoTaskMemFree(pidl);
end { If }
end; { GetShellFoldername }

end { Unit ShellUtils }.

--
Joe


mschnell
Beiträge: 3444
Registriert: Mo 11. Sep 2006, 10:24
OS, Lazarus, FPC: svn (Window32, Linux x64, Linux ARM (QNAP) (cross+nativ)
CPU-Target: X32 / X64 / ARMv5
Wohnort: Krefeld

Beitrag von mschnell »

Christian hat geschrieben:.... unter linux das programmverzeichnis ich bin mir beim linux nicht ganz sicher ob man dort nicht /etc/[app] nehmen sollte

Danke für die klaren Antworten !

Mit /etc/[app] hast Du sicher auch recht. Da braucht man auch keinen API-call um dieses Directory zu finden

Das Home directory ist in Linux '~'. Da braucht man auch keinen API call. Nehme man also "~/[app]" (Ich glaube die Konvention ist ".[app]". Das Directory ist dann hidden.)

Wohin aber mit von allen Benutzer veränderbaren Werten ?

Christian hat geschrieben:ausserdem würd ich nicht unbedingt ini files benutzen xml ist genau so einfach und macht unter linux nicht so einen basteleindruck :)


Naja. Eine ini-Komponente ist bei FP dabei. "Professioneller" ist natürlich XML (auch in Windows). Ist bei FP dafür etwas mitgeliefert, oder muss man sich das woanders besorgen ?

-Michael

Christian
Beiträge: 6079
Registriert: Do 21. Sep 2006, 07:51
OS, Lazarus, FPC: iWinux (L 1.x.xy FPC 2.y.z)
CPU-Target: AVR,ARM,x86(-64)
Wohnort: Dessau
Kontaktdaten:

Beitrag von Christian »

Das Home directory ist in Linux '~'. Da braucht man auch keinen API call. Nehme man also "~/[app]" (Ich glaube die Konvention ist ".[app]". Das Directory ist dann hidden.)


genau das liefert ja getAppConfigDir zurück auch mit versteckten pfaden.

Wohin aber mit von allen Benutzer veränderbaren Werten ?


dafür will ich ja die GetRootRights routine, wenn jemand ne idee hat wie man im laufenden betrieb für die eigene app root rights bekommen kann immer raus damit :)

xml hätt ich ja fast vergessen ja natürlich ist dafür was da TXMLPropStorage z.b. damit kannst du deine Einstellungen sogar visuell verwalten es gibt aber auch dom units.

mschnell
Beiträge: 3444
Registriert: Mo 11. Sep 2006, 10:24
OS, Lazarus, FPC: svn (Window32, Linux x64, Linux ARM (QNAP) (cross+nativ)
CPU-Target: X32 / X64 / ARMv5
Wohnort: Krefeld

Beitrag von mschnell »

Christian hat geschrieben:dafür will ich ja die GetRootRights routine, wenn jemand ne idee hat wie man im laufenden betrieb für die eigene app root rights bekommen kann immer raus damit :)


Die Einstellungen, die man nur mit "root" Rechten machen darf, fallen in meine Kategorie (a). Ich denke aber auch an Einstellungen die jeder machen darf. Das kann bei Gemeinsamer Benutzung eines Programms wichtig sein.

Christian hat geschrieben:xml hätt ich ja fast vergessen ja natürlich ist dafür was da TXMLPropStorage z.b. damit kannst du deine Einstellungen sogar visuell verwalten es gibt aber auch dom units.


Schau ich mir an.

-Michael

Christian
Beiträge: 6079
Registriert: Do 21. Sep 2006, 07:51
OS, Lazarus, FPC: iWinux (L 1.x.xy FPC 2.y.z)
CPU-Target: AVR,ARM,x86(-64)
Wohnort: Dessau
Kontaktdaten:

Beitrag von Christian »

Die Einstellungen, die man nur mit "root" Rechten machen darf, fallen in meine Kategorie (a). Ich denke aber auch an Einstellungen die jeder machen darf. Das kann bei Gemeinsamer Benutzung eines Programms wichtig sein.


Mir fällt aber kein "gemeinsam benutztes" Verzeichnis unter linux ein ausser /tmp lol.

Wozu auch es gibt eigentlich keine einstellung die ein benutzer für einen anderen einstellen können muss.
W.m.k.A.h.e.m.F.h. -> http://www.gidf.de/

mschnell
Beiträge: 3444
Registriert: Mo 11. Sep 2006, 10:24
OS, Lazarus, FPC: svn (Window32, Linux x64, Linux ARM (QNAP) (cross+nativ)
CPU-Target: X32 / X64 / ARMv5
Wohnort: Krefeld

Beitrag von mschnell »

Christian hat geschrieben:
Wozu auch es gibt eigentlich keine einstellung die ein benutzer für einen anderen einstellen können muss.


Da fallen mir aber viele ein.
- super-primitiv: Zähler wie oft das Programm aufgerufen wurde
- Zwischenstand ("Schichtwechsel"), wenn der nächste Benutzer an dem Punkt weiter arbeiten soll, wo der vorige aufgehört hat
- "Nachrichten" von einem Benutzer an alle anderen

Lässt sich alles mit einer Client-Server-Applikation oder einer Datenbank machen. Ich denke aber hier an "kleine" Projekte.

-Michael

Christian
Beiträge: 6079
Registriert: Do 21. Sep 2006, 07:51
OS, Lazarus, FPC: iWinux (L 1.x.xy FPC 2.y.z)
CPU-Target: AVR,ARM,x86(-64)
Wohnort: Dessau
Kontaktdaten:

Beitrag von Christian »

@Michael

Alle fälle die du aufgezählt hast treffen nur auf systeme zu die eh einen datenbank haben und dort würd ich das ganze einfach in die datenbank schreiben. Der Zähler ist hier der einzige etwas unklare fall aber den unix dateibaum gibts mittlerweile jahrzehnte ich hab gestern nochmal die offizielle quasi normierung durchgeschaut es gibt keinen ordner der für alle benutzer schreibbar ist und nicht /tmp heisst (also wahllos vom system gelöscht werden kann).
W.m.k.A.h.e.m.F.h. -> http://www.gidf.de/

mschnell
Beiträge: 3444
Registriert: Mo 11. Sep 2006, 10:24
OS, Lazarus, FPC: svn (Window32, Linux x64, Linux ARM (QNAP) (cross+nativ)
CPU-Target: X32 / X64 / ARMv5
Wohnort: Krefeld

Beitrag von mschnell »

Christian hat geschrieben: den unix dateibaum gibts mittlerweile jahrzehnte ich hab gestern nochmal die offizielle quasi normierung durchgeschaut es gibt keinen ordner der für alle benutzer schreibbar ist und nicht /tmp heisst (also wahllos vom system gelöscht werden kann).

OK. Dan bleibt wohl folgende Lösung:
Das Installations-Script (von root ausgeführt) legt ein directory .[appname] an und darin die nur von root änderbare Datei. Wird auch eine von allen Usern änderbare Datei benötigt, legt das Installations-Script sie auch da an und setzt die Rechte dieser Datei entsprechend (777 oder so).

-Michael

Christian
Beiträge: 6079
Registriert: Do 21. Sep 2006, 07:51
OS, Lazarus, FPC: iWinux (L 1.x.xy FPC 2.y.z)
CPU-Target: AVR,ARM,x86(-64)
Wohnort: Dessau
Kontaktdaten:

Beitrag von Christian »

Joa, das würde gehen.
W.m.k.A.h.e.m.F.h. -> http://www.gidf.de/

mschnell
Beiträge: 3444
Registriert: Mo 11. Sep 2006, 10:24
OS, Lazarus, FPC: svn (Window32, Linux x64, Linux ARM (QNAP) (cross+nativ)
CPU-Target: X32 / X64 / ARMv5
Wohnort: Krefeld

Beitrag von mschnell »

Ich habe 'mal (zunächst mit Delphi) eine Komponente gebastelt, die wie TIniFile aussieht und die drei Möglichkeiten zur Ablage der Datei durch eine zusätzliche Property zur Verfügung stellt. Bitte sagt Bescheid, wenn jemand das mit TP/lazarus testen möchte und/oder es für Linux erweitern will.

Gruß,
-Michael

danny61
Beiträge: 94
Registriert: So 5. Nov 2006, 18:40
OS, Lazarus, FPC: Winux (L 0.9.xy FPC 2.2.z)
CPU-Target: xxBit
Wohnort: Berlin

Beitrag von danny61 »

Ich muß hier auch noch mal kurz meinen Senf dazugeben :
1. Die Verwendung von "GetAppConfigDir(false)" hat auf meinem WinXP SP2 leider ein unbrauchbares Ergebnis geliefert :
"C:\Windows\local settings\Anwendungsdaten\myapp" und nicht "C:\Dokumente und Einstellungen\user\Anwendungsdaten\myapp"
Ich weiß nicht woran es liegt. Alle Umgebungsvariablen weisen korrekte Pfade aus.
Evtl. liegt es daran, daß meine Installation bereits seit mehreren Jahren läuft und auch schon mehrere Hardwarewechsel hinter sich hat und wenn ich mich noch richtig (dunkel) erinnere, habe ich sogar ein Update von win98 damit gemacht.
Man kann sich also nicht 100% auf die ermittelten Werte verlassen.
Außerdem kann es zu Fehlern in Zusammenhang mit UPX kommen, welches man dann also auch nicht mehr benutzen sollte.
2. Die Verwendung von XML-Dateien halte ich nicht für Sinnvoll, da es nichts bequemeres gibt als eine INI-Datei mit einem beliebigen Editor zu bearbeiten.

Christian
Beiträge: 6079
Registriert: Do 21. Sep 2006, 07:51
OS, Lazarus, FPC: iWinux (L 1.x.xy FPC 2.y.z)
CPU-Target: AVR,ARM,x86(-64)
Wohnort: Dessau
Kontaktdaten:

Beitrag von Christian »

getAppConfigDir nutzt Standard Windows Routinen bis jetzt hat das auch mehreren tausend Systemen geklappt (wird in jedem meiner Programme verwendet)
Bist du dir 100%ig sicher ?
W.m.k.A.h.e.m.F.h. -> http://www.gidf.de/

danny61
Beiträge: 94
Registriert: So 5. Nov 2006, 18:40
OS, Lazarus, FPC: Winux (L 0.9.xy FPC 2.2.z)
CPU-Target: xxBit
Wohnort: Berlin

Beitrag von danny61 »

hatte es vor meinem Beitrag gerade noch einmal getestet, da mir das Verzeichnis nicht mehr einfiel.

Antworten