Delphi-PRAXiS
Seite 3 von 4     123 4      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi Application Path (https://www.delphipraxis.net/72638-application-path.html)

himitsu 7. Okt 2013 19:09

AW: Application Path
 
Zitat:

Zitat von Der schöne Günther (Beitrag 1231071)
Kommen wir nochmal zu den "Datei öffnen"-Dialogen zurück. Die sind bislang aber auch die einzige Ausnahme, oder?

Nöö.
Auch die "Art" des Aufrufs/Starts des Programms ist entscheidend.


Im Prinzip kann einem das bei vielen (Fremd)Komponenten/-Codes passieren, welche mit Zugriffen auf die Festplatte arbeiten.

Grundsätzlich muß sollte man so sowieso immer davon ausgehen, daß "externe" Einstellung/Daten nicht als gegeben/konstant angesehen werden können.

Gutelo 7. Okt 2013 19:37

AW: Application Path
 
hmm, irgendwie beisst sich die Katze doch in den eigenen Schwanz. Entweder verzichtet man auf die Verwendung des "hardkodierten Pfades" und kann das Programm ueberhaupt nicht mehr Verschieben nach der Installation, oder man verwendet Sie mit der Gefahr dass sich der Wert der Variablen aendert. Letzteres impliziert dass man jedes Mal oben angesprochene Sicherheitsabfragen durchfuehren muss und gegebenenfalls darauf angewiesen ist den gesammten Verzeichnisbaum des Laufwerks zu durchsuchen.

Es ist Aufgabe von Embacedero sicherzustellen dass diese Funktion macht was Sie machen soll. Ehrlichgesagt sollte es simpel sein das Verzeichnis bei Ausfuehren des Programms so zu speichern dass der Wert durch andere Operationen nicht veraendert wird. Klingt eher wie ein Major Bug in Delphi.

himitsu 7. Okt 2013 20:07

AW: Application Path
 
Nein.

relative Pfade sind böse
und
hardcodierte Pfade genauso
(vorwie aus dem Grund, weil es bescheuerte Programmierer gab, welche Pfade hardcodierten, spricht das Verzeichnissystem nun englisch und der Benutzer sieht aber was Anderes)

Man fragt Windows nach den benötigten Verzeichnissen und verwendet diese für die Zugriffe mit den resulierenden absoluten Pfaden.


Es ist nicht die aufgabe von Embarcadero.
Ganz im Gegenteil.
Das ist ein normales Verhalten seitens des Betriebssystems.
Vorallem das Verhalten, daß bei Programmstart das Arbeitsverzeichnis nicht dem Programmverzeichnis entsprechen muß.

Der schöne Günther 7. Okt 2013 20:48

AW: Application Path
 
Zitat:

Zitat von himitsu (Beitrag 1231074)
Auch die "Art" des Aufrufs/Starts des Programms ist entscheidend.

Das ist glaube ich jedem klar.

Aber:
Zitat:

Zitat von himitsu (Beitrag 1231074)
Im Prinzip kann einem das bei vielen (Fremd)Komponenten/-Codes passieren, welche mit Zugriffen auf die Festplatte arbeiten.

Genau das wollte ich wissen ;-) Gibt es denn bekannte Fälle?

Im Endeffekt bin ich nur faul und würde gerne wissen, ob ich weiterhin ruhig schlafen kann oder die Sache doch möglichst bald angehen sollte: Bislang habe hole mir oft dynamisch das Arbeitsverzeichnis (ohne es je selbst zu ändern) und bastele mir damit dann eine absolute Pfadangabe zusammen. Wenn mir nun irgendetwas ohne mein Wissen das Arbeitsverzeichnis ändert ist das natürlich nicht nett :pale:

jaenicke 7. Okt 2013 20:52

AW: Application Path
 
Zitat:

Zitat von Gutelo (Beitrag 1231079)
Es ist Aufgabe von Embacedero sicherzustellen dass diese Funktion macht was Sie machen soll. Ehrlichgesagt sollte es simpel sein das Verzeichnis bei Ausfuehren des Programms so zu speichern dass der Wert durch andere Operationen nicht veraendert wird.

Du hast einmal das Anwendungsverzeichnis (Application.ExeName oder ParamStr(0)) und du hast einmal das aktuelle Arbeitsverzeichnis (GetCurrentDir). Das ist nun einmal nicht das gleiche.

Der Fehler liegt nicht in Delphi oder bei Embarcadero, wenn diese Funktionen falsch benutzt werden...

// EDIT:
Zitat:

Zitat von Der schöne Günther (Beitrag 1231089)
Genau das wollte ich wissen ;-) Gibt es denn bekannte Fälle?

Datenbankzugriffskomponenten, Fremddialoge, ...
Da gibt es einige Möglichkeiten.

Zitat:

Zitat von Der schöne Günther (Beitrag 1231089)
Bislang habe hole mir oft dynamisch das Arbeitsverzeichnis (ohne es je selbst zu ändern) und bastele mir damit dann eine absolute Pfadangabe zusammen.

Solange du damit auch das aktuelle Arbeitsverzeichnis ansprechen willst und nicht das Verzeichnis der Anwendung ist doch alles in Ordnung.

Perlsau 8. Okt 2013 05:30

Zusammenfassung
 
Da bei einigen offenbar rege Begriffsverwirrung herrscht, möchte ich das bisher Gesagte noch einmal zusammenfassen:

