Autor Beitrag
einsTeIn.NET
ontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic starofftopic star
Beiträge: 16



BeitragVerfasst: Di 04.11.03 16:50 
Tach zusammen!

Ich hab da mal eine kleine Frage: Es gibt hier ja ein sehr nützliches und auch wunderschönes, kleines Tutorial bzw. einen Tipp unter den FAQs, in dem erklärt wird wie man den Installationsordner von Windows bzw. das Systemverzeichnis herausfinden kann. Meistens braucht man ja genau diesen Pfad um ihn irgendwie weiter zu verwerten. Und genau dabei kann es zu Problemen kommen. Bei einer einfachen Ausgabe dieses Verzeichnis in einem Label oder sowas, ist das nicht so wild, weil die übrigen Zeichen eh nicht dargestellt werden... Aber ich fange wohl lieber vorne an: Ich glaube es ist von Tino und heißt.... ...das Windows- & das Systemverzeichnis bekommen?. Das ist soweit auch ganz klasse, allerdings seh ich da ein kleines Problemchen. Aber vielleicht seh ich das auch nur, weil ich was falsch verstanden hab, deshalb korrigiert mich bitte in meinem Gedankenfehler. :wink: Der Code ist in etwa folgender:
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
function GetWinDir: String;
var
  Size: DWORD;
begin
  Size := MAX_PATH + 1;
  SetLength(Result, Size);
  if GetWindowsDirectory(PChar(Result), Size) <> 0 then
    SetLength(Result, Size - 1)
  else
    Result := '';
end;

Man definiert sich eine Funktion und setzt die Größe auf die maximale Länge, die ein Pfadname im jeweiligen System haben darf (+1, wegen Terminierung), damit es zu keinem Überlauf kommen kann. (Das steht ja soweit auch in der OH drin, aber wenn man sich das mal genau überlegt, ist eine Festlegung auf die maximale Pfadlänge totaler Quatsch, weil zumindest bei Windows wenigstens noch die Ordner z.B. "Dokumente und Einstellungen\Lokale Einstellungen" oder "System32" dem Basispfad angefügt werden müssen und deshalb niemals die gesamte Länge durch den Systempfad alleine ausgefüllt sein kann. Aber safety first! :D ) Dann über GetWindowsDirectory den Pfad holen, das Terminierungsbit wieder entfernen und als Result zurückliefern.
Im Normalfall sollte das Ganze C:\Windows ergeben. Was passiert jetzt aber mit den restlichen Zeichen, denn wir hatten Result ja eine Länge von, ich glaube im 32Bit-Windows sind es 260+1 Zeichen (260 nutzbare) gegeben? Nun, dort bleibt dann einfach der Wert drin stehen, der vorher bereits an dieser Speicherstelle stand. Kann man ganz einfach sehen, indem man mal einShowmessage(Result);oder einShowmessage(inttostr(sizeof(Result)));einbaut. Normalerweise bekommt man dann einen ellenlangen String zurück, der außer dem C:\Windows noch nicht sichtbare Zeichen enthält. Es sind also nicht einfach nur Leerzeichen, sondern irgendwas. D.h. ein simplesResult := Trim(Result)bringt also auch nicht wirklich was, da ja immer noch andere nicht sichtbare Zeichen im String sind. Was kann man also dagegen machen? Denn, wenn man den zurückgelieferten String z.B. um einen bestimmten Pfad ergänzen möchte und in die Registry schreiben möchte,also z.B.RegVar.WriteString('',WinDir+'\System32\shell32.dll'), dann steht in dem Schlüssel nachher nur C:\Windows... drin, da ja die maximale Länge schon erreicht war. OK, man könnte WriteExpandString nehmen, aber das ist ja nur ein Beispiel.
Solution:
Wir füllen den String einfach vorher mit Leerzeichen auf und können diese dann nachher wieder abschneiden.
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
function GetWinDir: String;
var Size: DWORD;
begin
  Size := MAX_PATH + 1;
  SetLength(Result,Size);
  Result := StringOfChar(' ',MAX_PATH);
  if GetWindowsDirectory(PChar(Result),Size) <> 0 then begin
    SetLength(Result,Size - 1);
    Result := Trim(Result);
  end else
    Result := '';
end;


Ich hoffe, ich hab's so ausgedrückt, daß man es verstehen kann. :wink: Ansonsten nehme ich gerne Hinweise bzgl. des Verständnisses entgegen, auch falls ich was falsch verstanden hab. :wink:

_________________
greetingz,
earthlingz, we have now taken over your radioouooouoooo!
Motzi
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 2931

XP Prof, Vista Business
D6, D2k5-D2k7 je Prof
BeitragVerfasst: Di 04.11.03 22:20 
Du hast recht, aber das Problem lässt sich sehr einfach lösen:
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
function GetWinDir: String;
var
  Size: DWORD;
