![]() |
Problem mit Dateiaufruf per paramstr
Also folgendes Problem:
Habe ein programm das sich im Contextmenü einträgt. Wenn ich eine Datei über den Eintrag im CMenü auswähle startet mein Programm 1x und hat im paramstr(1) den Pfad zur Datei die gewählt wurde... Wenn ich mehr als eine datei aufrufe sollen diese natürlich auch von meinem programm geöffnet werden mein programm startet aber bei 3 dateien dann 3x ??? es soll aber nur 1x starten und die anderen dateien ebanfalls bearbeiten... Lösungsansatz: das Programm darf nur einmal starten und muss wenn es bemerkt das es mehrfach gestartet wurde sich selbst beenden und den jeweiligen paramstr(1) an das ersdte gestartet programm senden
Code:
// ===================================================
Initialization mHandle:=CreateMutex(nil,True,'my_programm'); if GetLastError=ERROR_ALREADY_EXISTS then begin // hier die Daten senden ??? wenn ja wie ? Halt; end; finalization if mHandle<>0 then CloseHandle(mHandle) end. Danke für Eure Hilfe :spin: |
Re: Problem mit Dateiaufruf per paramstr
Delphi-Quellcode:
Unter Win9x werden Mutexe/Atome/Semaphore usw. nicht mehr korrekt freigeben falls die Anwednung crasht. Dadurch könnte es passieren das eine einmal gecrashte Anwendung nicht erneut gestartet werden kann, da der globale benammte Mutex noch existiert. ABER!, das feine ist das Fensterhandles auch unter Win9x ungültig werden wenn die Anwendung gecrasht ist. Deshalb nutzen wir oben ein Fensterhandle mit möglichst eindeutigen Namen um 1. zu erkennen ob unsere Anwendung schon läuft und 2. gleichzeigt als Transportweg um ParamStr(1) zu übertragen.const cMagic = $1234567; cResult = $7654321; sTitle = 'my_program$XY12345678_Moeglichst_Eindeutiger_Name'; // als sTitle kann auch ParamStr(0) herhalten var WndHandle: hWnd = 0; type TSingleInstance = class class procedure WndProc(var Msg: TMessage); class procedure Start; class procedure Stop; end; class function TSingleInstance.WndProc(var Msg: TMessage); var Param: String; begin with Msg do if (Msg = wm_CopyData) and (PCopyDataStruct(lParam).cwData = cMagic) then begin Param := PCopyDataStruct(lParam).lpData; OpenFile(Param); // o.ä. Result := cResult; end else Result := DefWindowProc(WndHandle, Msg, wParam, lParam); end; class procedure TSingleInstance.Start; var PrevWnd: hWnd; Data: TCopyDataStruct; Param: String; begin PrevWnd := FindWindow('TPUtilWindow', sTitle); if IsWindow(PrevWnd) then begin Param := ParamStr(1); Data.cwData := cMagic; Data.cbData := Length(Param) +1; Data.lpData := Pointer(Param); if SendMessage(PrevWnd, wm_CopyData, 0, Integer(@Data)) = cResult then ; // erfolgreich Halt; end; WndHandle := AllocateHWnd(WndProc); SetWindowText(WndHandle, sTitle); end; class procedure TSingleInstance.Stop; begin if IsWindow(WndHandle) then DeallocateHWnd(WndHandle); end; initialization TSingleInstance.Start; finalization TSingleInstance.Stop; end; Allerdings auch diese Methode hat ihre Nachteile, z.b. bei Services die in einer anderen WinSta laufen. Gruß Hagen PS: obiger Code ist nur aus'm Gedächtnis, also keine Garantie das alles absolut korrekt ist ;) |
Re: Problem mit Dateiaufruf per paramstr
Kommt so erst mal in die Code-Lib. Irgendwelche Vorschlage für eine Überschrift, die kurz und aussagekräftig ist?
@Hagen: Das mit dem Schlüsselwort class vor den Methoden der Klasse sehe ich zum ersten mal. Dient das nur der Lesbarkeit oder hat das noch einen tieferen Sinn? |
Re: Problem mit Dateiaufruf per paramstr
wäre jemand so nett den source oben etwas näher zu erläutern ??
ich will ihn nicht nur kopieren sondern auch verstehen :) danke ... |
Re: Problem mit Dateiaufruf per paramstr
[Fehler] Unit1.pas(101): Funktion benötigt Ergebnistyp
[Fehler] Unit1.pas(106): Undefinierter Bezeichner: 'cwData' [Warnung] Unit1.pas(106): Der Vergleich ergibt immer Falsch [Fehler] Unit1.pas(108): Inkompatible Typen: 'String' und 'Pointer' [Fehler] Unit1.pas(109): Inkompatible Typen: 'String' und 'PChar' [Fehler] Unit1.pas(121): Inkompatible Typen: 'String' und 'PChar' [Fehler] Unit1.pas(125): Undefinierter Bezeichner: 'cwData' [Warnung] Unit1.pas(131): Symbol 'AllocateHWnd' wird abgelehnt [Warnung] Unit1.pas(137): Symbol 'DeallocateHWnd' wird abgelehnt [Fataler Fehler] filekiller.dpr(5): Verwendete Unit 'Unit1.pas' kann nicht compiliert werden |
Re: Problem mit Dateiaufruf per paramstr
Das muß dwData heißen.
Den String kannst du einfach nach PChar casten. Desweiteren helfen uns deine Zeilennummern nicht wirklich. Gib mal die Stellen im Code an. |
Re: Problem mit Dateiaufruf per paramstr
ich glaube ich weiß wo mein problem liegt ...
ich will das eine *.exe einzelne dateien als auch mehrere datein löschen kann... wenn ich das versuche mit den hier genannten beispielen zu lösen passiert folgendes: 3 Dateien ausgewählt -> myprogramm.exe startet 3x exe1 heisst 'myprogramm' soll da bleiben und daten von 2,3 empfangen exe2 heisst 'myprogramm' soll paramstr(1) an 1 exe senden + schliessen exe3 heisst 'myprogramm' soll paramstr(1) an 1 exe senden + schliessen und genau da ist das problem, in dem moment wenn ich sende sind läuft mein programm mehr als 1 mal... wie kann ich das lösen ? |
Re: Problem mit Dateiaufruf per paramstr
@wb32: so wie oben angedeutet. Der Source ist allerdings eben aus dem Gedächtnis und NICHT garantiert lauffähig.
@Lucki: Ich werde den Source lieber nochmal überarbeiten, so daß er auch tatsächlich funktioniert (per Copy&Paste, war aber eigentlich nicht so gedacht von mir :) Zur Frage mit dem Klassen Methoden -> class function ... Ja dies ist absolut notwendig, zumindestens für class procedure WndProc(). Diese Deklaration ist Typkompatibel mit TWndMethod die ja in AllocateHWnd(TSingleInstance.WndProc) benötigt wird. Normalerweise deklarieren wir ein TObject mit procedure WndMethod(), erzeugen ein solches Object um dann AllocateHWnd(MyObject.WndProc) benutzen zu können. Wir müssten im Normalfall also immer eine Objectinstance erzeugen. Um dies nicht machen zu müssen gibt es zwei Wege: 1.) über den obigen Klassenmethoden Weg oder 2.) über ein getürktes Event bei TMethod(Event).Code := @Procedure. Der Weg über Klassenmethoden ist aber sauberer. Um nun alles noch sauberer zu kapseln habe ich gleich noch die Methoden .Start und .Stop als Klassenmethode deklariert. Gruß Hagen |
Re: Problem mit Dateiaufruf per paramstr
also ich hab folgende idee...
1 programmstart form1.caption:='myprogramm'; dann prüfen ob mehrfachstart vorliegt 2,3,4,5,6 form1.caption:='xxxxxxxxx'; dann einfach an 'myprogramm' senden... geht das so ? irgendwas stimmt am source aber nicht...
Code:
was stimmt da nicht ?
procedure TForm1.FormShow(Sender: TObject);
begin if ParamCount > 0 then begin Form1.Caption:= 'myprogramm'; mHandle := CreateMutex(nil,True, 'myprogram_45zg556z5g43'); Memo1.Lines.Add(SysErrorMessage(GetLastError)); // das funktioniert if GetLastError=ERROR_ALREADY_EXISTS then begin // das funktioniert nicht Form1.Caption:= 'xxxxxxxxx'; end; end; |
Re: Problem mit Dateiaufruf per paramstr
ok ich glaube ich habs, die funktion getlaserror ist nach dem aufruf leer richtig ?
|
Re: Problem mit Dateiaufruf per paramstr
Hier also die lauffähige Version. Einfach diese Unit in das Projekt einbinden und die Methode TSingleInstance.OnStartUp mit eigenen Leben füllen. Nicht vergessen den Wert sTitle mit einem eigenen eindeutigen Wert zu ändern.
Gruß Hagen
Delphi-Quellcode:
unit SingleInstance;
interface implementation uses Windows, SysUtils, Controls, Messages, Dialogs, Forms; type TSingleInstance = class class procedure WndProc(var Msg: TMessage); class procedure Start; class procedure Stop; class function GetParamStr(P: PChar; var Param: string): PChar; class function ParamCount: Integer; class function ParamStr(Index: Integer): string; class procedure OnStartup; end; const sTitle = 'my_ProgramXYZ$123456789'; // dieser Wert MUSS individuell angepasst werden class procedure TSingleInstance.OnStartup; // diese Methode muß mit eigenen Inhalt gefüllt werden, // als Beispiel wird hier die 1. Instance sichtbar gemacht // und der ParamStr() der 2. Instance angezeigt. var S: String; I: Integer; begin Application.Minimize; Application.Restore; S := ''; for I := 0 to ParamCount do S := S + ParamStr(I) + #10; ShowMessage(S); end; // ab hier Implementierung const cMagic = $BADF00D; // dient zur Idententifizierung der Message wm_CopyData cResult = $DAED; var WndHandle: hWnd = 0; // die 1. Instance erzeugt ein Fensterhandle CmdLine: PChar = nil; // ParamStr() der 2. Instance per wm_CopyData transportiert class function TSingleInstance.GetParamStr(P: PChar; var Param: string): PChar; // diese funktion musste aus System.pas kopiert werden für unser // ParamStr() udn ParamCount() nötig var Len: Integer; Buffer: array[0..4095] of Char; begin while True do begin while (P[0] <> #0) and (P[0] <= ' ') do Inc(P); if (P[0] = '"') and (P[1] = '"') then Inc(P, 2) else Break; end; Len := 0; while (P[0] > ' ') and (Len < SizeOf(Buffer)) do if P[0] = '"' then begin Inc(P); while (P[0] <> #0) and (P[0] <> '"') do begin Buffer[Len] := P[0]; Inc(Len); Inc(P); end; if P[0] <> #0 then Inc(P); end else begin Buffer[Len] := P[0]; Inc(Len); Inc(P); end; SetString(Param, Buffer, Len); Result := P; end; class function TSingleInstance.ParamCount: Integer; // diese Funktion musste aus System.pas kopiert werden für unser // ParamStr() und ParamCount() nötig da System.pas NICHT auf die // globale Variable System.CmdLine zugreift sondern per Funktion GetCommandLine() arbeitet. var P: PChar; S: string; begin P := GetParamStr(CmdLine, S); // CmdLine statt GetCommandLine Result := 0; while True do begin P := GetParamStr(P, S); if S = '' then Break; Inc(Result); end; end; class function TSingleInstance.ParamStr(Index: Integer): string; // siehe ParamCount 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 := CmdLine; // CmdLine statt GetCommandLine while True do begin P := GetParamStr(P, Result); if (Index = 0) or (Result = '') then Break; Dec(Index); end; end; end; class procedure TSingleInstance.WndProc(var Msg: TMessage); // das ist die Fensterprocedure von WndHandle, sie empfängt innerhalb // der 1. Instance die wm_CopyData Message mit der CommandLine der // 2. Instance begin with Msg do if (Msg = wm_CopyData) and (PCopyDataStruct(lParam).dwData = cMagic) then begin Result := cResult; CmdLine := PCopyDataStruct(lParam).lpData; OnStartup; end else Result := DefWindowProc(WndHandle, Msg, wParam, lParam); end; class procedure TSingleInstance.Start; var PrevWnd: hWnd; Data: TCopyDataStruct; begin if MainInstance = GetModuleHandle(nil) then // nur in EXE's möglich, nicht in DLL's oder packages begin PrevWnd := FindWindow('TPUtilWindow', sTitle); // suche unser Fenster if IsWindow(PrevWnd) then begin // 1. Instance läuft also schon, sende CommandLine an diese Data.dwData := cMagic; Data.cbData := StrLen(GetCommandLine) +1; Data.lpData := GetCommandLine; if SendMessage(PrevWnd, wm_CopyData, 0, Integer(@Data)) = cResult then Halt; end; // keine 1. Instance gefunden, wir sind also die 1. Instance WndHandle := AllocateHWnd(WndProc); SetWindowText(WndHandle, sTitle); // falls auch bei der 1. Instance OnStartup aufgerufen werden soll // CmdLine := System.CmdLine; // OnStartup; end; end; class procedure TSingleInstance.Stop; begin if IsWindow(WndHandle) then DeallocateHWnd(WndHandle); end; initialization TSingleInstance.Start; finalization TSingleInstance.Stop; end. |
Re: Problem mit Dateiaufruf per paramstr
tut mir leid das is mir zu hoch kann sich mal jemand meinen source ansehen bitte... es funktioniert einwandfrei ausser das beim zuerst gestarteten programm der falsche paramstr ankommt...
Code:
procedure TForm1.WndProc(var msg : TMessage); begin if msg.Msg = dwMessage then begin if msg.lParam <> 0 then begin m1.Lines.Add(PChar(msg.lParam)); end else begin if msg.WParam > -1 then begin m1.Lines.Add(IntToStr(msg.wParam)); end else begin m1.Lines.Add('Keine Daten...'); end; end; end else begin inherited WndProc(msg); end; end; function FindSyncDemo(const p_hWindow : DWORD;const p_szCaption : PChar) : Boolean; stdcall; var dwLen : DWORD; szWork : PChar; begin Result := true; dwLen := SendMessage(p_hWindow,WM_GETTEXTLENGTH,0,0) + 1; if Length(p_szCaption) <> (dwLen-1) then exit; szWork := AllocMem(dwLen); try SendMessage(p_hWindow,WM_GETTEXT,dwLen,lParam(szWork)); if StrLComp(szWork,p_szCaption,dwLen) = 0 then begin Form1.m1.Lines.Add('Sende '+Pfad); SendMessage(p_hWindow, dwMessage,0, lParam(Pfad)); end; finally FreeMem(szWork,dwLen); end; end; procedure TForm1.FormShow(Sender: TObject); var FName: String; begin FName:='myprogramm'; if ParamCount > 0 then begin Pfad:= paramstr(1); Form1.Caption:= FName; mHandle := CreateMutex(nil,True, 'FKILLER-36545tf456-34tf34tf23-23r3'); if GetLastError=ERROR_ALREADY_EXISTS then begin Form1.Caption:= 'xxxxxxxxxxxxxxxxxxxx'; // jetzt paramstr(1) an exe1 senden dwMessage := RegisterWindowMessage(3654-5tf-456-34tf3-4tf23); EnumWindows(@FindSyncDemo,integer(FName)); end; end; |
Re: Problem mit Dateiaufruf per paramstr
Zitat:
In deinem Source gibt es gleich mehrere Probleme. 1.) CreateMutex() kann fehlschlagen wenn unter Win9x der Prozess der diesen Mutex angelegt hat gecrasht ist. Dann besteht dieser Mutex im System weiterhin obwohl es diesen Prozess nicht mehr gibt. Normalerweise würde eine Anwendung die auf CreateMutex() aufbaut dann nicht mehr starten. In deinem Falle würde die 1. Instance dann per EnumWindow() nach dem Fenster suchen, aber keines finden. Somit ist der CreateMutex() Aufruf sinnlos. 2.) Benötigt man zwecks Datenaustausch von ParamStr() ein Fensterhandle dann kann auch CreateMutex() verzichtet werden. 3.) Daten die von einem Prozess zu einem anderen Prozess, über Fensterhandles, ausgetauscht werden sollen müssen per wm_CopyData gesendet werden. wm_CopyData stellt sicher das der Speicherbereich in TCopyDataStruct aus der Gültigkeit des sendenden Prozesses auch gültig im empfangenden Prozess ist. Deshalb wird wm_CopyData immer NUR mit SendMessage() benutzt. Und deshalb funktioniert dein SendMessage() eben nicht. 4.) Dein EnumWindows() kann leicht durch FindWindow() ersetzt werden. Statt also mit EnumWindows() über alle TopLevel Fenster zu iterieren reicht FindWindow(ClassName, WindowText) völlig aus. 5.) die Überprüfung in .FormShow() und das Erzeugen des Mutex ist an dieser Stelle denkbar ungünstig. Der beste Zeitpunkt, und auch der frühestmögliche, ist innerhalb einer Unit-Initialization. Wird meine obige Unit im Projektquelltext an 1. Stelle eingefügt dann wird sie noch vor der Erstellung jeglicher Forms ausgeführt. Damit würde also die 2. Instance der Anwendung erst garnicht langwierige Initialisierungen durchführen. Aber im Grunde macht mein Vorschlag genau das was du versucht zu erreichen. 1.) TSingleInstance.Start sucht im System nach einem Fenster vom Typ "TPUtilWindow" + Caption "my_programXYZ12345". Dies erhöt die Sicherheit. 2.) wenn es gefunden wird wird der aktuelle ParamStr() = GetCommandLine an dieses Fenster per wm_CopyData gesendet. Wir senden also nicht nur ParamStr(1) sondern die komplette Kommandozeile. 3.) sollte das Fenster korrekt antworten so wird die aktuelle Anwendung angehalten und terminiert 4.) sollte kein Fenster "PrevWnd" gefunden worden sein, oder das Fenster hat nicht korrekt geantwortet dann wird die aktuelle Anwendung zur 1. Instance. Sie erzeugt ein Fenster vom Typ "TPUtilWindow" + Caption "my_programxyz123445" 5.) TSingleInstance.WndProc() wartet nun auf die Message wm_CopyData die durch eine 2. Instance der Anwendung aufgerufen wird. Punkte 1.) bis 3.) oben. 6.) sollte TSingleInstance.WndProc() eine gültige wm_CopyData Message erhalten so setzt sie die globale Variable CmdLine auf die Daten die per wm_CopyData empfangen wurde. CmdLine entspricht in diesem Moment der Kommandozeile der zweiten Instance der Anwendung. 7.) nun wird TSingleInstance.OnStartup() aufgerufen, die DEINEN Code enthalten sollte. Innerhalb .OnStartup() kannst du über die Methoden .ParamCount und .ParamStr() auf die Kommandozeile der zweiten Anwendung zugreifen. 8.) TSingleInstance.Stop wird bei der Terminierung der Anwendung aufgerufen und zerstört unser Helperfenster. So was ist daran kompliziert ? besonders weil es auch sauberer und lesbarer Source ist ! :) D.h. für dich: 1.) füge Unit Singleinstance zu deinem Projekt hinzu 2.) ändere den Wert von sTitle auf einen eindeutigen String 3.) ändere den Code in .OnStartup so wie du ihn brauchst. Innerhalb von .OnStartup nutzt du ParamCount und ParamStr() so als würdest du ganz normal damit wie in deiner Anwendung arbeiten. Das wars. Gruß Hagen |
Re: Problem mit Dateiaufruf per paramstr
Sooo danke noch mal für die Hilfe gestern abend, heute morgen usw *gg*...
war gar nich so schwer wie ich dachte aber manchmal muss man nach stundenlangem verzweifeln einfach ne Pause machen und dann später nochmal schauen... soweit so gut jetzt taucht das nächste problem auf :(... wenn ich mit deiner Unit alle dateien fein nacheinander auswäle und öffne dann geht es wunderbar, wenn ich aber 3 markiere und sage mit myprogramm öffnen dann öffnet sich myprogramm 3x ... woran könnte das liegen ? |
Re: Problem mit Dateiaufruf per paramstr
Jay, jetzt's wirds kritisch. Das lässt sich so ohne weiteres nicht ändern, leider. Es liegt an der Vorgehensweise wie die Shell = Explorer eine Anwendung startet. Sie hat die 3 Dateien und erzeugt mit CreateProcess() 3 mal deinen Prozess. ABER! sie gibt diesen 3 neuen Prozessen erst dann eine Chance anzulaufen wenn alle 3 Prozesse schon erzeugt wurden. Deshalb ist es enorm wichtig den "Einmal-Startcode" so früh und so effizient wie möglich einzubauen. Leider bewirkt die Benutzung von Fensterhandles in unserem "Einmal-Startcode" das auch die beiden anderen Prozesse Rechenzeit bekommen, noch bevor überhaupt ein Fensterhandle vollständig erzeugt wurde.
Man kann dies ändern, aber das wird vom Verständnis echt komplizierter. Dafür müssen wir auf Semaphores und Interprozesskommunikation ausweichen. D.h. alle 3 Prozesse laufen korrekt an, wissen aber welche die 1. 2. und 3. Instance ist. Wenn die 1. Instance ordentlich läuft senden die zwei nachfolgenden Prozesse ihre Parameter an die 1. Instance und terminieren. D.h. falls die 2 nachfolgenden Prozesse anhand der Semaphore bemerken das sie nicht die 1. Instance sind müssen die solange warten bis sie mit der 1. Instance kommunizieren können. Allerdings, irgendwie verstehe ich dein Problem noch nicht so recht. Wenn ich mich richtig erinnere kann man den Registryschlüssel für ShellEx/Commmand so anlegen das der Explorer multiple Files an EINE Instance der Anwendung sendet. Er startet dann nur eine Instance und übergibt alle Files als Params. Ansonsten, gibts noch den Weg über COM Interfaces ein eigenes Shell-Interface zu programmieren. Statt dann über ParamStr() und ein EXE zu gehen, codet man eine DLL als Handler. In dieser kann über die Shellextension direkt auf die ausgewählte Dateiliste im Explorer zugegriffen werden. Bei Delphi sind zwei Beispiel dafür vorhanden IShellContextMenu und IShellExecuteHook. Gruß Hagen |
Re: Problem mit Dateiaufruf per paramstr
Zitat:
???????????????????????????????????????????? das geht ? dann hätten wir uns die Aktion doch sparen können ich habe doch mehrmals geschrieben wofür ich das benutzen will :) wie geht das mit der einstellung für multiple files ? |
Re: Problem mit Dateiaufruf per paramstr
Zitat:
Zitat:
Vielleicht weiß ja ein anderer DP'ler schnell die Antwort. Gruß Hagen |
Re: Problem mit Dateiaufruf per paramstr
Zitat:
Zitat:
Zitat:
also ich hab schon in der msdn gesucht bin aber nich so wirklich fündig geworden :( |
Re: Problem mit Dateiaufruf per paramstr
Ich habe mal auf die schnelle meine Registry gescannt.
Es gäbe den Weg über DDE, ein sehr alter Weg, oder eben über die Shell Extensionen. Lass mir ein bißchen Zeit, am Wochenende werde ich mal TSingleInstance erweitern um die Semaphores, eventuell mit Memory Mapped Files + Events in Threads. Auf jeden Fall habe ich noch nie einen absolut sauber arbeitenden Single Instance Code gefunden. Zur Zeit muß ich erstmal Geld verdienen. Gruß Hagen |
Re: Problem mit Dateiaufruf per paramstr
hmm falls jemand anderes weiß wie man mutltiple files an eine instance senden kann bitte trotzdem posten mal schauen ob wir was finden und was letztendlich dann der beste weg ist :)
@Hagen danke erstmal, mal schauen ob du es hinbekommst |
Re: Problem mit Dateiaufruf per paramstr
Zitat:
Gruß hagen |
Re: Problem mit Dateiaufruf per paramstr
also ich habe folgendes festgestellt:
Code:
procedure TForm1.addClick(Sender: TObject);
begin reg:=tregistry.create(); // Dateien ins Context Menü Reg.RootKey:=HKEY_CLASSES_ROOT; Reg.OpenKey('*\shell',true); Reg.CloseKey; Reg.OpenKey('*\shell\'+Name,true); Reg.WriteString('',Title);//optional Reg.CloseKey; Reg.OpenKey('*\shell\'+Name+'\command',true); Reg.WriteString('',Adress); // adress="c:\test\meinprogramm.exe %1" Reg.CloseKey; Reg.OpenKey('*\shell\'+Name+'\ddeexec\',true); Reg.WriteString('','[open("%1")]'); Reg.CloseKey; // Ordner ins Context Menü Reg.OpenKey('Directory\shell',true); Reg.CloseKey; Reg.OpenKey('Directory\shell\'+Name,true); Reg.WriteString('',Title);//optional Reg.CloseKey; Reg.OpenKey('Directory\shell\'+Name+'\command',true); Reg.WriteString('',Adress); Reg.CloseKey; reg.free; del.enabled:=true; add.Enabled:=false; end; Dieser Code hier:
Code:
bewirkt das man multiple dateien auswählen kann, wenn ich mehr als eine Datei wähle funktioniert alles bestens, wenn ich nun aber nur eine wähle kommt eine Messagebox das die mit Rechtsklick gewählte Datei nicht gefunden wurde ????Reg.OpenKey('*\shell\'+Name+'\ddeexec\',true); Reg.WriteString('','[open("%1")]'); Reg.CloseKey; der pfad zur datei wird aber wie programmiert in meine Listbox eingetragen... es funktioniert also alles ausser das dann dieser hinweis kommt, weiß jemand woran das liegt ? |
Re: Problem mit Dateiaufruf per paramstr
hat niemand eine Idee ?
|
Re: Problem mit Dateiaufruf per paramstr
ich habe das mal mit dem deexec probiert, das klappt nicht bei mir öffnet er die exe trotzdem mehrmals und bringt zusätzlich nich merhmals eine Fehlermeldung. Natürlich habe ich keine DDE Komponente drauf :)
Gruß hagen |
Re: Problem mit Dateiaufruf per paramstr
man man man das ist doch zum verrückt werden :evil:
es gibt hunderte von programmen die mehr als eine datei mit einem rechtsklick öffnen können das kann doch nich so schwer sein... zum beispiel beim dateien löschen kann man doch mehr als eine gleichzeitig markeiren und alle löschen... hab hier mal nen link zum source von eraser einem Delete Tool ![]() der kann mehr als eine markierte datei auf einmal lsöchen vielleicht kann damit jemand was anfangen und da mal reinschauen.. is aber C glaube ich ... |
Re: Problem mit Dateiaufruf per paramstr
Also mit dem DDE ist das ziemlich einfach.
Als erstes in dein Formular eine TDDEServerConv rein, bei dieser den Namen auf "System" un das Event OnexecuteMacro etwa so:
Delphi-Quellcode:
Nun noch die Registry.
procedure TForm1.SystemExecuteMacro(Sender: TObject; Msg: TStrings);
begin ListBox1.Items.AddStrings(Msg); end; Zitat:
Über'n Explorer im Menu\Extras\Ordneroptionen...\Dateitypen kann man dies auch komfortabel editieren. Ich schätze mal das wars dann :) Gruß Hagen |
Re: Problem mit Dateiaufruf per paramstr
ich muss dich leider enttäuschen *gg*...
ich will ein programm bauen wie diesen eraser der dateien löscht, dazu ist es wie bereits beschrieben nötig alle möglichen dateiarten *.rtf oder *.doc oder *.txt zu markieren und dieses werte also den pfad der datei auf der platte (den ich ja zum löschen einer datei brauche) an meine exe zu senden... es nützt mir also nichts wenn ich nur dateien die eine bestimmte endung haben damit öffnen kann ... sorry :) |
Re: Problem mit Dateiaufruf per paramstr
oder ich trenne das auf in 2 exe dateien ?
den klick auf eine datei lenke ich auf die umleitung.exe die prüft ob die delete.exe schon gestartet ist, wenn nicht wird sie gestartet... danach sendet die umleitung.exe die daten paramstr an die delete.exe und beendet sich selbst... dbaei wäre es egal wie oft die umletiung exe gestartet wird da sie eh unsichtbar ist und sich selbst beendet... ist doch besser so oder ? |
Re: Problem mit Dateiaufruf per paramstr
ok ich hab die DDE Kompos drauf, hab auch schon einbeispiel gefunden dazu
![]() nur leider funktioniert es bei einem klick nur einmal und das mit der rückmeldung vom server geht nich so wie es da steht... der text aus dem memo im client wird aber korrekt an den server gesendet... hat jemand noch ein beispiel oder ähnliches dazu ? |
Re: Problem mit Dateiaufruf per paramstr
Liste der Anhänge anzeigen (Anzahl: 1)
ich verstehe dein Problem nicht. Nun habe ich mal in hKey_Classes_Root den * Eintrag für alle Dateien erweitert
Zitat:
Mit nachfolgender Registry habe ich sogar für Verzeichnise einen neuen Eintrag im Contextmenu der "Suchen" heist. Wird er angeklickt so wird korrekterweise der Project11.exe der Verzeichnisname gesendet. Zitat:
Gruß Hagen |
Re: Problem mit Dateiaufruf per paramstr
hmmm also ich hab mir dein projekt mal runtergeladen und aus dem reg zeugs ne *.reg gemacht...
nur elider passiert da gar nicht, ich hab keinen zusätzlichen punkt im context menu und kann darum auch natürlich nichts testen ... was hat das mit den @ zeichen zu bedeuten und wo wird das in die registry geschrieben ? es kam zwar die meldung das meine *.reg registriert wurde aber vielleicht ist da was schiefgegangen ich finde die einträge jedenfalls im shell ordner nicht... |
Re: Problem mit Dateiaufruf per paramstr
sooo also der schlüssel wird in der registry angelegt...
nur wurde er wie gesagt nicht im contextmenu angezeigt, also hab ich ihn mal umbenannt in 123456 und siehe da plötzlich taucht im context menu 123456 auf, open scheint nicht zu funktionieren... als ich den schlüssel wieder in open umbennnen wollte sagte die registry das dieser name bereits vorhanden wäre ??? aber nicht im ordner shell, oder dar er gar nicht doppelt vorkommen ??? jedenfalls wenn ich rechtsklick auf ne datei mache und klicke 123456 kommt die meldung Zitat:
was ist denn das nu wieder :bouncing4: *verücktwerd* :bouncing4: |
Re: Problem mit Dateiaufruf per paramstr
boahhhhhhhhhhhhhhhh icke hab et *gg*
also er hat zwar alle daten in die reg importiert aber komischerweise nicht die pfad zur exe unter command... habs soeben bemerkt und sieh da nun gehts *freu*... vielen vielen dank, für Eure (@Hagen und besonders Deine Hilfe) :bounce2: |
Re: Problem mit Dateiaufruf per paramstr
Puh schwitz, ist das Thema damit jetzt abgegessen ??
Gruß Hagen |
Re: Problem mit Dateiaufruf per paramstr
joaaahhhh is zwar nich sehr schnell wenn man mehrere dateien laden will aber ich denke damit werde ich leben müssen :)
ich brauche ne Routine die Ordner rekursiv löscht auch wenn diese Unterordner enthalten, wichtig ist sie muss mit mit DeleteFile() arbeiten... haste da ne idee ? wenn nich stell ich die frage nochmal im neuen thread ... vielen dank nochmal... |
Re: Problem mit Dateiaufruf per paramstr
Such hier im Form nach TSreachRec und du findest alles was du brauchst.
|
Re: Problem mit Dateiaufruf per paramstr
ok jetzt hab ich alles zusammen, bin fast fertig...
hab ne routine gefunden die gleich noch die atrribute ändert usw. zum löschen... nochmal vielen dank :spin: |
Re: Problem mit Dateiaufruf per paramstr
muss leider den thread nochmal fortführen...
funktioniert zwar alles aber die dde server compo ist sehr langsam :( wenn man mehrere dateien auswählt und dann mit dem programm öffnet dauert es sehr lange weil die dateien nacheinander über die compo gesendet werden ... hat jemand ne idee ? |
Re: Problem mit Dateiaufruf per paramstr
Dann bleiben nur die Shell Extensionen übrig. Diese sind sehr schnell weil man dort direkt auf die Datenstrukturen des Explorers zu greifen kann. D.h. der Explorer übergibt der ShellExtension alle selektierten Dateien. Interessant für die solltt das IContexMenu Demo im Demoordner von Delphi sein.
Gruß Hagen |
Re: Problem mit Dateiaufruf per paramstr
ich hab ne demo shellext im order activex ansonsten nichts was so ähnlich heisst ??? --> delphi 6 enterprise
|
Alle Zeitangaben in WEZ +1. Es ist jetzt 15:50 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