Autor Beitrag
F.Art
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 434



BeitragVerfasst: Mi 11.06.03 14:20 
Ich habe mein Projekt mit einem anderen Programm gejoint und möchte das wenn das Projekt gestartet wird die fremde datei in den speicher kommt oder gejoint bleibt und von meinem projekt gesteuert wird.
Andreas Pfau
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 997



BeitragVerfasst: Mi 11.06.03 16:52 
Hört sich nach einigen Dingen gleichzeitig an. Also:
- Wie du die 2. File extreheirst, ist dein Problem, duhast auch den Algo zum joinen
- Die Datei kommt auf die Festplatte. Am besten in gleiche Verzeichnis wir die 1. Anwendung, vorsicht: Dateiname prüfen, du darfst nix überschreiben! Bei überschneidung: Index anhängen ("Date0001.exe")
- OK, dann startest du die Anwendung mit
ausblenden Delphi-Quelltext
1:
2:
3:
Uses WhellApi;
{...}
ShellExecute(0Nil, PChar('Anwendung.exe'), NilNil, Sw_ShowNormal);

- Dann willst du die Anwendung steuern... wie darf ich das verstehen? Ist die 2. Anwendung von dir? Wenn ja, mit Messages, Events, MMF, DDE... es gibt viele Möglichkeiten!

_________________
Life is a bad adventure, but the graphic is really good!
F.Art Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 434



BeitragVerfasst: Mi 11.06.03 23:37 
Die Anwendung ist nicht von mir ist ein HTACCESS Generator für DOS.
Also es müss per DOS mit den PArametern gestertet werden und es entsteht eine txt datei die soll mein prog wieder einlesen und anzeigen.
Andreas Pfau
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 997



BeitragVerfasst: Do 12.06.03 16:56 
Hallo,