begin
  Size := MAX_PATH + 1;
  SetLength(Result, Size);
  if GetWindowsDirectory(PChar(Result), Size) <> 0 then
    SetLength(Result, StrLen(PChar(Result))
  else
    Result := '';
end;

StrLen gibt die Länge eines PChars zurück - da die Länge eines PChars durch das Nullzeichen bestimmt wird ist das in diesem Fall genau das was wir brauchen. Delphi-Strings sind zwar auch nullterminiert führen aber intern noch einen 32bit Längenzähler mit...

Es gäbe allerdings noch eine andere Möglichkeit, da GetWindowsDirectory die Länge des kopierten Strings zurückgibt. In diesem Fall kann man die Länge des Strings sogar erweitern falls er zu kurz ist...

_________________
gringo pussy cats - eef i see you i will pull your tail out by eets roots!
einsTeIn.NET Threadstarter
ontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic starofftopic star
Beiträge: 16



BeitragVerfasst: Mi 05.11.03 00:47 
Oder so! Ist natürlich noch einfacher, aber hab ich nicht dran gedacht. Aber dafür gibt's ja ein Forum, irgendeinen klugen Kopf findet sich da immer, der noch ne bessere Idee hat. :wink:

Das versteh ich allerdings nicht:
Zitat:
Es gäbe allerdings noch eine andere Möglichkeit, da GetWindowsDirectory die Länge des kopierten Strings zurückgibt. In diesem Fall kann man die Länge des Strings sogar erweitern falls er zu kurz ist...
In der Hilfe steht nichts davon, daß die Länge des kopierten Strings von GetWindowsDirectory zurückgeliefert wird. Gibt's da noch nen Trick?

_________________
greetingz,
earthlingz, we have now taken over your radioouooouoooo!
Luckie
Ehemaliges Mitglied
Erhaltene Danke: 1



BeitragVerfasst: Mi 05.11.03 05:29 
In dem man in der richtigen Hilfe nachkuckt. :wink:
Zitat:

If the function succeeds, the return value is the length of the string copied to the buffer, in TCHARs, not including the terminating null character.

msdn.microsoft.com/l...windowsdirectory.asp
Tino
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Veteran
Beiträge: 9839
Erhaltene Danke: 45

Windows 8.1
Delphi XE4
BeitragVerfasst: Mi 05.11.03 10:58 
Danke für den Hinweis. Hab den FAQ Sourcecode entsprechend geändert.

Gruß
Tino
Motzi
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 2931

XP Prof, Vista Business
D6, D2k5-D2k7 je Prof
BeitragVerfasst: Mi 05.11.03 11:36 
Luckie hat folgendes geschrieben:
In dem man in der richtigen Hilfe nachkuckt. :wink:
Zitat:

If the function succeeds, the return value is the length of the string copied to the buffer, in TCHARs, not including the terminating null character.

msdn.microsoft.com/l...windowsdirectory.asp

Genau.. und im Falle dass der Buffer zu klein ist:
MSDN hat folgendes geschrieben:
If the length is greater than the size of the buffer, the return value is the size of the buffer required to hold the path.

_________________
gringo pussy cats - eef i see you i will pull your tail out by eets roots!
einsTeIn.NET Threadstarter
ontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic starofftopic star
Beiträge: 16



BeitragVerfasst: Do 06.11.03 00:37 
@Tino: Bitte, bitte. Immer wieder gerne :D

Ach, die Hilfe meint ihr! Sollte man vielleicht mal öfter reinsehen. Das dauert nur immer viel länger, die Sachen auf englisch durchzuarbeiten :wink: Aber wie man sieht, bringt es auch was!


so, on this note

best regards

_________________
greetingz,
earthlingz, we have now taken over your radioouooouoooo!
Luckie
Ehemaliges Mitglied
Erhaltene Danke: 1



BeitragVerfasst: Do 06.11.03 04:19 
Und noch ein Weg:
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
function GetWinDir: String;
var
  len: DWORD;
  buffer: array[0..MAX_PATH] of Char;
begin
  len := GetWindowsDirectory(nil, 0);
  if len > 0 then
  begin
    GetWindowsDirectory(buffer, len);
    SetString(result, buffer, len);
  end
  else
    result := '';
end;


Und hier die Quick and Brite Methode von Nico:
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
function GetWinDir(): string;
begin
  SetLength(Result, MAX_PATH + 1);
  SetLength(Result, GetWindowsDirectory(PChar(Result), MAX_PATH));
end;
mimi
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 3458

Ubuntu, Win XP
Lazarus
BeitragVerfasst: Do 06.11.03 16:44 
den letzten weg verstehe ich nicht ganz:
wo wird result gestetzt ?

_________________
MFG
Michael Springwald, "kann kein englisch...."
Luckie
Ehemaliges Mitglied
Erhaltene Danke: 1



BeitragVerfasst: Do 06.11.03 17:15 
Na kuck doch, wo es im Quellcode auftaucht....
mimi
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 3458

Ubuntu, Win XP
Lazarus
BeitragVerfasst: Do 06.11.03 18:47 
aber da wird doch nur die länge fest gelegt, mehr doch nicht. und wo gibt er was zurück ???
oder wird bei:
SetLength(Result, GetWindowsDirectory(PChar(Result), MAX_PATH));
der wert reult schon gesetzt ?

_________________
MFG
Michael Springwald, "kann kein englisch...."
Motzi
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 2931

XP Prof, Vista Business
D6, D2k5-D2k7 je Prof
BeitragVerfasst: Do 06.11.03 20:29 
Die letzte Zeile macht alles in einem... GetWindowsDirectory legt den Pfad in der Variable Result ab und gibt die Anzahl der kopierten Zeichen zurück. Dieser Rückgabewert wird gleich ausgenutzt und an die Funktion SetLength weitergereicht, die die Variable Result auf die benötigte Anzahl an Zeichen zurückstutzt.

_________________
gringo pussy cats - eef i see you i will pull your tail out by eets roots!
mimi
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 3458

Ubuntu, Win XP
Lazarus
BeitragVerfasst: Do 06.11.03 20:48 
warum schwer, wenn es auch einfach geht *G*

_________________
MFG
Michael Springwald, "kann kein englisch...."