Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Programmieren allgemein (https://www.delphipraxis.net/40-programmieren-allgemein/)
-   -   Funktion zum auflösen von Pfaden mit Umgebungsvariablen? (https://www.delphipraxis.net/170810-funktion-zum-aufloesen-von-pfaden-mit-umgebungsvariablen.html)

Popov 4. Okt 2012 06:14

Funktion zum auflösen von Pfaden mit Umgebungsvariablen?
 
Die Funktion GetEnvironmentVariable ist mir bekannt.

Bevor ich jedoch gleiche eine Funktion bastle die einen Pfad mit Umgebungsvariablen (z. B. "%USERPROFILE%\SendTo") auflöst, wollte ich fragen ob es bereits etwas fertiges gibt.

Und wenn wir schon dabei sind, vielleicht gibt es auch eine Funktion die automatisch aus normalen Pfaden einen Pfad mit Umgebungsvariablen erstellt.

Wie gesagt, nur eine Frage.

daywalker9 4. Okt 2012 06:39

AW: Funktion zum auflösen von Pfaden mit Umgebungsvariablen?
 
Hier im Forum suchenExpandEnvironmentStrings

Bummi 4. Okt 2012 06:42

AW: Funktion zum auflösen von Pfaden mit Umgebungsvariablen?
 
Delphi-Quellcode:
ExpandEnvironmentStrings('%USERPROFILE%\SendTo',Pchar(s),Length(s));

s.h.a.r.k 4. Okt 2012 06:48

AW: Funktion zum auflösen von Pfaden mit Umgebungsvariablen?
 
Zitat:

Zitat von Popov (Beitrag 1185606)
Und wenn wir schon dabei sind, vielleicht gibt es auch eine Funktion die automatisch aus normalen Pfaden einen Pfad mit Umgebungsvariablen erstellt.

PathUnExpandEnvStrings

Popov 4. Okt 2012 15:30

AW: Funktion zum auflösen von Pfaden mit Umgebungsvariablen?
 
Vielen Dank. Irgendwie hatte ich da die richtige Vermutung.

Zitat:

Zitat von daywalker9 (Beitrag 1185607)

Ich komme mit der Funktion nicht 100% klar, bzw. verstehe sie nicht in allen Einzelheiten. Mein Englisch ist verbesserungswürdig, aber was ich aus der MSDN Hilfe herauslesen kann ist, dass im Erfolgsfall die Funktion die Anzahl der nötigen Zeichen (inc. Nullzeichen) zurück gibt. Das gleiche (?) passiert wenn der String für den Rückgabewert zu klein dimensioniert ist. Beim Fehler gibt es als Rückgabe 0.

Wie soll man die Funktion nun verstehen? Zuerst die Funktion auf gut Glück ausführen um zu gucken ob alles ok ist, wenn nicht, dann ein zweites Mal mit den richtigen Werten?

Uwe Raabe 4. Okt 2012 15:36

AW: Funktion zum auflösen von Pfaden mit Umgebungsvariablen?
 
Zitat:

Zitat von Popov (Beitrag 1185722)
Wie soll man die Funktion nun verstehen? Zuerst die Funktion auf gut Glück ausführen um zu gucken ob alles ok ist, wenn nicht, dann ein zweites Mal mit den richtigen Werten?

Nicht auf gut Glück. Erst mit nSize = 0 und lpDst = nil und damit die benötigte Größe ermitteln. Dann den passenden Puffer allokieren und mit den korrekten Werten nochmal übergeben um das Ergebnis zu bekommen.

Popov 4. Okt 2012 15:45

AW: Funktion zum auflösen von Pfaden mit Umgebungsvariablen?
 
Ok, das mit dem "auf gut Glück" war etwas übertrieben formuliert, aber ist das tatsächlich so gedacht? Interessante Methode.

DeddyH 4. Okt 2012 15:46

AW: Funktion zum auflösen von Pfaden mit Umgebungsvariablen?
 
Das gibt es in der Win32-API immer wieder mal.

Jumpy 4. Okt 2012 15:50

AW: Funktion zum auflösen von Pfaden mit Umgebungsvariablen?
 
Aber das ist doch bei einigen API-Funktionen so, das man einen Buffer übergibt und z.B. ein Word? Der Buffer enthält dann soviel Inhalt wie reinpasste und die Word-Variable die Info, wie groß der Buffer hätte sein sollen.
Manchmal weiß man ja ungefähr wieviel zurückkommt, dann kann man dann direkt beim ersten mal einen großzügig bemessenen Buffer bereitstellen und dann diesen dann später nur bis zur benötigten/angegebenen Länge auslesen.

DeddyH 4. Okt 2012 16:34

AW: Funktion zum auflösen von Pfaden mit Umgebungsvariablen?
 
Ja, aber wozu einen "zu großen" Puffer deklarieren, wenn man die tatsächlich benötigte Größe vorher ermitteln kann?

Popov 4. Okt 2012 17:10

AW: Funktion zum auflösen von Pfaden mit Umgebungsvariablen?
 
Trotz dem eine interessante Methode.

Wie gesagt, mein Englisch ist verbesserungswürdig. Nun habe ich mich der PathUnExpandEnvStrings Funktion gewidmet. Kann man über eine Unit drauf zugreifen? Weiß das einer?

Bummi 4. Okt 2012 17:19

AW: Funktion zum auflösen von Pfaden mit Umgebungsvariablen?
 
Delphi-Quellcode:
unit Path_Utils;
// Thomas Wassermann (Bummi)
interface
uses Windows;


Function ExpandEnvironmentStrings_D(Const s:String):String;
Function PathUnExpandEnvStrings_D(Const s:String):String;
{$IFDEF UNICODE}
Function PathUnExpandEnvStrings(pszPath, pszBuf: PChar; cchBuf: UINT): BOOL; stdcall;
{$ELSE}
Function PathUnExpandEnvStrings(pszPath, pszBuf: PChar; cchBuf: UINT): BOOL; stdcall;
{$ENDIF}



implementation
{$IFDEF UNICODE}
Function PathUnExpandEnvStrings; External 'shlwapi.dll' Name 'PathUnExpandEnvStringsW';
{$ELSE}
Function PathUnExpandEnvStrings; External 'shlwapi.dll' Name 'PathUnExpandEnvStringsA';
{$ENDIF}



Function ExpandEnvironmentStrings_D(Const s:String):String;
begin
  SetLength(Result,ExpandEnvironmentStrings(PChar(s),Pchar(Result),0));
  ExpandEnvironmentStrings(Pchar(s),Pchar(Result),Length(Result));
end;

Function PathUnExpandEnvStrings_D(Const s:String):String;
var
 i:Integer;
begin
  SetLength(Result,MAX_PATH);
  PathUnExpandEnvStrings(PChar(s),Pchar(Result),MAX_PATH);
  Result := PChar(Result);
end;

end.

Popov 4. Okt 2012 17:33

AW: Funktion zum auflösen von Pfaden mit Umgebungsvariablen?
 
Danke. Hab gerade mit den Hausmitteln eine Alternative gebastelt, aber ich glaube deine Unit ist besser.

Delphi-Quellcode:
var
  EnvStrings: array[0..6] of String = ('ALLUSERSPROFILE', 'APPDATA', 'TEMP',
    'COMMONPROGRAMFILES', 'PROGRAMFILES', 'SYSTEMROOT', 'USERPROFILE');

function PathUnExpandEnvStrings2(Path: String): String;
var
  i, p: Integer;
  s: String;
begin
  Result := Path;

  for i := Low(EnvStrings) to High(EnvStrings) do
  begin
    p := Pos(UpperCase(GetEnvironmentVariable(EnvStrings[i])), UpperCase(Path));

    if p > 0 then
    begin
      Delete(Result, p, Length(GetEnvironmentVariable(EnvStrings[i])));
      Insert('%'+EnvStrings[i]+'%', Result, p);
      Exit;
    end;
  end;
end;
Ich glaube ich nehme deine Unit, die beinhaltet ja gleich beide Funktionen.

shmia 4. Okt 2012 18:57

AW: Funktion zum auflösen von Pfaden mit Umgebungsvariablen?
 
Die JCL macht das so (Unit JclSysInfo).
Auch keine schlechte Lösung; über den boolschen Resultwert erfährt man ob etwas expandiert wurde.
Delphi-Quellcode:
function ExpandEnvironmentVar(var Value: string): Boolean;
var
  R: Integer;
  Expanded: string;
begin
  SetLength(Expanded, 1);
  R := ExpandEnvironmentStrings(PChar(Value), PChar(Expanded), 0);
  SetLength(Expanded, R);
  Result := ExpandEnvironmentStrings(PChar(Value), PChar(Expanded), R) <> 0;
  if Result then
  begin
    StrResetLength(Expanded);
    Value := Expanded;
  end;
end;

himitsu 4. Okt 2012 19:22

AW: Funktion zum auflösen von Pfaden mit Umgebungsvariablen?
 
Nur daß der von der JCL wohl auch nicht wirklich Ahnung hatte.

himitsu 4. Okt 2012 20:09

AW: Funktion zum auflösen von Pfaden mit Umgebungsvariablen?
 
Oder wieso findete man das
Delphi-Quellcode:
SetLength(Expanded, 1);
dort?

Nja, und dann soll laut MSDN die ANSI-Version einen Bug haben (auch wenn er wohl spätestens im Win7 schon nicht mehr vorhanden zu sein scheint),
wonach dort der Buffer ein Byte größer sein muß.

Variante 1 nach MSDN-Vorgaben und möglichst direkt in den Zielpuffer (Result-String).
OK, abgesehn von dem Bugfix für's ANSI, aber FastMM wird die Speicherverwaltung optimieren und zu mindestens 99% nichts umkopieren.
Delphi-Quellcode:
function ExpandEnvironmentVars(var Value: string): Boolean;
var
  R: Integer;
  Expanded: string;
begin
  R := ExpandEnvironmentStrings(PChar(Value), nil, 0);
  if R = 0 then
    Exit(False);
  {$IFDEF UNICODE}
  SetLength(Expanded, R - 1);
  Result := ExpandEnvironmentStrings(PChar(Value), PChar(Expanded), R) = R;
  {$ELSE}
  SetLength(Expanded, R);
  Result := ExpandEnvironmentStrings(PChar(Value), PChar(Expanded), R + 1) = R;
  SetLength(Expanded, R - 1);
  {$ENDIF}
  if Result then
    Value := Expanded;
end;
Variante 1 ohne den Bugfix (für aktuellere Windowse):
Delphi-Quellcode:
function ExpandEnvironmentVars(var Value: string): Boolean;
var
  R: Integer;
  Expanded: string;
begin
  R := ExpandEnvironmentStrings(PChar(Value), nil, 0);
  if R = 0 then
    Exit(False);
  SetLength(Expanded, R - 1);
  Result := ExpandEnvironmentStrings(PChar(Value), PChar(Expanded), R) = R;
  if Result then
    Value := Expanded;
end;
Variante 2 inkl. Bugfix und mit Zwischenpuffer auf'm Stack.
Delphi-Quellcode:
function ExpandEnvironmentVars(var Value: string): Boolean;
var
  Buffer: array[0..MAX_PATH] of Char; // maximal 32 KB
  R: Integer;
begin
  R := ExpandEnvironmentStrings(PChar(Value), @Buffer, MAX_PATH {$IFDEF UNICODE}+ 1{$ENDIF});
  Result := (R > 0) and (R < MAX_PATH);
  if Result then
    SetString(Value, Buffer, R - 1);
end;
Da man die Umkehrfunktion sowieso nach Variante 2 bauen muß, könnte man Beides nach der gleichen Version deklarieren. (vorallem da es sich positiv auf den Bugfix auswirkt)


Alle Zeitangaben in WEZ +1. Es ist jetzt 14:02 Uhr.

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