wenn du Parameter brauchst, füge sie doch einfach hinter dem Dateinamen in ShellExecute() ein. Wenn du den TXT-Output brauchst, öffne die Datei mit TTextfile oder so. Falls du auch noch Konsolen-Output brauchst, verwende folgende endlange Prozedur, die ich mal irgendwo gefunden und modifiziert habe:
ausblenden volle Höhe Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:
66:
67:
68:
69:
70:
71:
72:
73:
74:
75:
76:
77:
78:
79:
80:
81:
82:
83:
84:
85:
function GetConsoleOutput(const Command: Stringvar Output, Errors: TStringList): Boolean;
var
  StartupInfo: TStartupInfo;
  ProcessInfo: TProcessInformation;
  SecurityAttr: TSecurityAttributes;
  PipeOutputRead: THandle;
  PipeOutputWrite: THandle;
  PipeErrorsRead: THandle;
  PipeErrorsWrite: THandle;
  Succeed: Boolean;
  Buffer: array [0..255of Char;
  NumberOfBytesRead: DWORD;
  Stream: TMemoryStream;
begin
  //Initialisierung ProcessInfo
  FillChar(ProcessInfo, SizeOf(TProcessInformation), 0);

  //Initialisierung SecurityAttr
  FillChar(SecurityAttr, SizeOf(TSecurityAttributes), 0);
  SecurityAttr.nLength := SizeOf(SecurityAttr);
  SecurityAttr.bInheritHandle := true;
  SecurityAttr.lpSecurityDescriptor := nil;

  //Pipes erzeugen
  CreatePipe(PipeOutputRead, PipeOutputWrite, @SecurityAttr, 0);
  CreatePipe(PipeErrorsRead, PipeErrorsWrite, @SecurityAttr, 0);

  //Initialisierung StartupInfo
  FillChar(StartupInfo, SizeOf(TStartupInfo), 0);
  StartupInfo.cb:=SizeOf(StartupInfo);
  StartupInfo.hStdInput := 0;
  StartupInfo.hStdOutput := PipeOutputWrite;
  StartupInfo.hStdError := PipeErrorsWrite;
  StartupInfo.wShowWindow := sw_Hide;
  StartupInfo.dwFlags := STARTF_USESHOWWINDOW or STARTF_USESTDHANDLES;

  if  CreateProcess(nil, PChar(command), nilnil, true,
  CREATE_DEFAULT_ERROR_MODE or CREATE_NEW_CONSOLE or NORMAL_PRIORITY_CLASS, nilnil,
  StartupInfo, ProcessInfo) then begin
    result:=true;
    //Write-Pipes schließen
    CloseHandle(PipeOutputWrite);
    CloseHandle(PipeErrorsWrite);

    //Ausgabe Read-Pipe auslesen
    Stream := TMemoryStream.Create;
    try
      while true do begin
        succeed := ReadFile(PipeOutputRead, Buffer, 255, NumberOfBytesRead, nil);
        if not succeed then break;
        Stream.Write(Buffer, NumberOfBytesRead);
      end;
      Stream.Position := 0;
      Output.LoadFromStream(Stream);
    finally
      Stream.Free;
    end;
    CloseHandle(PipeOutputRead);

    //Fehler Read-Pipe auslesen
    Stream := TMemoryStream.Create;
    try
      while true do begin
        succeed := ReadFile(PipeErrorsRead, Buffer, 255, NumberOfBytesRead, nil);
        if not succeed then break;
        Stream.Write(Buffer, NumberOfBytesRead);
      end;
      Stream.Position := 0;
      Errors.LoadFromStream(Stream);
    finally
      Stream.Free;
    end;
    CloseHandle(PipeErrorsRead);

    WaitForSingleObject(ProcessInfo.hProcess, INFINITE);
    CloseHandle(ProcessInfo.hProcess);
  end
  else begin
    result:=false;
    CloseHandle(PipeOutputRead);
    CloseHandle(PipeOutputWrite);
    CloseHandle(PipeErrorsRead);
    CloseHandle(PipeErrorsWrite);
  end;
end;

Selbsterklärend.


Moderiert von user profile icontommie-lie: Code- durch Delphi-Tags ersetzt

_________________
Life is a bad adventure, but the graphic is really good!
F.Art Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 434



BeitragVerfasst: Fr 13.06.03 11:55 
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
procedure Split(Main_FileName, NewFromMain_Filename : string);
var
 MainFile  : TFileStream;
 SplitFile : TFileStream;
 HelpStr   : string[10];
 GetSize   : integer;
begin
 MainFile    := TFileStream.create(Main_FileName, fmOpenReadWrite or fmShareDenyWrite);
 try
   SplitFile := TFileStream.Create(NewFromMain_Filename, fmCreate or fmShareDenyNone);
   try
     MainFile.Position   := MainFile.Size - 11;
     MainFile.Read(HelpStr, 10);
     GetSize := StrToInt(HelpStr);
     MainFile.Position := GetSize;
     SplitFile.CopyFrom(MainFile, MainFile.Size-GetSize);
     SplitFile.Size := SplitFile.Size - 11;
     MainFile.Size :=  GetSize;
   finally
    SplitFile.Free;
   end;
 finally
  MainFile.Free;
 end;
end;


Noch ne weitere Frage:
Dieser Code splittet beide Files voneinanderer wie mache ich das das er nur die angehängt irgendwohin speichert aber nicht raus nimmt?
Es wäre auch toll wenn mir einer diesen Coder im einzelnen erklären könnte. Er ist nicht von mir.
Andreas Pfau
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 997



BeitragVerfasst: Fr 13.06.03 13:18 
Hallo,

Lass' einfach die Zeile "MainFile.Size := GetSize;" weg. Die veranlasst nämlich, dass die MainFile gekürzt wird. Also: hier dann mal die Erklärung:
ausblenden volle Höhe Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
procedure Split(Main_FileName, NewFromMain_Filename : string);
var
 MainFile  : TFileStream;
 SplitFile : TFileStream;
 HelpStr   : string[10];
 GetSize   : integer;
begin
 MainFile    := TFileStream.create(Main_FileName, fmOpenReadWrite or fmShareDenyWrite);
 try
   SplitFile := TFileStream.Create(NewFromMain_Filename, fmCreate or fmShareDenyNone);
   try
     // Zu der Position gehen, wo die Größenangabe ist
     // Streams fangen bie 0 an, d.h. 1. Byte = Index 0!!!
     MainFile.Position   := MainFile.Size - 11;
     // Länge der angehängten Datei einlesen
     MainFile.Read(HelpStr, 10);
     // Länge in String konvertieren (würde ich anders machen, aber dann müsstest dua cuh die andere Proc ändern)
     GetSize := StrToInt(HelpStr);
     // Zu der Stelle gehen, wo die angehängte Datei anfängt
     MainFile.Position := GetSize;
     // Angehängte Datei rauskopieren
     SplitFile.CopyFrom(MainFile, MainFile.Size-GetSize);
     // Neue Datei kürzen, da auch noch die Längenangabe dran ist
     SplitFile.Size := SplitFile.Size - 11;
     // Wiese Zeile würde jetzt die angeh. Datei löschen
     {MainFile.Size :=  GetSize;}
   finally
    SplitFile.Free;
   end;
 finally
  MainFile.Free;
 end;
end;


Ich hoffe, wu deißt, was Streams sind? Wenn nein, stell' dir einfach vor, das sind Objekte, mit denen man Daten speichern kann. TFileStream ist von TStream abgeleitet, und beim FileStream kommen diese Daten aus Dateien.

Übrigens: Verbesserung weil (um ein paar ns) schneller:
ausblenden Delphi-Quelltext
1:
2:
SplitFile.CopyFrom(MainFile, MainFile.Size-GetSize);
SplitFile.Size := SplitFile.Size - 11;

Ersetzen durch:
ausblenden Delphi-Quelltext
1:
SplitFile.CopyFrom(MainFile, MainFile.Size-(GetSize+10));					

Dann werden die 10 Byte der längenangabe gleich weggelassen.


Moderiert von user profile icontommie-lie: Code- durch Delphi-Tags ersetzt
Bitte demnächst Delphi-Tags verwenden, Danke!

_________________
Life is a bad adventure, but the graphic is really good!
F.Art Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 434



BeitragVerfasst: Fr 13.06.03 23:46 
OK ich werde alle Daten mal im Kopf verarbeiten und melde mich später zurück.

ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
procedure Join (Main_FileName, Hidden_Filename : string);
var
 MainFile    : TFileStream;
 HiddenFile  : TFileStream;
 SizeOfFile  : Cardinal;
 SearchWord  : string[10];
begin
 MainFile       := TFileStream.Create(Main_FileName, fmOpenReadWrite or fmShareDenyWrite);
 try
   SizeOfFile     := MainFile.Size;
   HiddenFile     := TFileStream.Create(Hidden_Filename, fmOpenRead or fmShareDenyNone);
   try
     MainFile.Seek(0, soFromEnd);
     MainFile.CopyFrom(HiddenFile, 0);
     MainFile.Seek(0, soFromEnd);
   finally
    HiddenFile.Free;
   end;
   SearchWord := IntToStr(SizeOfFile) + #0;
   MainFile.Seek(0, soFromEnd);
   MainFile.WriteBuffer(SearchWord, SizeOf(SearchWord));
 finally
  MainFile.Free;
 end;
end;


Gibt es hierbei auch noch verbesserungs Vorschläge?
F.Art Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 434



BeitragVerfasst: Sa 14.06.03 13:11 
ausblenden Delphi-Quelltext
1:
ShellExecute(0Nil, PChar('C:\MD5.exe -bcdpm test User Pw'), NilNil, Sw_ShowNormal);					


Das funktioniert nicht ganz wenn ich C:\MD5.exe nur eintrage dann öffnet sich kurz ein fenster aber sonst nicht.

Ich will auch noch eine andere fremnde anwendung starten.
ist auch ein dos programm aber sobal es gestertet wird muss mann noch eingaben machen die man nicht per parameter machen kann.wie bekomme ich die steuerung hin?

ICh möchte noch zusätzlich das wenn das projekt gestertet wird die datei raus gejoint wird egal ob das projekt umbenannt wurde, wie bekomme ich dies noch hin?
Andreas Pfau
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 997



BeitragVerfasst: Sa 14.06.03 17:41 
Hallo,

du schreibst so tolle sätze... was willst du? Ich verstehe das so, dass du EXE2 aus EXE1 extrahieren willst, egal wie EXE1 heißt? Wenn das so ist, nimm "ParamStr(0)", das gibt den ersten Konsolenparameter zurück (also den Dateinnamen).

Dass sich das Fenster nur kurz öffnet, ist klar. Das kann man meines Wissens nur umgehen, wenn man die Dateioptionen ändernt ("Beim beenden sofot schließen"). Wie man das mit der API macht, weiß ich nicht. Oder schreib' eine Batch-File, und schreib hinter den Konsolenparameter zu Starten "@Pause", das geht auch.

Parameter zur Laufzeit übergeben? Null Problemo, nimm' diese enlange Prozedur oben, die fängt alle Befehle ab, und wenn ein Eingabe erwartet wird, kannst du sie übergeben. Müsste zumindest gehen, irgendwie.

_________________
Life is a bad adventure, but the graphic is really good!
F.Art Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 434



BeitragVerfasst: Sa 14.06.03 23:20 
Ich habe leider fast nichts verstanden. Ich bin Anfänger und verstehe die Begriffe nicht so.
Also wenn ich ein dos fenster öffne und C:\MD5.exe -bcdpm test User Pw
eingebe erstellt er mir das file was ich haben möchte aber wenn das per Delphi (siehe Oben) mache nicht. Dann habe ich noch eine andere dos datei die beim normalen dos aufruf wie die MD5.exe ist aber dann zusätzlich noch eingabe aufforderung haben will. ich möchte dazu wissen wie ich das 2. programm steuern kann.
Andreas Pfau
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 997



BeitragVerfasst: Sa 14.06.03 23:45 
Hallo,

ich glaube, du musst für DOS-Anwendungen den Interpreter erst aufrufen. Das ist:
- Unter 95/98/Me "Command.com"
- Unter NT/2k/XP "Cmd.exe"
Also etwa so:
"Cmd.exe C:\Pfad\Anwendung.exe -Parameter1 -Parameter2"

_________________
Life is a bad adventure, but the graphic is really good!
F.Art Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 434



BeitragVerfasst: So 15.06.03 00:44 
Das funktioniert auch nicht. Ich denke man müsste das dos fenster offen halten als ob man die verknüpfung des dos anklicken würde
Andreas Pfau
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 997



BeitragVerfasst: So 15.06.03 11:26 
Sorry...a bin da mit meinem Latein am Ende :(

_________________
Life is a bad adventure, but the graphic is really good!
F.Art Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 434



BeitragVerfasst: So 15.06.03 11:54 
ICh möchte noch zusätzlich das wenn das projekt gestertet wird die datei raus gejoint wird egal ob das projekt umbenannt wurde, wie bekomme ich dies noch hin?
Andreas Pfau
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 997



BeitragVerfasst: So 15.06.03 13:34 
Den aktuellen Dateinamen (incl. Pfad) erfährst du mit "ParamStr(0)". Nur den Dateinamen kannst du mit "ExtractFileName()" extrahieren.

_________________
Life is a bad adventure, but the graphic is really good!
F.Art Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 434



BeitragVerfasst: So 15.06.03 14:25 
Wenn ich es so mache:
ausblenden Delphi-Quelltext
1:
Split(ParamStr(0), 'C:\Normal.exe');					

kommt immer
ausblenden Quelltext
1:
Datei D:/....exe kann nicht geöffnet werden. Der Prozess kann nicht auf die Datei zugreifen, da sie von einem anderen Prozess verwendet wird.					


und
ausblenden Delphi-Quelltext
1:
CopyFile(ParamStr(0), 'C:\Generatoren.exe', TRUE);					

will es auch nicht.
Andreas Pfau
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 997



BeitragVerfasst: So 15.06.03 18:24 
Hallo,

müsste am FileSharing liegen. Ändere
ausblenden Quelltext
1:
MainFile       := TFileStream.Create(Main_FileName, fmOpenReadWrite or fmShareDenyWrite);					

durch
ausblenden Quelltext
1:
MainFile       := TFileStream.Create(Main_FileName, fmOpenRead or fmShareDenyNone);					

Dann müsstest du eigentlich Zugriff bekommen.

_________________
Life is a bad adventure, but the graphic is really good!
F.Art Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 434



BeitragVerfasst: So 15.06.03 18:44 
THX so geht es.
Nun müsste das mit den DOS aufrufen richtig funktionieren.
Ich habe auch schon etwas mit Eine Exe-Datei in einer Applikation einbinden und sie ausführen experimentiert.
Die Exe wurde eingebunden aber das aufrufen ist noch fehlerhaft.