Das Anwendungsverzeichnis ändert sich nicht, während das Programm läuft:
Delphi-Quellcode:
Anwendungsverzeichnis := SysUtils.ExtractFilePath(System.ParamStr(0));
Anwendungsverzeichnis := SysUtils.ExtractFilePath(Forms.Application.ExeName);
Das Arbeitsverzeichnis kann sich während des Programmlaufs jedoch ändern, z.B. durch einen Aufruf von OpenDialg oder SaveDialog:
Delphi-Quellcode:

Arbeitsverzeichnis := SysUtils.GetCurrentDir;
Wenn ich im Programm ein festes Verzeichnis benötige, das sich nicht ändern soll, dann lege ich dieses Verzeichnsi beim Programmstart fest, z.B. den Ort, an dem die benötigte Firebird-Datenbank zu finden ist:
Delphi-Quellcode:
Const
  DB_Datei = 'MeineDatenbank.FDB';
Var
  DB_DateiName,
  DB_DateiPfad : String;
Diesen Speicherort ermittle ich entweder durch einen OpenDialog oder lege ihn in einer Ini-Datei fest (das kann auch ein einfaches Ascii-File mit nur einer Zeile sein). Diese Ini-Datei speichere ich nur dann im Anwendungsverzeichnis, wenn

1. sie nicht vom Programm verändert zurückgeschrieben werden soll und/oder
2. es sich um eine portable Anwendung handelt, die sich nicht in einem der Windows-Systemordner befindet.

Ansonsten speichert man Ini-Dateien (und andere, die man benötigt) im Benutzer-Verzeichns, und zwar bei:

WinXP entweder unter \AllUsers\Anwendungsdaten oder \[CurrentUser]\Anwendungsdaten
Win7 entweder unter \Users\Public\Documents\MeineAnwendungsDaten\ oder entsprechend unter \Users\[CurrentUser]\
Win 8 weiß ich nicht, hab ich nicht ...

Oder man setzt entsprechende Registry-Einträge und erfährt dann aus der Registry alle notwendigen festen Verzeichnisse.

hathor 8. Okt 2013 07:13

AW: Application Path
 
WIN 8:

Delphi-Quellcode:
uses
  ActiveX, ShlObj;

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)+'\ProgName';
  if DirectoryExists(AppDir) = false then mkdir(AppDir);
    result := AppDir+'\';
end;

//ergibt: C:\Users\HATHOR\AppData\Roaming\ProgName\
Hinweis:
Über den WIN8-Explorer kommt man nur hin, wenn man
C:\Users\HATHOR\AppData\Roaming\ProgName\
direkt in die Adresszeile eingibt.


Alternativ: Im Explorer - Ansicht - Häkchen bei Ausgeblendete Elemente

Furtbichler 8. Okt 2013 07:23

AW: Application Path
 
Und davor (rausgeschnibbelt aus einer größeren Unit)

Delphi-Quellcode:
unit SettingsPaths;

interface
Function LocalUserFilesPath: String;
Function LocalAppDataPath(AppName: String): String;
Function AppDataPath(AppName: String): String;
implementation
Uses sysutils,windows,ShlObj, ActiveX;
Function GetSpecialFolderLocation(csidl: integer): String;
Var
  pMalloc: IMalloc;
  pidl: PItemIDList;
  path: Array[0..MAX_PATH] Of Char;
Begin
  Result := '?';
  If SHGetMalloc(pMalloc) = S_OK Then Begin
    SHGetSpecialFolderLocation(0, csidl, pidl);
    SHGetPathFromIDList(pidl, path);
    Result := IncludeTrailingPathDelimiter(Path);
    pMalloc.Free(pidl);
  End;
End;

Function LocalUserFilesPath: String;
Begin
  Result := IncludeTrailingPathDelimiter(GetSpecialFolderLocation(CSIDL_PERSONAL));
End;

Function LocalAppDataPath(AppName: String): String;
Begin
  Result := IncludeTrailingPathDelimiter(GetSpecialFolderLocation(CSIDL_LOCAL_APPDATA));
  Result := IncludeTrailingPathDelimiter(Result + AppName);
  ForceDirectories(Result)
End;

Function AppDataPath(AppName: String): String;
Begin
  Result := IncludeTrailingPathDelimiter(GetSpecialFolderLocation(CSIDL_APPDATA));
  Result := IncludeTrailingPathDelimiter(Result + AppName);
  ForceDirectories(Result)
End;
end.
So, und wer jetzt seine INI ins Programmverzeichnis schmeißt, wird geteert und gefeedert (mit Doppel-E!). :mrgreen:

DeddyH 8. Okt 2013 07:24

AW: Application Path
 
SHGetSpecialFolderLocation
Zitat:

[SHGetSpecialFolderLocation is not supported and may be altered or unavailable in the future. Instead, use SHGetFolderLocation.]
Das führt dann zu SHGetFolderLocation
Zitat:

Deprecated. Retrieves the path of a folder as an ITEMIDLIST structure.
Alternativ kann man dann auf SHGetFolderPath zurückgreifen, aber
Zitat:

Deprecated. Gets the path of a folder identified by a CSIDL value.
Was einen dann letztendlich zu SHGetKnownFolderPath führt.
Einziger Haken:
Zitat:

Minimum supported client
Windows Vista [desktop apps only]
Daher greife ich persönlich derzeit auf SHGetFolderPath zurück, dazu braucht man nur die Unit SHFolder, und einfacher zu handhaben (und nicht ganz so veraltet wie die erstgenannten) ist sie auch noch.

Furtbichler 8. Okt 2013 07:32

AW: Application Path
 
Oh, nie drauf geachtet.


Alle Zeitangaben in WEZ +1. Es ist jetzt 19:36 Uhr.
Seite 3 von 4     123 4      

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz