Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi Problem beim Ermitteln von Verzeichnissen über CSIDL (https://www.delphipraxis.net/93350-problem-beim-ermitteln-von-verzeichnissen-ueber-csidl.html)

Mazel 4. Jun 2007 18:40


Problem beim Ermitteln von Verzeichnissen über CSIDL
 
Hallo,

in MyPC ermittle mit folgender Funktion ein Verzeichnis:
Delphi-Quellcode:
function TMain.GetShellFolder(const CSIDL: Byte): String;
var
 PIDL          : PItemIdList;
 Malloc        : IMalloc;

begin
 if (SHGetMalloc(Malloc) = S_OK) and (SUCCEEDED(SHGetSpecialFolderLocation(Handle, CSIDL, PIDL))) then
  try
   SetLength(Result, MAX_PATH + 1);
   if (SHGetPathFromIDList(PIDL, PChar(Result))) and (PChar(Result) <> '') then Result := IncludeTrailingPathDelimiter(PChar(Result))
   else Result := '';
  finally
   Malloc.Free(pidl);
  end
 else Result := '';
end;
Zudem habe ich ein Array in dem verschiedene CSIDL's enthalten sind. Mein Programm listet diese auf und mit einem Doppelklick kann man diese schnell erreichen. Nun hat aber nicht jedes OS einen bestimmten Ordner, darum muss ich prüfen, ob das Verzeichnis existiert oder nicht. Nun wenn es vorhanden ist, soll es aufgelistet werden. Dies regle ich folgendermaßen:
Delphi-Quellcode:
If DirectoryExists(GetShellFolder(SHELL_CSIDL_DIRS[i])) then
    begin
     SysDirInfo[i].DirName := SHELL_STRING_DIRS[i];
     SysDirInfo[i].DirPath := GetShellFolder(SHELL_CSIDL_DIRS[i]);
     Inc(SysDirCounter);
    end;
Das Problem was hierbei entsteht ist, dass auf manchen Systemen "Geisterverzeichnisse" hinzukommen. Das heißt, eine Leerzeile wird im Programm angezeigt. Wenn man nun darauf einen Doppelklick macht, öffnet sich das Hauptverzeichnis (Root), von dem das Programm gestartet wird (C:\, D:\, etc). Danke an RWarnecke, dem das Phänomen aufgefallen ist. Wenn ein Leerstring zurückgegeben wird, muss doch DirectoryExists False zurückgeben und das Verzeichnis dürft nicht aufgenommen werden.

Was ist hier falsch?

Gruß
Mazel

Der_Unwissende 4. Jun 2007 19:39

Re: Problem beim Ermitteln von Verzeichnissen über CSIDL
 
Zitat:

Zitat von Mazel
Delphi-Quellcode:
If DirectoryExists(GetShellFolder(SHELL_CSIDL_DIRS[i])) then
    begin
     SysDirInfo[i].DirName := SHELL_STRING_DIRS[i];
     SysDirInfo[i].DirPath := GetShellFolder(SHELL_CSIDL_DIRS[i]);
     Inc(SysDirCounter);
    end;
Was ist hier falsch?

Hi,
sieht ein wenig so aus, als ob Du SysDirInfo[i] durch SysDirInfo[SysDirCounter] ersetzen solltest. Besser wäre vielleicht gleich auf eine TList zurückzugreifen.

Gruß Der Unwissende

RWarnecke 4. Jun 2007 19:56

Re: Problem beim Ermitteln von Verzeichnissen über CSIDL
 
Zitat:

Zitat von Mazel
Delphi-Quellcode:
function TMain.GetShellFolder(const CSIDL: Byte): String;
var
 PIDL          : PItemIdList;
 Malloc        : IMalloc;

begin
 if (SHGetMalloc(Malloc) = S_OK) and (SUCCEEDED(SHGetSpecialFolderLocation(Handle, CSIDL, PIDL))) then
  try
   SetLength(Result, MAX_PATH + 1);
   if (SHGetPathFromIDList(PIDL, PChar(Result))) and (PChar(Result) <> '') then Result := IncludeTrailingPathDelimiter(PChar(Result))
   else Result := '';
  finally
   Malloc.Free(pidl);
  end
 else Result := '';
end;

Ich würde das result ändern, dass kein Leer String zurückkomt sondern eine Antwort wie "kein Verzeichnis gefunden". Damit könntest Du zumindext die IF-Abfrage mit Directory-Exists überlisten.

Wo wird i erhöht und initialisiert ?

Mazel 4. Jun 2007 20:27

Re: Problem beim Ermitteln von Verzeichnissen über CSIDL
 
@Der_Unwissende:
Ich habe vorhin vergessen die Variablen anzugeben. I steht für die Schleifenvaraible um auf das entsprechende Element im Array zuzugreifen und nur wenn das Verzeichnis existiert wird SysDirCounter erhöht um in der Anzeige dann nur die die mögliche Anzahl anzuzeigen.

@RWarnecke:
Meinst du dass DirectoryExists ein Leerstring falsch versteht? Wenn ja müsste er mir auch das Element aus dem Array anzeigen, tut es aber nicht. Also angenommen i = 5 und das Verzeichnis welches ich nachschaue existiert nicht aber DirectoryExists gibt trotzdem True zurück müsste es mir auch das Element 5 im Array anzeigen, aber du weist ja, dass es Leer ist.

Ich kann mir nicht erklären was da passiert.

Der_Unwissende 4. Jun 2007 20:32

Re: Problem beim Ermitteln von Verzeichnissen über CSIDL
 
Zitat:

Zitat von Mazel
@Der_Unwissende:
Ich habe vorhin vergessen die Variablen anzugeben. I steht für die Schleifenvaraible um auf das entsprechende Element im Array zuzugreifen und nur wenn das Verzeichnis existiert wird SysDirCounter erhöht um in der Anzeige dann nur die die mögliche Anzahl anzuzeigen.

Ich kann mir nicht erklären was da passiert.

Du erklärst es imho hier. Sagen wir Du möchtest aus 10 Ordnern nur die Speichern, die Deine Bedingung erfüllen. Also legst Du ein Array der Größe 10 an und alle Eintrage sind erstmal nicht initialisiert (Verzeichnis mit Glück der leere String). Nun läufst Du in einer Schleife über die 10 Ordner und prüfst für jeden, ob er die Bedingung erfüllt. Bei denen, bei denen das der Fall ist änderst Du das Verzeichnis, die anderen bleiben auf dem nicht initialisierten Wert (hier zufällig der leere String).
Versuche es mal so:
Delphi-Quellcode:
If DirectoryExists(GetShellFolder(SHELL_CSIDL_DIRS[i])) then
begin
  SysDirInfo[SysDirCounter].DirName := SHELL_STRING_DIRS[i];
  SysDirInfo[SysDirCounter].DirPath := GetShellFolder(SHELL_CSIDL_DIRS[i]);
  Inc(SysDirCounter);
end;

setLength(SysDirInfo, SysDirCounter);

Mazel 11. Jun 2007 12:44

Re: Problem beim Ermitteln von Verzeichnissen über CSIDL
 
Das Problem scheint gelöst zu sein. Ich bin mir nicht sicher was nun der Grund war, aber durch verschiedene Lösungen habe ich den Code so geändert dass es jetzt fubktioniert, genaueres kann ich nicht sagen, da ich die Änderungen nicht zurückverfolgen kann.

Danke an alle. :)

Gruß
Mazel


Alle Zeitangaben in WEZ +1. Es ist jetzt 01:59 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