Entwickler-Ecke
Dateizugriff - Sinnvollste Lösung: Wo Daten speichern?
JayEff - Mo 05.02.07 17:36
Titel: Sinnvollste Lösung: Wo Daten speichern?
Hallo Leute!
Folgende Situation.
Man weis nicht genau, ob man Schreibrechte im Programmverzeichnis hat, ob Windows xp oder höher vorhanden, sprich, der Anwenderdaten Ordner verfügbar ist etc. etc.
Ich habe überlegt, den User den Speicherort wählen zu lassen, das Problem ist natürlich dann, wie speichere ich die Information über den Speicherort? Schließlich muss mein Programm wissen, wo es suchen muss, noch bevor ich eine Ini laden kann, in der der Speicherort gespeichert ist.. Ähm .. ich weis, verwirrend, ich hoffe ihr verstehts dennoch.
Meine Frage nun:
Was ist die sinnvollste Lösung für dieses Problem? SHGetSpecialFolderPath einsetzen, wenn das nicht geht, Programmpfad versuchen, wenn das nicht geht, Start verweigern? ( :lol: )
Hat sich schonmal jemand mit diesem Problem auseinander gesetzt, eine eine derartige Prozedur geschrieben und wäre bereit selbige zu posten? Ein Konzept würde natürlich auch reichen ;)
Danke schonmal,
Jay
Gausi - Mo 05.02.07 17:52
Na, da bin ich ja mal erleichtert, dass nicht nur ich mir Gedanken darüber mache :lol:.
Meine Lösung sieht so aus - wenn auch etwas unkonventionell:
Delphi-Quelltext
1: 2: 3: 4: 5: 6:
| if AnsiLowerCase(ExtractFileName(Application.ExeName)) = 'blabla.exe' then SavePath := ExtractFilePath(Application.ExeName) else SavePath := GetShellFolder(CSIDL_APPDATA) + ; |
In dem else-Zweig könnte man zusätzlich überprüfen, ob überhaupt ein NT-System vorhanden ist, bei dem dieser Ordner existiert.
Die Info, wo nach der Ini etc. gesucht werden soll, speichere ich also im Dateinamen der Exe. Alles andere (über Schreibrechte etc.) halte ich für Problematisch, da diese vom Admin geändert werden können und/oder dadurch beide Dateiversionen entstehen können, womit der User dann verwirrt sein könnte, wo die Infos nun gelesen werden.
Ich mache das bei mir so, weil es Programme gibt, für die beide Varianten sinnvoll sind. Allgemein würde ich das Anwenderverzeichnis vorziehen. Also so:
Delphi-Quelltext
1: 2: 3: 4: 5:
| if WindowsVersion >= NT then SavePath := GetShellFolder(CSIDL_APPDATA) + else SavePath := ExtractFilePath(Application.ExeName) |
Martin1966 - Mo 05.02.07 17:56
Titel: Re: Sinnvollste Lösung: Wo Daten speichern?
hallo :wink2:
JayEff hat folgendes geschrieben: |
Ich habe überlegt, den User den Speicherort wählen zu lassen, das Problem ist natürlich dann, wie speichere ich die Information über den Speicherort? Schließlich muss mein Programm wissen, wo es suchen muss, noch bevor ich eine Ini laden kann, in der der Speicherort gespeichert ist.. |
Den Speicherort könntest du in der Registry ablegen.
JayEff hat folgendes geschrieben: |
Was ist die sinnvollste Lösung für dieses Problem? |
Als sinnvoll würde ich das
Benutzer-Anwendungsdaten-Verzeichnis [
http://www.delphi-library.de/topic_wie+kann+ich+spezielle+Ordner+finden_9428.html] (CSIDL_APPDATA) sehen. ;-)
Lg Martin
HelgeLange - Mo 05.02.07 17:57
Man weiss nicht, welche Windows-Version verwendet wird ? Kann man das neuerdings nicht mehr rausbekommen ?
Und Registry sollte doch immer gehen, oder ? Ich meine, HK_CURRENT_USER zum Bsp. Kann mir ehrlich gesagt nicht vorstellen, dass die bei M$ dir als Programm den Zugriff darauf verwehren, schliesslich ist die Registry dazu gedacht, genau solche Informationen zu hinterlegen...
JayEff - Mo 05.02.07 18:00
Aha! Interessanter Vorschlag, nur bedeutet das, dass ich dem Benutzer sagen muss: "Wenn du XP hast, änder den Dateinamen!" oder wie stellst du dir das vor? (Ich erinnere mich dunkel an ein Nemp.exe und NempXP.exe, aber weis nicht mehr, um was es da ging...)
Martin, wenn ich keinen Zugriff aufs Programmverzeichnis habe (Sprich, nicht Admin bin), habe ich vermutlich auch keinen auf die Registry.
Klar ist das Anwenderdatenverzeichniss sinnvoll, nur weis ich ja nicht, ob NT oder höher und damit selbiges Verzeichnis vorhanden ist.
HelgeLange hat folgendes geschrieben: |
Man weiss nicht, welche Windows-Version verwendet wird ? Kann man das neuerdings nicht mehr rausbekommen ? |
Doch schon, aber es ist .. kompliziert ... :(
Gausi - Mo 05.02.07 18:13
Wie ich sagte: Ich habe das bei mir über den Dateinamen gelöst, weil ich beide Varianten brauche - die XP-Version, wenn ich das Programm bei mir laufen habe, und die andere, wenn es als Tool auf einem anderen Rechner ausgeführt werden soll (z.B. als Programm auf einer externen Festplatte an einem Party-Laptop).
Im Normalfall würde ich auch die Fassung empfehlen: Wenn möglich (d.h. Windows-Version gibt das her) ins Anwenderverzeichnis, ansonsten ins Programmverzeichnis. Und so kompliziert ist es nicht, die Version zu bestimmen. Ab und zu darf man auch mal Copy&Paste machen (und einmal grob über den Code gucken, was da in etwa passiert) ;-).
HelgeLange - Di 06.02.07 15:30
JayEff hat folgendes geschrieben: |
HelgeLange hat folgendes geschrieben: | Man weiss nicht, welche Windows-Version verwendet wird ? Kann man das neuerdings nicht mehr rausbekommen ? |
Doch schon, aber es ist .. kompliziert ... :( |
Ach, du weisst doch, es gibt keine Probleme beim Programmieren, nur Aufgaben ;)
JayEff - Di 06.02.07 15:55
Ist das ein Scherz, oder hälst du den Code für simpel? ^^
Ich denke, ich werd Sonderanfertigungen machen, solang ich nichts Kommerzielles mache. Und wenns kommerziel wird...: Hey! Die Computerspiel-Entwickler halten sich auch nicht an gängige Regeln! :roll:
jaenicke - Di 06.02.07 22:02
Ja, den Code halte ich für simpel...
Und in diesem Fall reicht ja auch die simple Abfrage ob NT-Reihe ab 2000 oder nicht. In dem von mir verlinkten Beispiel wird ja JEDE Version unterschieden.
Hier reicht ja das:
Delphi-Quelltext
1: 2: 3: 4:
| if (Win32Platform = VER_PLATFORM_WIN32_NT) and (Win32MajorVersion >= 5) then else |
JayEff - Di 06.02.07 22:08
jaenicke hat folgendes geschrieben: |
Ja, den Code halte ich für simpel... |
Ich nicht. Ich könnte mir das nie auswendig merken und kurz frei Hand tippen (meine Definition für simpel ;) )... :(
jaenicke - Di 06.02.07 22:12
Wenn das deine Definition ist, dann ist es für meine Begriffe eindeutig simpel. Ich könnte das nämlich... ;-)
Ich weiß ja welche Versionsnummern zu welcher Version gehören.
Aber zumindest die Unterscheidung zwischen 2000/XP/Vista und älteren Versionen ist ja hoffentlich auch in deinen Augen simpel. ;-)
HelgeLange - Di 06.02.07 22:15
und wozu überhaupt merken ? das schreibt man einmal (oder kopiert es sich eben) und dann hat man es... denkst Du, die MSDN-Library ist nur für die programmierer, die nicht bei Microschuft arbeiten? *kicher*
JayEff - Di 06.02.07 22:15
jaenicke hat folgendes geschrieben: |
Aber zumindest die Unterscheidung zwischen 2000/XP/Vista und älteren Versionen ist ja hoffentlich auch in deinen Augen simpel. ;-) |
Das ist so ein Code Snippet, das man sich merken sollte. klasse sache :)
Aber ich bin zu Faul zum auswendiglernen. vielleicht sollte ich mir dazu auch mal ein Programm wie meinen FULP schreiben... einen FUCS.. nein warte, das gabs schonmal ... :(
alzaimar - Di 06.02.07 23:16
??? JayEff: Du verwendest unzählige Routinen, die Du nicht geschrieben hast, und die auch nicht simpel sind. Kopier dir das Snippet in ein Unit, nenne sie 'JayTools' und jedesmal, wenn Du etwas kompliziertes aber Nützliches entdeckst, packst Du das auch in die Unit... Man, wenn Du nur Programmteile verwendest, die Du auswendig kannst, wie willst Du denn dann etwas dazulernen, also ehrlich...
JayEff - Di 06.02.07 23:18
Äh.. in .. dem ... ich ... die Programmteile .. lerne? :) Aber du hast das ganze eh falsch verstanden. Ich benutze einen Programmteil und versuche ihn dann soweit zu verstehen, dass ich ihn wiedergeben kann.
alzaimar - Mi 07.02.07 09:58
JayEff hat folgendes geschrieben: |
...Ich benutze einen Programmteil und versuche ihn dann soweit zu verstehen, dass ich ihn wiedergeben kann. |
:gruebel: Suboptimal, wenn Du mich fragst. Ich verwende die Win-API und könnte die zugrundeliegenden Routinen nicht wiedergeben. Aber ich hab Dich schon richtig verstanden.
Ich wollte Dich nur dezent drauf hinweisen, das Du dir hier vielleicht selbst im Weg stehst. :wink:
jaenicke - Mi 07.02.07 10:00
Die alte Aussage, dass man nicht alles wissen muss sondern nur wissen muss, wie oder wo man es findet, stimmt schon...
Ich kenne sicher nicht alle Befehle, die ich verwende, auswendig. Von Delphi selbst kenne ich natürlich auch sehr viele auswendig. Aber z.B. was die Win-API angeht da gibts einfach so viele, dass man die kaum alle auswendig können kann. Ich weiß aber, wo ich eine bestimmte API Funktion vermutlich finde.
Das reicht aber auch, denn das PSDK und MSDN kann man ja benutzen. Und in diesem Fall hier kenne ich zwar die Versionsnummern auswendig, aber das muss man nicht, denn die kann man jederzeit aus dem MSDN holen.
(Aber ich hatte bis vor 3 - 4 Monaten kein Internet zu Hause^^)
JayEff - Mi 07.02.07 18:32
Da habt ihr mich falsch verstanden, ich habs aber auch recht seltsam formuliert...
Ich meinte, dass ich am liebsten Code aus dem Handgelenk benutze, aber auch mal nachschlage (ist ja auch klar).
Meistens bin ich für sowas aber zu faul :P
Wie auch immer, dieses mal nicht. Ich habe eure Links und Vorschläge benutzt und in mein Programm
FULP eingebaut. Nun wird folgender Code beim Start des Programms ausgeführt:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44:
| isXP := (Win32Platform = VER_PLATFORM_WIN32_NT) And (Win32MajorVersion >= 5);
If isXP Then Begin path := GetSpecialFolder(CSIDL_APPDATA) + '\FULP Saved Data\'; If Not FileExists(path + 'urls.txt') Then Begin MkDir(path); URLs.Add('http://www.Delphi-Forum.de'); URLs.Add('http://www.christian-stelzmann.de/index_tutorials_crashkurs.html'); URLs.Add('http://www.google.de/');
LB.Items.Add('Delphi-Forum'); LB.Items.Add('Delphi Crashkurs, Christian S.'); LB.Items.Add('Google'); End; End Else path := ExtractFilePath(ParamStr(0));
urlsFile := path + 'urls.txt'; LabelFile := path + 'labels.txt';
Try ini := TIniFile.Create(path + 'config.ini');
If FileExists(urlsFile) Then URLs.LoadFromFile(urlsFile) Else URLs.SaveToFile(urlsFile);
If FileExists(LabelFile) Then LB.Items.LoadFromFile(LabelFile) Else URLs.SaveToFile(LabelFile); Except On E: Exception Do Begin MessageBox(Form1.Handle, PChar('Auf "' + path + '" konnte nicht zugegriffen werden. Nachricht:'#13#10 + E.Message), '"Speicherpfad wählen"', mb_OK); closeNow := True; close; End; End; |
Falls ihr etwas darin findet, was ihr nicht für optimal haltet, korrigiert das ruhig hier. Es ist nicht Off-Topic, da ich am ende des Threads den nach Möglichkeit optimalsten Code stehen haben will, falls mal jemand das gleiche Problem hat und auf diesen Thread stößt :D
jaenicke - Mi 07.02.07 18:52
Ich würde statt MkDir lieber CreateDir oder ForceDirectories nehmen und den Rückgabewert prüfen.
Die Funktionen geben zurück, ob das Verzeichnis erzeugt werden konnte (bzw. auch True, wenn es schon existiert).
Ich benutze immer diese Funktionen, weil sie zurückgeben ob das geklappt hat. Und ForceDirectories erstellt auch die gesamte Verzeichnishierarchie bei Bedarf. (Letzteres ist hier allerdings egal, weil die Oberverzeichnisse ja existieren.)
Ach so: Noch ein Unterschied: MkDir löst einen InOutError aus, während CreateDir und ForceDirectories lediglich den Misserfolg zurückmelden.
JayEff - Mi 07.02.07 18:56
Ah prima. Ich hab wegen dieser Prozedur einfach rumgespielt, mögliche Namen ausprobiert (makeDirectory makedir etc. ) bis kontexthilfe angezeigt wurde. Ich werd gleichmal CreateDir einbauen, wobei es mir lieber wäre, wenn ich wüsste, ob der Ordner bereits existiert hat. Gibts eine funktion ähnlich der FileExists für Ordner?
jaenicke - Mi 07.02.07 19:08
Ja, DirectoryExists... ;-)
JayEff - Mi 07.02.07 19:19
jaenicke hat folgendes geschrieben: |
DirectoryExists |
:oops:
Die Änderung im Code sieht nun so aus:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10:
| If Not DirectoryExists(path) Then Begin If Not CreateDirectory(PChar(path), Nil) Then Begin MessageBox(Form1.Handle, PChar('Auf "' + path + '" konnte nicht zugegriffen werden. Nachricht:'#13#10 + 'Ich weis leider nicht, warum. (provisorische Lösung ;) )'), '"Speicherpfad wählen"', mb_OK); closeNow := True; close; End; |
Gibt es eine Möglichkeit, vielleicht per GetLastError, heraus zufinden, warum die Funktion CreateDirectory False zurückliefert? Wenn ja, bekomme ich sicher auch noch raus, wie man GetLastError einsetzt und poste hier dann den perfektionierten Code ;)
Wenn nicht, werde ich den String mit "(provisorische Lösung)" halt weglassen müssen.
JayEff - Mi 07.02.07 19:54
Argh ja, C++.. die guten alten Zeiten. Ich habs nun so umgesetzt:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15:
| Function ErrorIDtoString(errID: Cardinal): String; Var p: PChar;
Const FormatControl = (FORMAT_MESSAGE_ALLOCATE_BUFFER Or FORMAT_MESSAGE_IGNORE_INSERTS Or FORMAT_MESSAGE_FROM_SYSTEM); Begin p := ''; If FormatMessage(FormatControl, Nil, errID, 0, @p, 0, Nil) <> 0 Then Result := String(p) Else Result := 'Unbekannter Fehler!'; End; |
Habe die Funktion mit
showmessage(ErrorIDtoString(ERROR_FILE_NOT_FOUND)); erfolgreich getestet.
Damit lautet mein Code wie folgt:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18:
| isXP := (Win32Platform = VER_PLATFORM_WIN32_NT) And (Win32MajorVersion >= 5); URLs := TStringList.Create; If isXP Then Begin path := GetSpecialFolder(CSIDL_APPDATA) + '\FULP Saved Data\'; If Not DirectoryExists(path) Then Begin If Not CreateDirectory(PChar(path), Nil) Then Begin MessageBox(Form1.Handle, PChar('Auf "' + path + '" konnte nicht zugegriffen werden. Nachricht:'#13#10 + ErrorIDtoString(GetLastError)), '"Speicherpfad wählen"', mb_OK); closeNow := True; close; End; End; End Else path := ExtractFilePath(ParamStr(0)); |
Edit: Der Pfad in dem die Einstellungen gespeichert werden sollen, steht am Ende dann in der Variable path drin.
GetSpecialFolder gibt's hier
http://www.delphi-library.de/topic_wie+kann+ich+spezielle+Ordner+finden_9428.html
rushifell - So 03.04.11 09:57
Hallo Leute,
ich grabe das alte Thema nochmal aus, da es für mich aktuell ist. Ich hoffe, das ist in Ordnung.
Am liebsten speichere ich die Dateien im Verzeichnis oder in Unterverzeichnissen der Anwendung, da ich gerne alle Daten zusammen halte und auch wieder alle zusammen restlos löschen kann.
Wäre es vielleicht nicht am besten, den Benutzer im Programm selbst festlegen zu lassen, wo er seine Daten gespeichert haben möchte? Eine Checkbox "Daten im Ordner der Anwendung speichern" würde reichen. Diese Einstellung wird z.B. in einer Ini-Datei am entsprechenden Ort gespeichert. Beim Neustart des Programms muss ich natürlich erstmal nach der ini-Datei suchen. Dafür überprüfe ich, ob die ini-Datei im Verzeichnis der Anwendung existiert. Ist dies nicht der Fall, dann suche ich im Ordner GetShellFolder(CSIDL_LOCAL_APPDATA). Wird dort auch nichts gefunden, wurden noch keine Daten gespeichert. Zuletzt könnte ich sogar noch den Wert der Variablen überprüfen und meckern, falls dieser falsch gesetzt ist. Was haltet ihr davon?
Das Problem ist, wenn ich meine Anwendung aus dem Ordner "C:\Program files" starte, und speichere, macht das Vista anstandslos, aber automatisch im Ordner "VirtualStore".
Generell könnte man doch einfach überprüfen, ob der Ordner, in dem sich die Anwendung befindet, ein Unterverzeichnis von "C:\Program files" ist, und dementsprechend die Voreinstellung festlegen!?
Gruß rushifell
Gausi - So 03.04.11 10:05
rushifell hat folgendes geschrieben : |
Generell könnte man doch einfach überprüfen, ob der Ordner, in dem sich die Anwendung befindet, ein Unterverzeichnis von "C:\Program files" ist, und dementsprechend die Voreinstellung festlegen!? |
Ja, das ist eine Möglichkeit. Auf 64Bit-Systemen gibt es allerdings zwei Verzeichnisse, die man da testen sollte. ich mach das mittlerweile so:
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14:
| function IsExeInProgramSubDir: Boolean; var p1: String; begin result := false; p1 := IncludeTrailingPathDelimiter(GetEnvironmentVariable('ProgramFiles')); if AnsiStartsText(p1, ParamStr(0)) then result := true else begin p1 := GetEnvironmentVariable('ProgramW6432'); if p1 <> '' then result := AnsiStartsText(IncludeTrailingPathDelimiter(p1), ParamStr(0)); end; end; |
rushifell - So 03.04.11 10:16
Danke Gausi,
das ist gut. Copy & Paste :oops:
jaenicke - So 03.04.11 10:41
Meine Lösung dazu sieht so aus:
Ich frage einfach den Benutzer, wenn ich nirgends Einstellungen finde. Einer der Vorteile ist, dass ich auch woanders hin installieren kann (wie es ja viele machen) und dennoch die Daten nicht einfach im eigenen Verzeichnis landen. Denn wenn dieses andere Verzeichnis (wie bei mir z.B.) auch nicht beschreibbar ist, gibts sonst wieder Probleme...
Dafür habe ich einfach ein paar Klassen geschrieben, die ich in meine Projekte eingebunden habe, so dass ich mich da nie wieder drum einzeln kümmern muss:
http://www.delphi-forum.de/viewtopic.php?t=92348
rushifell - Fr 08.04.11 16:40
Danke jaenicke. Wenn Deine Kompatibilitätsliste stimmt, brauch ich's damit jedoch gar nicht erst versuchen. Benutze Delphi2005.
Ich habs nun folgendermaßen geplant: Ich überprüfe, ob sich das Verzeichnis meiner Anwendung im Programme-Verzeichnis befindet. Ist dies nicht der Fall, so versuche ich, die Einstellungen im Ordner der Anwendung zu speichern. Ist dies nicht möglich, oder befindet sich meine Anwendung im Programme-Verzeichnis, so speichere ich unter GetShellFolder(CSIDL_LOCAL_APPDATA). Ist dies nicht möglich, halte ich die Möglichkeit offen, "manuell" eine Ini-Datei mit dem Speicherpfad im Ordner der Anwendung zu erstellen (letzteres müsste ja eigentlich möglich sein). Wobei das mit dem VirtualStore ja vielleicht auch nicht unbedingt verkehrt ist.
So viel Aufwand, nur um ein paar Einstellungen bzw. Daten zu speichern :-(
Delete - Fr 08.04.11 17:01
Meins:
Geht bei XP und WIN7
Delphi-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23:
| function SpecialDirectory(const iID: Integer): string; var aPath : array[0..MAX_PATH] of Char; pilTemp: PItemIDList; begin try if SHGetSpecialFolderLocation(0, iID, pilTemp)=S_OK then begin if SHGetPathFromIDList(pilTemp, aPath) then begin Result := string(aPath); end else Result := ''; CoTaskMemFree(pilTemp); end else Result := ''; except Result := ''; end; end;
function GetConfigPath: String; var AppDir: String; begin AppDir := SpecialDirectory(CSIDL_APPDATA)+'\DeinProgrammName'; if DirectoryExists(AppDir) = false then mkdir(AppDir); result := AppDir+'\'; end; |
jaenicke - Fr 08.04.11 17:16
rushifell hat folgendes geschrieben : |
Danke jaenicke. Wenn Deine Kompatibilitätsliste stimmt, brauch ich's damit jedoch gar nicht erst versuchen. Benutze Delphi2005. |
Dort habe ich es nicht getestet, weil ich das wegen der vielen Bugs weit von mir halte, aber es sollte da auch gehen. Die XML-Unterstützung musst du evtl. auch dort deaktivieren.
rushifell - So 10.04.11 16:41
Danke nochmal :-)
jaenicke hat folgendes geschrieben: |
Dort habe ich es nicht getestet, weil ich das wegen der vielen Bugs weit von mir halte, aber es sollte da auch gehen. Die XML-Unterstützung musst du evtl. auch dort deaktivieren. |
Gäbe es Delphi zu einem für Hobby-Programmierer vernünftigen Preis, von mir aus um die 100 Euro, so würde ich sofort zuschlagen.
Ich habs jetzt folgendermaßen gemacht. Weil für mich im Moment umständlich genug:
Beim Programmstart wird die ini-Datei gesucht, zuerst im Verzeichnis der Anwendung, dann im "gemeinsamen" Verzeichnis. Wird keine ini-Datei gefunden, so gehe ich davon aus, dass noch nie gespeichert wurde. Nun wird einfach gefragt, wo der Benutzer seine Daten gespeichert haben möchte. Zur Auswahl habe ich das Verzeichnis der Anwendung und ein Verzeichnis für gemeinsame Dateien. Wem beides nicht passt, kann ein eigenes Verzeichnis angeben (siehe unten).
Anschließend wird mit DirectoryExists und ForceDirectories das Vorhandensein der Verzeichnisstruktur bzw. ein mögliches Erstellen überprüft. ;-)
Wenn das fehlschlägt, gibts ne Fehlermeldung.
Ein eigenes Verzeichnis lasse ich folgendermaßen wählen. Der Benutzer muss manuell eine ini-Datei (oder Textdatei) mit dem Speicherpfad erstellen und diese Datei ins Verzeichnis der Anwendung kopieren. Letzteres ist zwar etwas umständlich und vielleicht etwas unkonventionell. Da es jedoch nur einmal durchgeführt werden muss, vielleicht auch zumutbar.
Eine andere Möglichkeit wäre, einfach irgendwo zu speichern und per FindFirst/FindNext nach den Dateien zu suchen. :wink: :twisted: :twisted:
Gruß
rushifell
jaenicke - So 10.04.11 17:10
rushifell hat folgendes geschrieben : |
Gäbe es Delphi zu einem für Hobby-Programmierer vernünftigen Preis, von mir aus um die 100 Euro, so würde ich sofort zuschlagen. |
So viel davon entfernt sind die 150€ für Delphi XE Starter ja nicht, die auch eine eingeschränkte kommerzielle Nutzung erlaubt. ;-)
Für ca. 100€ gibt es nur die Education Version, die keine Veröffentlichung der erstellten Programme zulässt.
rushifell hat folgendes geschrieben : |
Ein eigenes Verzeichnis lasse ich folgendermaßen wählen. Der Benutzer muss manuell eine ini-Datei (oder Textdatei) mit dem Speicherpfad erstellen und diese Datei ins Verzeichnis der Anwendung kopieren. |
Das kann dein Programm doch bei der Auswahl selbst machen, vorausgesetzt der Benutzer hat der Anwendung ggf. Adminrechte gegeben (oder du forderst diese an). ;-)
rushifell - So 10.04.11 20:27
jaenicke hat folgendes geschrieben: |
Das kann dein Programm doch bei der Auswahl selbst machen, vorausgesetzt der Benutzer hat der Anwendung ggf. Adminrechte gegeben (oder du forderst diese an). |
Und wie ist das möglich? Bei wird beim Versuch, im Programme-Verzeichnis zu speichern automatisch im VirtualStore gespeichert.
Danke für den Tipp mit Delphi XE Starter :-)
jaenicke - So 10.04.11 21:14
rushifell hat folgendes geschrieben : |
Und wie ist das möglich? Bei wird beim Versuch, im Programme-Verzeichnis zu speichern automatisch im VirtualStore gespeichert. |
Indem du deine eigene Exe mit ShellExecute und dem Verb runas erneut startest. Diese neue Instanz hat dann Adminrechte. Natürlich musst du auch die Parameter mitgeben, damit die neue Instanz weiß was sie tun soll. ;-)
rushifell hat folgendes geschrieben : |
Danke für den Tipp mit Delphi XE Starter :-) |
Hier gibt es dazu übrigens eine Review:
http://www.delphi-forum.de/delphi_xe_review.html
Und damit du es nicht übersiehst: Für den Upgradepreis ist keine vorher gekaufte Version von Delphi notwendig. ;-)
Entwickler-Ecke.de based on phpBB
Copyright 2002 - 2011 by Tino Teuber, Copyright 2011 - 2025 by Christian Stelzmann Alle Rechte vorbehalten.
Alle Beiträge stammen von dritten Personen und dürfen geltendes Recht nicht verletzen.
Entwickler-Ecke und die zugehörigen Webseiten distanzieren sich ausdrücklich von Fremdinhalten jeglicher Art!