![]() |
Fehler bei eigenem Installationsprogramm - Verknüpfung
Hi,
ich habe folgendes Problem: Ich habe eine eigene Installationsroutine geschrieben. Soweit - sogut, funktioniert jedenfalls fast alles, bis auf das manche ein Problem haben mein Programm zu installieren. Bei manchen Leuten geht´s bei manchen nicht. Ich möchte für mein Programm eine Verknüpfung auf dem Desktop erstellen (*.lnk Datei) und verwende dafür folgende Funktion:
Code:
Das Problem ist jetzt, dass bei manchen Leuten die Fehlermeldung "Konnte Pfad nicht setzen" kommt. Ich denke mir, dass es an der oben markieren Zeile liegt, aber wie kann ich den Fehler beheben? Wäre nett, wenn mir jemand helfen könnte!
procedure NewShellLink(Const pcsFileToLinkTo : String);
const IID_IPersistFile: TGUID = '{0000010b-0000-0000-C000-000000000046}'; var slShellLink : IShellLink; pfPersistFile : IPersistFile; wsShortCut : PWideChar; hRes : HResult; sShortCut : String; begin CoInitialize(nil); hRes := CoCreateInstance(CLSID_ShellLink, nil, CLSCTX_INPROC_SERVER, IID_IShellLinkA, slShellLink); if hRes = S_OK then begin slShellLink.SetPath(PChar(pcsFileToLinkTo)); // HIER DÜRFTE DER FEHLER LIEGEN!!! hRes := slShellLink.QueryInterface(IID_IPersistFile, pfPersistFile); end; if hRes = S_OK then begin GetMem(wsShortCut,MAX_PATH shl 1); sShortCut := ChangeFileExt(pcsFileToLinkTo,'.LNK'); MultiByteToWideChar(CP_ACP, 0, PChar(sShortCut), -1, wsShortCut, MAX_PATH shl 1); pfPersistFile.Save(wsShortCut, TRUE); FreeMem(wsShortCut,MAX_PATH shl 1); end; end; Gruß Yheeky |
Moin Yheeky,
irgendwie erkenn' ich da meine "Handschrift" ;-) Wenn ich nicht irre, war das ganze auch mal mit Kommentaren versehen. Wichtig wäre schon einmal, dass das CoInitialize nur einmal pro Thread aufgerufen wird, was sich am elegantesten wohl im initialization Abschnitt des Hauptformulares erledigen lässt. Dazu muss zu jedem Aufruf von CoInitialize auch ein Aufruf von CoUninitialize erfolgen (finalization). Das nur mal vorweg, da es für ein sauberes Resourcenmanagement wichtig ist. Ich denke mal, dass der Fehler erst in der Zeile pfPersistFile.Save... liegt, da hier erst wirklich gespeichert wird. Allerdings weiss ich nicht genau, welcher Pfad angemeckert wird, der der LNK Datei, oder der auf die die LNK Datei verweist (dann hättest Du wohl recht mit der fehlerhaften Zeile). Gibt es bei den Systemen, bei denen der Fehler auftritt irgendwelche Gemeinsamkeiten (im Moment habe ich den Verdacht, dass es sich durchweg um XP bzw. W2K handeln könnte)? Vermutlich liegt die Fehlerursache darin, dass auf einen Pfad verwiesen wird, der Leerstellen enthält. |
Hi,
was ein Zufall, dass die Funktion von dir ist :roll: :lol: Naja, der Fehler taucht eigentlich unregelmäßig auf. Bei mir und ein paar Freunden geht es problemlos unter WinXP, bei meiner Freundin jedoch, kommt der oben beschriebene Fehler (auch unter WinXP). Meinst du, dass es wirklich an den Leerzeichen liegt? Warum geht es denn dann an manchen Rechnern oder wie könnte man das Problem sonst beheben? Hab den Rest jetzt so eingebaut. Ist das richtig?
Code:
Gruß Yheeky
Initialization
CoInitialize(nil); Finalization CoUnInitialize(nil); end. |
Moin Yheeky,
unter XP hab' ich's noch nicht getestet. Mittlerweile hab' ich die Funktion noch ein wenig überarbeitet. Ich muss nur mal sehen, wo ich sie habe. (nach der Neuinstallation ist noch nicht wieder alles da wo's hingehört ;-) ) Mal abgesehen davon, das CoUninitialize keinen Parameter hat stimmt's soweit, wenn Du's denn im Hauptformular eingetragen hast. Es wäre zumindest noch interessant, wie die Pfade (zur Exe und zur Lnk) bei dem Rechner lauten sollen, bei dem es nicht funktioniert). Tritt der Fehler reproduzierbar auf? |
Hi Christian,
okay, dann hab´ ich soweit alles richtig eingebaut. Was die Pfade betrifft...das kann ich dir ja nicht sagen. Der User kann ja einen Pfad auswählen. Was ich dir aber sagen kann ist, dass es bei dem Standardpfad auftritt (in diesem Falle: "C:\Programme\BrotherSoft\ISDN - Exchange"). Gruß Yheeky |
Moin Yheeky,
hier noch eine leicht aktualisierte Fassung:
Delphi-Quellcode:
Leider kann ich den Fehler nicht reproduzieren (mit Deinem Pfad), und somit wird's auch etwas schwierig die Ursache zu ermitteln.
// Der Einfachheit halber heisst der Link genauso, wie die Datei
procedure NewShellLink(Const pcsFileToLinkTo : String); // Auf diese Datei soll verwiesen werden const // Fehlende Deklaration in Delphi // Zu finden in der Registry // HKEY_CLASSES_ROOT\Interface // nach IPersistFile suchen IID_IPersistFile: TGUID = '{0000010b-0000-0000-C000-000000000046}'; var slShellLink : IShellLink; // ShellLink Interface pfPersistFile : IPersistFile; // Shortcut (Link) Permanent speichern wsShortCut : PWideChar; // Buffer für den Shortcutnamen hRes : HResult; // Für Zwischenergebnisse sShortCut : String; // So heisst dann der Shortcut begin // COM Object der Klasse ShellLink erzeugen hRes := CoCreateInstance(CLSID_ShellLink, // ID von ShellLink (Typ TGUID) nil, CLSCTX_INPROC_SERVER, IID_IShellLinkA, // Referenz auf die Funktion slShellLink); // erhält nach erfolgreichem Aufruf // den Pointer auf die Funktion if hRes = S_OK then begin slShellLink.SetPath(PChar(pcsFileToLinkTo)); // Auf diese Datei geht der Link slShellLink.SetWorkingDirectory(PChar(ExtractFilePath(pcsFileToLinkTo))); slShellLink.SetHotKey((MOD_WIN shl 8) or ord('T')); hRes := slShellLink.QueryInterface(IID_IPersistFile, // wieder mal einen pfPersistFile); // Pointer holen end; if hRes = S_OK then begin GetMem(wsShortCut,MAX_PATH shl 1); // Speicher reservieren für den Shortcutpfadnamen // Eigentlich genügt die Länge MAX_PATH, aber da // der Wert in UNICode zurückgegeben wird mal 2 try sShortCut := ChangeFileExt(pcsFileToLinkTo,'.LNK'); // Soll einfach mal so heissen, // Wie die aufzurufende Datei MultiByteToWideChar(CP_ACP, // ANSI Codepage benutzen 0, PChar(sShortCut), // Der soll konvertiert werden -1, // der zu konvertierende String ist Null terminiert wsShortCut, // und hier soll das Ergebnis rein MAX_PATH shl 1); // Länge von wsShortCut pfPersistFile.Save(wsShortCut, TRUE); // Jetzt noch den Link speichern finally FreeMem(wsShortCut,MAX_PATH shl 1); // und den Platz wieder freigeben end; end; end; procedure TForm1.Button1Click(Sender: TObject); begin if Opendialog1.Execute then begin NewShellLink(OpenDialog1.FileName); end; end; initialization begin CoInitialize(nil); end; finalization begin CoUnInitialize; end; Was bei dem Beispiel Code noch wichtig wäre: Der Link wird im gleichen Verzeichnis gespeichert, wie die Exe. Soll die gleich auf dem Desktop landen, muss in der Zeile pfPersistFile.Save noch der richtige Pfad eingetragen werden. |
Hi Christian!
Okay, danke für die aktualisierte Version. Was aber meinst du mit Zitat:
Gruß Yheeky |
Moin Yheeky,
das Beispiel ist ja mehr als Demo denn als direkt verwertbarer Codeschnipsel zu verstehen. Ich kann mir offengestanden nicht so recht den Fall vorstellen, in dem der Link genauso heissen soll und in genau dem Verzeichnis liegen soll, wie die Datei, auf die verwiesen werden soll. Mindestens ein zweiter Parameter, der eben diesen Pfad (incl. Namen) angibt wäre wohl schon nicht verkehrt. Statt der Variablen sShortCut wird dann dieser Parameter mit dem MultiByteToWideChar in wsShortCut geschoben. (die ChangeFileExt Zeile kann dann natürlich ersatzlos gestrichen werden). Wie ich gerade gesehen habe setze ich da auch noch einen HotKey auf Windowstaste+T. Die Zeile kann auch gestrichen werden, das funktioniert nämlich sowieso nicht (jedenfalls nicht mit der Windowstaste). Schau Dir doch mal im PSDK die Methoden von IShellLink an. Dann bekommst Du mal eine Übersicht, was so alles eingestellt werden kann. |
Lag gar nicht an der Funktion, sondern an etwas anderem :oops:
Trotzdem danke für deine "aktuellen Zeilen". Gruß Yheeky |
Alle Zeitangaben in WEZ +1. Es ist jetzt 13:55 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 by Thomas Breitkreuz