ini-Datei: wohin
-
- 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
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
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
-
- 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:
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
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;
-
- 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
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
-
- 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
Danke für die klaren Antworten !Christian hat geschrieben: .... unter linux das programmverzeichnis ich bin mir beim linux nicht ganz sicher ob man dort nicht /etc/[app] nehmen sollte
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 ?
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 ?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
-Michael
-
- 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:
genau das liefert ja getAppConfigDir zurück auch mit versteckten pfaden.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.)
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 damitWohin aber mit von allen Benutzer veränderbaren Werten ?

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.
-
- 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
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: 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
Schau ich mir an.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.
-Michael
-
- 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:
Mir fällt aber kein "gemeinsam benutztes" Verzeichnis unter linux ein ausser /tmp lol.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.
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/
-
- 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
Da fallen mir aber viele ein.Christian hat geschrieben:Wozu auch es gibt eigentlich keine einstellung die ein benutzer für einen anderen einstellen können muss.
- 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
-
- 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:
@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).
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/
-
- 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
OK. Dan bleibt wohl folgende Lösung: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).
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
-
- 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
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
Gruß,
-Michael
-
- 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
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.
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.