Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   GUI-Design mit VCL / FireMonkey / Common Controls (https://www.delphipraxis.net/18-gui-design-mit-vcl-firemonkey-common-controls/)
-   -   Delphi ParamStr ParamStr(0), Bildschirmschoner und lange Dateinamen (https://www.delphipraxis.net/168534-paramstr-paramstr-0-bildschirmschoner-und-lange-dateinamen.html)

Delphi-Laie 27. Mai 2012 17:56


ParamStr ParamStr(0), Bildschirmschoner und lange Dateinamen
 
Hallo Delphisten!

Zum ersten Male in meinem Leben verwandte ich Ini-Dateinamen. Als Relikt aus den Win3.x-Zeiten sind es Totgesagte, die deutlich länger als erwartet leben, und es erstaunte mich mithin auch nicht, daß das Programm (mit langem Exe-Dateinamen) eine korrespondierende Ini-Datei mit einer Tilde im Dateinamen anlegte - zumindest unter Windows 2000. Dasselbe Programm auf dem letzten Mohikaner meiner 9.x-Windows (konkret ME) ausgeführt, und ich kam aus dem Staunen so schnell nicht wieder heraus: Eine Ini-Datei mit komplettem langem Dateinamen wie der Dateiname der erzeugenden Exe-Datei, nur eben mit anderem Parameter (eben ini statt exe), wurde angelegt - ausgerechnet bei einem Betriebsprogramm, dem vom Alter her bald die Weihe in das Erwachsenendasein bevorsteht. Überflüssig, daß auch korrekt aus dieser Datei gelesen bzw. in diese geschrieben wurde, was aber auch unter Windows 2000 so war.

Es war zudem ein Delphi-2.0-Compilat.

Also kann TIniFile schon bei Delphi 2.0 eben doch grundsätzlich Dateien mit langem Namen anlegen und auch damit korrekt umgehen!

Nun vermute ich wegen der 2000er-Erfahrung, daß es unter NTx generell nicht funktioniert.

Weiß jemand, ob und, falls ja, wie man TIniFile den generellen Umgang mit langen Dateinamen beibringen kann?

Dank und Gruß

Delphi-Laie

himitsu 27. Mai 2012 18:11

AW: IniFile TIniFile und lange Dateinamen
 
Wie hieß die EXE und der Pfad?

Wenn es z.B. Probleme mit Unicode-Zeichen gibt, dann weißt die ANSI-WinAPI auf den alternativen kurzen Dateinamen aus.

Grundsätzlich versteht API lange Dateinamen.
Aber wenn die Datei schon existiert, dann kann man auch problemlos über den kurzen Namen gehn.
(geht natürlich nicht beim Anlegen einer Datei)

Delphi-Laie 27. Mai 2012 18:21

AW: IniFile TIniFile und lange Dateinamen
 
Deine Antwort war der Anstoß, aus einer anderen Richtung die Sache zu betrachten.

Der Fehler muß woanders liegen, und zwar daran, daß der Dateiname mit der verwandten Funktion aus dem Programmnamen nicht richtig extrahiert wird, es war nämlich, mein Irrtum, eine Bildschrimschonerdatei mit dem Parameter ".scr". Mit ".exe" klappte es auch auf Windows 2000 mit dem langen Dateinamen. Komisch eben nur, unter ME klappt es auch mit der scr-Programmdatei.

Ich danke Dir!

Delphi-Laie 27. Mai 2012 22:06

AW: IniFile TIniFile und lange Dateinamen
 
Also, die Sache weiterverfolgt: (T)Inifile ist völlig unschuldig. Die Ursache liegt darin, daß Paramstr(0) nur einen kurzen Dateinamen zurückliefert, wenn der Bildschirmschoner im Windows- oder im untergeordneten System32-Verzeichnis liegt. Das passiert aber nur, wenn der Bildschirmschoner vom Fenster "Eigenschaften von Anzeige" aufgerufen wird, wie es gewöhnlich ja auch sein soll. Wird er über die Kommandozeile des Eingabeaufforderungsfensters (Konsole) gestartet, auch wenn er sich am richtigen Ort (also in einem bzw. jedem der genannten Verzeichnisse) befindet, so liefert Paramstr(0) den "korrekteren" - nämlich den langen - Dateinamen zurück. Rätselhaft...

Edit: Hiermit funktioniert es zum Glück. Rätselhaft, warum beim Aufrufen der Bildschrimschoner von besagtem Fenster aus seitens Paramstr dateisystemisch in die DOS-Zeit zurückgeschaltet wird.

Luckie 27. Mai 2012 22:34

AW: IniFile TIniFile und lange Dateinamen
 
Sind Leerzeichen im Pfad? Und wenn ja, was passiert, wenn du ihn in Anführungszeichen setzt?

Delphi-Laie 27. Mai 2012 22:51

AW: IniFile TIniFile und lange Dateinamen
 
Zitat:

Zitat von Luckie (Beitrag 1168328)
Sind Leerzeichen im Pfad? Und wenn ja, was passiert, wenn du ihn in Anführungszeichen setzt?

Leerzeichen nicht, auch nicht im Dateinamen. Allerdings lautet das Verzeichnis C:\Winnt.0, ob das schon zuviel ist? Was Du mit Anführungszeichen meinst, weiß ich nicht, ich arbeite ja mit Paramstr(0) und nicht mit in Anführungszeichen gesetzten Strings, die man an Stringvariablen übergibt.

Leerzeichen wäre(n) auch kein Argument dagegen, denn lange Dateinamen erlauben ja auch Leerzeichen in den Verzeichnis-/Dateinamen (was ja im weiteren Sinne dasselbe ist), auch mehrere Punkte usw. Die Konvention wird doch damit nicht verletzt (alles andere ließe Windows ja auch nicht zu). Wenn langnamentauglich, dann richtig oder eben gar nicht.

Ist doch jetzt auch nicht mehr wichtig. Paramstr(0) lieferte nur den kurzen Dateinamen zurück, warum auch immer, aber mit der Funktion in der verlinkten Diskussion ließ sich dieses (Fehl-?)Verhalten heilen.

Edit: Die Verliebtheit des ParamStr mit kurzen Dateinamen scheint auch andere vor Probleme gestellt zu haben, s. hier (dort wird allerdings ParamStr(1) verwendet, n.m.W. der Abruf des ersten Übergabeparameters).

Popov 27. Mai 2012 23:07

AW: IniFile TIniFile und lange Dateinamen
 
Also lange oder kurze Dateinamen, das interessiert die Ini nicht. Ob du dem Ident als Wert einen langen Dateinamen oder ein Banane zuweist, ist ihm egal, solange die Zeile unter 1024 Zeichen bleibt. Auch interessieren ihn keine Leerzeichen. Das einzige ist, dass Anführungszeichen beim auslesen entfernt werden.

Zitat:

Paramstr(0) lieferte nur den kurzen Dateinamen zurück
Bei mir nicht.

Wenn du Lust hast, ich habe hier paar Units, z. B. EasyIniAppExe speichert alles in der Ini am Programm, wechselt man die Ini aus, wird alles in der Reg gespeichert, usw.

Luckie 27. Mai 2012 23:18

AW: IniFile TIniFile und lange Dateinamen
 
Zitat:

Zitat von Delphi-Laie (Beitrag 1168329)
Leerzeichen nicht, auch nicht im Dateinamen. Allerdings lautet das Verzeichnis C:\Winnt.0, ob das schon zuviel ist? Was Du mit Anführungszeichen meinst, weiß ich nicht, ich arbeite ja mit Paramstr(0) und nicht mit in Anführungszeichen gesetzten Strings, die man an Stringvariablen übergibt.

Delphi-Quellcode:
meine.exe C:\Dies ist ein langer Pfad mit Leerzeichen\meine.ini
Das sind für ParamStr 7 Parameter.
Delphi-Quellcode:
meine.exe "C:\Dies ist ein langer Pfad mit Leerzeichen\meine.ini"
Das sind für ParamStr ein Parameter.

Delphi-Laie 27. Mai 2012 23:21

AW: IniFile TIniFile und lange Dateinamen
 
Liste der Anhänge anzeigen (Anzahl: 1)
Zitat:

Zitat von Popov (Beitrag 1168330)
Also lange oder kurze Dateinamen, das interessiert die Ini nicht. Ob du dem Ident als Wert einen langen Dateinamen oder ein Banane zuweist, ist ihm egal, solange die Zeile unter 1024 Zeichen bleibt. Auch interessieren ihn keine Leerzeichen. Das einzige ist, dass Anführungszeichen beim auslesen entfernt werden.

Zitat:

Paramstr(0) lieferte nur den kurzen Dateinamen zurück
Bei mir nicht.

Bei mir leider schon. Ich reduzierte das Problem auf das Minimale. Leg den beigelegten Bildschirmschoner bitte mal in ein relevantes Verzeichnis und starte ihn über das Fenster "Eigenschaften von Anzeige". Er gibt den Paramstr(0)-Dateinamen zurück, einmal vor, einmal nach Application.Run. In jedem Falle bei mir mit den heißgeliebten Tilden.

Danke, den Rest schaue ich mir an, wenn der Tag wieder heller ist.

Luckie 27. Mai 2012 23:22

AW: IniFile TIniFile und lange Dateinamen
 
Was ist ein relevantes Verzeichnis?

Delphi-Laie 27. Mai 2012 23:24

AW: IniFile TIniFile und lange Dateinamen
 
Zitat:

Zitat von Luckie (Beitrag 1168334)
Das sind für ParamStr 7 Parameter.

Danke, jetzt ist klar, was Du mit Deinen Fragen meintest und auch, welche Tücken sich bei dieser Auswertung auftun.

Popov 27. Mai 2012 23:27

AW: IniFile TIniFile und lange Dateinamen
 
Zitat:

Zitat von Delphi-Laie (Beitrag 1168335)
Leg den beigelegten Bildschirmschoner bitte mal in ein relevantes Verzeichnis und starte ihn über ...

Hab ich, beide lang.

himitsu 28. Mai 2012 08:54

AW: IniFile TIniFile und lange Dateinamen
 
Besitzt du die Quellcodes deines Delphis?

Wie sieht der Code von ParamStr aus?

Delphi-Laie 28. Mai 2012 09:37

AW: IniFile TIniFile und lange Dateinamen
 
Liste der Anhänge anzeigen (Anzahl: 1)
Mit "relevantem Verzeichnis" meinte ich eines für die Bildschirmschoner, also Windows (wie immer es auch benannt ist, früher gab es da ja noch Wahlfreiheit) oder sein Unterverzeichnis "System32". Die beiden kenne ich dafür. Also: Ein für die Bildschirmschoner relevantes Verzeichnis.

Bei mir liefert ParamStr(0), wenn (m)ein Bildschirmschonerprogramm aufgerufen wird, eben nur den kurzen Dateinamen (angehängtes Bild), der Grund liegt weiterhin im dunkeln. An einer fehlenden Path-Variable auf diese Verzeichnisse liegt es auch nicht. Hat jemand eine Idee? Falls nein, GetLongPahtName (bzw. dessen Kapselung) sind in der Lage, ParamStr(0)s Teilversagen auszugleichen.

Es muß jetzt mal heraus: Ich möchte nur mal ein größeres Programmierprojekt erleben, bei dem man nicht mit solchen unverhergesehenen Problemen, Widrigkeiten, ja Lästigkeiten zu kämpfen hat. Gibt es wahrscheinlich nicht, liegt wohl im Wesen der Programmiererei. Wenn ich so etwas beruflich täte, liefe ich Gefahr, irgendwann vor Frustration bis Wut einen Rappel zu bekommen.

Moderation: Soll ich den Titel dieser Diskussion umbenennen, z.B. in der Art: "ParamStr(0) liefert nur kurzen Dateinamen"?

himitsu: Habe ich, liegt in der System.pas, sieht so:

Delphi-Quellcode:
function ParamStr(Index: Integer): string;
var
  P: PChar;
  Buffer: array[0..260] of Char;
begin
  if Index = 0 then
    SetString(Result, Buffer, GetModuleFileName(0, Buffer, SizeOf(Buffer)))
  else
  begin
    P := GetCommandLine;
    while True do
    begin
      P := GetParamStr(P, Result);
      if (Index = 0) or (Result = '') then Break;
      Dec(Index);
    end;
  end;
end;
und scheint sich zumindest bis Delphi-Version 4 auch nicht zu verändern.

Popov 28. Mai 2012 09:47

AW: IniFile TIniFile und lange Dateinamen
 
Jetzt mal nur eine dumme Frage, was ist an dem kurzen Pfad falsch, wieso stört es?

himitsu 28. Mai 2012 09:47

AW: IniFile TIniFile und lange Dateinamen
 
Schade, dann scheint das ein Problem bei MSDN-Library durchsuchenGetModuleFileName in dem alten Windows zu sein.
Hätte ja sein können, daß es bei dir noch nicht verbaut wurde.

Der erste Wert (0. Parameter) von MSDN-Library durchsuchenGetCommandLine ist nämlich noch schlimmer, da er genau dem Entspricht, wie der Aufruf passierte.
z.B. über die Konsole oder via ShellExecute mit relativem Pfad aufgerufen "meinprogramm" (ohne .exe), dann steht genau das "meinprogramm" darin.

Delphi-Referenz durchsuchenExpandFileName oder MSDN-Library durchsuchenGetFullPathName

[edit]
Wenn du es benutzt, um z.B. auf eine INI zuzugreifen
Delphi-Quellcode:
ChangeFileExt(ParamStr(0), '.ini')
, dann gibt es ein Problem, wenn es die INI noch nicht gibt und sie erstellt werden soll.
(OK, wobei es eh keine gute Idee ist, die INI nach C:\Windows oder ins Programmeverzeichnis legen zu wollen :roll:)

Außerdem ist der Kurzname der gleichnamigen INI nicht unbedingt identisch mit dem Kurznamen der EXE, selbst wenn die langen Namen übereinstimmen.

Delphi-Laie 28. Mai 2012 09:55

AW: IniFile TIniFile und lange Dateinamen
 
Popov: Es funktioniert auch mit kurzem Dateinamen und läßt sich auch mit besagter Zusatzfunktion beheben. Aber Du weißt doch, wie Programmierer sind: Akribisch, pedantisch, penibel (wie immer positiv oder negativ konnotiert man das ausdrückt). Die Tilde sieht einfach besch...eiden aus und erinnert an das dunkle Windows-Mittelalter (was diesen geschwungenen Bogen wohl erst so häßlich werden ließ). Wenn es einmal korrekt und einmal nur halb funktioniert, dann stimmt doch irgendwo irgendetwas nicht, und wir wären keine Programmierer, wenn wir nicht wenigstens dieser Sache auf den Grund zu gehen versuchen würden, nicht wahr? Ist ja an der regen Beteiligung in den allermeisten Diskussionen ablesbar, und es schult ja sogar die Profis und fordert sie heraus (sozusagen eine kostenlose Weiterbildung).

himitsu: Vielleicht ist sogar ParamStr oder konkret ParamStr(0) unschuldig, aber einen GetCommandLine- oder GetModuleFileName-Befehl jetzt noch zu analysieren, überfordert mich nun doch endgültig. Allerdings funktionierte es sogar schon unter ME, und das wird wohl kaum großartig andere Befehle verbaut bekommen haben (2000 und ME erschienen ja fast gleichzeitig).

Vielen Dank allen Interessenten und Helfern hier!

Edit: Sogar unter einem XP funktioniert es mit dem langen Dateinamen unter den schon beschriebenen Voraussetzungen nicht.

Delphi-Laie 28. Mai 2012 10:40

AW: IniFile TIniFile und lange Dateinamen
 
Liste der Anhänge anzeigen (Anzahl: 1)
Ich "pushe" jetzt ganz bewußt. Das Problem muß noch tiefer stecken. Im Anhang die Bildschirmkopie unter Windows XP (!) meines nunmehr inzwischen mit Delphi 7 (!) erstellten Testbildschirmschoners. Allmählich wundert es mich sogar, daß dieses Problem nicht nachvollziehbar sein soll.

himitsu 28. Mai 2012 11:00

AW: IniFile TIniFile und lange Dateinamen
 
Alles vollkommen korrekt.

MSDN-Library durchsuchenGetModuleFileName
Zitat:

Windows XP: The string is truncated to nSize characters and is not null-terminated.

The string returned will use the same format that was specified when the module was loaded. Therefore, the path can be a long or short file name, and can use the prefix "\\?\". For more information, see Naming a File.
Man hätte nur mal nachlesen zu brauchen. :roll:


MSDN-Library durchsuchenGetModuleFileNameEx ?


Tja, das zeigt auch gleich, daß diese Programme mindestens Windows XP benötigen ... davor werden sie nichtmal starten.

Delphi-Laie 28. Mai 2012 14:44

AW: IniFile TIniFile und lange Dateinamen
 
Nachlesen...naja, wenn zwei tun, ist es noch lang nicht dasselbe.

Danke, himitsu, daß Du Dich so rührend darum kümmerst.

Wenn "alles vollkommen korrekt" ist, was ich nicht bezweifele, so ist doch - zumindest für mich - nicht nachvollziehbar, wieso dieses (Fehl-)Verhalten

- Popov nicht bestätigen kann
- nur auftritt, wenn der BS-Schoner über das von Windows eigens dafür präparierte Fenster, nicht jedoch über die Konsole aufgerufen wird.

Konsistent ist das m.E. nicht.

himitsu 28. Mai 2012 14:56

AW: IniFile TIniFile und lange Dateinamen
 
Auch mal den Kurznamen über die Konsole probiert?
Mit absolutem und relativen Pfad.

Delphi-Laie 28. Mai 2012 15:09

AW: IniFile TIniFile und lange Dateinamen
 
Zitat:

Zitat von himitsu (Beitrag 1168388)
Auch mal den Kurznamen über die Konsole probiert?
Mit absolutem und relativen Pfad.

Nein, ich rief nur über den langen Dateinamen über die Konsole auf, bei den kurzen ist schon die Schwierigkeit, die Tilde zu erzeugen. Vielleicht wird es über das Fenster ja mit dem kurzen aufgerufen?
Mit "relativem" Pfad kann ich nicht viel anfangen, vermutlich sind da Umgebungsvariablen mit im Spiel. Ich rief nur über den absoluten Pfad auf ("C:\Winnt.0\ParamStrTest.scr").

Edit: Nein, auch wenn ich mit kurzem Dateinamen über die Konsole aufrufe, wird korrekterweise der lange angezeigt.


Alle Zeitangaben in WEZ +1. Es ist jetzt 17:29 Uhr.

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