also ich habe jetzt ma die o.g. vorgehensweise von
Apollonius ausprobiert.
was ich (testweise) wollte ist eine datei mit dem windows öffnen-mit dialog öffnen
(rundll32.exe shell32.dll,OpenAs_RunDLL blabla.txt). der user wählt dann
ein programm aus (zum test notepad), bearbeitet die datei, und wenn das
programm beendet wird lädt mein programm die datei neu. da ich nich an irgendein
handle des vom user ausgewählten/gestarteten progamm komme, ich aber auf das ende
dieses programms warten möchte, habe ich das, wie oben in diesem thread beschrieben,
mit einem JobObject und einem IoCompletionPort gemacht.
klappt eigentlich auch ganz gut, bis auf eine kleinigkeit:
wie gesagt, zum test habe ich meien textdatei mit notepad geöffnet (über den öffnen-mit dialog).
in notepad habe ich dann über den öffnen-dialog eine andere datei geöffnet
(rechtsklick auf eine datei und dann z.B. senden an o.ä.). dies erzeugt dann einen
weiteren prozess der (logischerweise) dann ja auch zu dem jobobject gehört.
soweit ist ja auch alles ok.
wenn ich nun aber notepad schliesse, ist in dem job ja immer noch ein aktiver
prozess (das programm das über den öffnen dialog gestartet wurde).
der prozess (notepad) auf den ich warten wollte ist aber ja schon beendet.
von daher könnte mein programm ja nun "aufwachen" und mit seiner arbeit weiter
machen (textdatei neu laden). dies passiert nun aber erst, wenn der andere prozess auch
beendet wird (da ich auf ActiveProcesses = 0 teste).
kann ich nich irgendwie nur auf einen bestimmten prozess in dem jobobject warten
(den ich natürlich nachträglich erst auslesen muß, sprich nachdem der öffnen-mit
dialog das programm gestartet hat)?
ich hoffe ihr versteht was ich meine
edit:
ich habe es nun doch noch selber hingekommen (man muss nur ma in ruhe sdks lesen *g*).
wen es interessiert wie ichs gemacht hab:
Delphi-Quellcode:
procedure TForm1.Button2Click(Sender: TObject);
var
Filename:
String;
pi: windows.TProcessInformation;
hJob, hProc: THandle;
aExitCode: Cardinal;
InfoBasic: TJobObjectBasicAccountingInformation;
InfoPIDs: TJobObjectBasicProcessIdList;
Len: Cardinal;
count: integer;
PID: Cardinal;
begin
Filename := IncludeTrailingPathDelimiter(ExtractFilePath(Paramstr(0)))+'
text.txt';
Memo1.Lines.SaveToFile(Filename);
if not RunProcess('
rundll32.exe shell32.dll,OpenAs_RunDLL ' + Filename, SW_SHOW, pi)
then
raise Exception.CreateFmt('
"%s" konnte nicht gestartet werden', [Filename]);
try
hJob := CreateJobObject(
nil,
nil);
if not AssignProcessToJobObject(hJob, pi.hProcess)
then
raise Exception.Create(SysErrorMessage(GetLastError));
WaitForSingleObject(pi.hProcess, INFINITE);
count := 0;
repeat
Sleep(100);
if not QueryInformationJobObject(hJob, JobObjectBasicAccountingInformation, @InfoBasic, sizeof(InfoBasic), @Len)
then
raise Exception.Create(SysErrorMessage(GetLastError));
count := InfoBasic.ActiveProcesses;
until count >= 1;
if not QueryInformationJobObject(hJob, JobObjectBasicProcessIdList, @InfoPIDs, sizeof(InfoPIDs), @Len)
then
raise Exception.Create(SysErrorMessage(GetLastError));
if InfoPIDs.NumberOfProcessIdsInList <= 0
then
raise Exception.Create('
Prozess nicht gefunden!');
PID := InfoPIDs.ProcessIdList[0];
hProc := OpenProcess(SYNCHRONIZE, false, PID);
if hProc = 0
then
raise Exception.Create('
Kann Prozess nicht öffnen');
try
WaitForSingleObject(hProc, INFINITE);
Memo1.Lines.LoadFromFile(Filename);
finally
CloseHandle(hProc);
end;
finally
CleanUpHandles(pi);
CloseHandle(hJob);
end;
end;
der code ist nicht grade optimiert. wie gesagt, ist nur zum test gewesen.
wenn ich was falsch gemacht hab oder es anders besser geht bin ich
aber für kritik offen!
soweit ich das sehen kann geht das in diesem fall hier so ganz gut.
das ganze muß man dann vll nur ma in n thread packen damit die
anwendung nicht "einfriert".