externes Programm vorzeitig beenden
-
Das verstehe es jetzt nicht ganz. Ich will doch eigentlich dem ext. Programm sagen, daß es sich beenden soll. Also wenn ich z.B. OnClose() in der Hauptanwendung aufrufe. Da muß doch das ext. Programm irgendwie eine Nachricht bekommen??
-
Nö, nciht automatisch. Wäre ja Unfug. Aber Jochen hat dir ja schon zwei Möglichkeiten aufgezeigt, wie du es "per Hand" veranlassen kannst:
Die nette Methode: "Magst dich beenden?" und der Kopfschuß
-
evil-peter schrieb:
Da muß doch das ext. Programm irgendwie eine Nachricht bekommen??
Hab ich doch eigentlich auch gesagt (oder zumindest gemeint
)... Du musst dem externen Programm eine WM_CLOSE Nachricht an das Hauptfenster schicken! (Es sei denn es handlet sich dabei um eine Consolen-Anwendung)...
-
So wollte ich das machen:
void CTest_Dialog::OnClose() { int iGedrueckt; iGedrueckt = MessageBox("Test wirklich abbrechen?","", MB_YESNO | MB_ICONQUESTION); CFile file; switch (iGedrueckt) { case IDYES: file.Remove(pfad + "\\XML\\" + user.u_strUserPath + "\\" + "Ausgabe.xml"); file.Remove(pfad + "\\XML\\" + user.u_strUserPath + "\\" + "Eingabe.xml"); file.Remove(pfad + "\\XML\\" + user.u_strUserPath + "\\" + "Auswertung.xml"); file.Remove(pfad + "\\XML\\" + user.u_strUserPath + "\\" + "Auswertung.xls"); m_fFont.DeleteObject(); t_fFont.DeleteObject(); t_bmpHintergrund.DeleteObject(); EndThread = true; TerminateProcess(m_SpeechThread->ShExecInfo.hProcess, 0);//das ist der Prozess, um den es geht OnOK(); break; case IDNO: return; break; } CDialog::OnClose(); }Nun rufe ich das OnClose in der Hauptanwendung auf und wollte halt von hier aus den Prozess beenden. Geht aber so nicht. Wie mache ich das richtig???
Edit: Es ist eine Konsolenanwendung die im Hintergrund läuft!!!
-
Jetzt habe ich das Programm mal manuell in der Konsole gestartet und dann einfach das Konsolenfenster wieder geschlossen. Und dann beendet sich das Programm. Würde es nicht vielleicht auch gehen, daß ich das in meinem Programm auch irgendwie mache???
-
Kann mir den keiner bei dem Problem helfen? Ist doch bestimmt nicht unlösbar!
Bitte Bitte!!!
-
starte die console mit CreateProcess dadurch erhälst du die ProcessID(pInfo) die du brauchst um den process wieder zu zerstöhren.
//Processinformationen zum zerstöhren der Anwendung PROCESS_INFORMATION pInfo; ZeroMemory(&pInfo,sizeof(pInfo)); char cExecute[MAX_PATH] = "C:\\Pfad\\zur\\Console.exe"; //Erstelle die Startinformationen für das Consolenfenster STARTUPINFO sInfo; ZeroMemory(&sInfo,sizeof(sInfo)); sInfo.cb = sizeof(sInfo); sInfo.dwFlags =STARTF_USESTDHANDLES|STARTF_USESHOWWINDOW; sInfo.hStdInput = NULL; sInfo.wShowWindow = SW_HIDE; //Erstelle den Consloenprocess CreateProcess(0,cExecute,0,0,TRUE, NORMAL_PRIORITY_CLASS,0,0,&sInfo,&pInfo);HANDLE hProcess = OpenProcess( PROCESS_TERMINATE, FALSE, [b]pInfo.dwProcessId[/b]); if( NULL != hProcess ) { TerminateProcess( hProcess, 0 ); } CloseHandle( hProcess );
-
Ich hoffe da kann ich dann aber auch alle Angaben machen, wie bei ShellExecuteEx!
Danke erstmal.Gruß
-
Ich dachte mir das schon, daß es da Probleme geben wird. Ich hatte ja extra ShellExecuteEx damals verwendet, weil meine Konsolenanwendung auch Parameter zum starten braucht.
Wie kann ich die den bei CreateProcess einbauen?
Und außerdem benutze ich ja auch CStrings. Die müssen ja dann auch noch irgendwie in char konvertiert werden.
Und wie soll das gehen?
Ich kenne nur die konvertierung in char* und da braucht man ja auch die Länge des Strings?
-
Jetzt habe ich das erstmal zum laufen gebracht. Es gibt aber noch Probleme.
Einmal wird das Konsolenprogramm mit verschiedenen Kommandozeilen aufgerufen. Nun verlangt CreateProcess aber einen konstanten String zum Aufruf des Programms bzw. Prozesses.
Wie kann ich das nun lösen?
-
für CString in char
CString sString = "Ich werd nen char"; char *cString = sString.GetBuffer(sString.GetLength()); MessageBox(cString );für die parameterübergabe an eine console kannst du den/die parameter mit in den Parameter 2 (LPCWSTR lpszCmdLine) der CreateProcess Function packen.
CString sExecute = "C:\\Path\\Console.exe"; CString sArgumente = "/Argument /Argument";//Wie die eizelnen argumente an die console übergeben werden bitte bei deiner console kucken char cExecute[MAXPATH]; sprintf(cExecute,"%s %s",sExecute,sArgumente); ... CreateProcess(0,cExecute,0,0,TRUE, NORMAL_PRIORITY_CLASS|CREATE_NO_WINDOW,0,0,&sInfo,&pInfo);// ...um andere parameter an deine console zu übergeben kuck dir mal bitte die STARTUPINFO struckur & die übergabeparameter der CreateProcess Funktion genauer an
mfg
LowFly
-
Wunderbar. das mit der Umwandlung hatte ich so noch nicht gekannt. Das mit dem Parameter klappte ja auch schon(siehe letzten Beitrag).
Jetzt aber doch noch ein Problem. Im Normalbetrieb soll der Prozess nicht vorzeitig beendet werden. Es wird aber nach dem Beenden eine Variable gesetzt die die Enter-Taste freigibt, damit wieder ein Prozess beim drücken ablaufen kann. Wie kriege ich heraus, wann der Prozess sich selber beendet hat?
-
wenn mich nicht alles täuscht aber ich weis es nicht genau kannst die über die STARTUPINFO
festlegen ob der zu erstellende process überwacht werden soll/kann/darf. das gibst du dem mit auf den weg.
dann muste dir nen thead mit WaitForSingleObject baun der dir das Handle (PROCESS_INFORMATION) auf den Process überwacht.
wenn das handle auf den thread nicht mehr existiert weist du das der process beendet ist.
kuck dir mal dieses beispielmfg
LowFly
-
OK habe ich jetzt. CreateProcess gibt ja einen Wert zurück. So nun müßte alles Klar sei.
Danke noch mal für die vielen Antworten!!!Beste Grüße!!
-
LowFly schrieb:
wenn mich nicht alles täuscht aber ich weis es nicht genau kannst die über die STARTUPINFO
festlegen ob der zu erstellende process überwacht werden soll/kann/darf. das gibst du dem mit auf den weg.
dann muste dir nen thead mit WaitForSingleObject baun der dir das Handle (PROCESS_INFORMATION) auf den Process überwacht.
wenn das handle auf den thread nicht mehr existiert weist du das der process beendet ist.
kuck dir mal dieses beispielmfg
LowFlySo nun habe ich das WaitForSingleObject in einen Thread ausgelagert und das klappt so ganz gut. Auch mit den ganzen Nachrichten usw. Aber jetzt kommt ein Debug Assertion Failed an der Stelle, wenn ich das ganze jetzt vorzeitig beende! Also beim return 0 vom Thread. Wie bekomme ich das den nun weg???
-
kann es vieleicht sein das da noch ein thread läuft wenn du das prog beendest.
wenn du nen thread erstellst bendest du ihn mit AfxEndThread
Ich vermute mal du erstellst einen thread in der art wie unten folgtstatic DWORD m_dwThreadExitCode;//*.h o. *cpp auserhalg jeder funktion
UINT CDialog::thrFunction(LPVOID pParam)//Eigendliche thread funktion
{
CDialog* pDialog = (CDialog*) pParam;
::GetExitCodeThread(pDialog, &m_dwThreadExitCode);
.....}
AfxEndThread(m_dwThreadExitCode,TRUE);//In die Funktion mit der du deinen dialog bendest
-
Das ist meine Thread-Run. Hier habe ich das WaitForSingleObject von dem Prozess (also von CreateProcess) "ausgelagert":
int CWarten::Run() { WaitForSingleObject(m_pOwner->pInfo.hProcess,INFINITE); CloseHandle(m_pOwner->pInfo.hThread); CloseHandle(m_pOwner->pInfo.hProcess); m_pOwner->PostMessage(WM_ENDE_SPEECH,0,0); return 0; }Den Thread selber starte ich so:
void CTest_Dialog::WartenThread(void) { BOOL a = GetExitCodeThread(m_WartenThread,test1); if(a==FALSE) { m_WartenThread = (CWarten*)AfxBeginThread(RUNTIME_CLASS(CWarten), NULL, 0, CREATE_SUSPENDED); m_WartenThread->SetOwner(this); m_WartenThread->ResumeThread(); } else{ } }So und nun beende ich ja den Thread nicht richtig sauber, wenn ich einfach das Programm beende. Ich weiß jetzt nicht so richtig, wie ich das erklären soll! Sbald ich das Programm ganz normal ablaufen lasse, ist ja auch alles in Ordnung. Weil halt der Process der vom Thread gesteuert wird sich ja richtig beendet. Aber wenn ich den Process beende, weiß ja auch der Thread nicht mehr vozu er da ist und deshalb muß der Thread halt vorzeitig beendet werden. Ja, aber wie????
-
Ich werde noch verrückt!! Wieso geht den das nicht richtig!??! Ich könnte ja nun sagen: Bei der Release-Version funktioniert es Ja. Das ist aber irgendwie nicht so richtig befriedigend. Soll ich etwa noch mal den kompletten Code posten???
-
also jetzt muß ich noch mal fragen. Ich starte also meinen externen Process mit CreateProcess. Wenn ich jetzt das einfach so lasse, kann ich nach dem Start des Processes nichts mehr machen, also mit der Eingabe, Maus und Tastatur. Nun schreibe ich einen LEEREN Thread und starte ihn genau nach dem Process und ich kann alles machen. Wieso denn das??
So und jetzt möchte ich doch einfach nur mal wissen, wann mein Process beendet ist und damit dann einen Wert setzen!! Das kann doch nicht unmöglich sein??!
Natürlich muß der Process dabei aber auch per Tastendruck abgebrochen werden können. Bei mir hat bisher eben immer nur entweder das eine oder andere richtig funktioniert??!!
-
So Jungs und Mädels, jetzt habe ich das endlich hinbekommen. Es lag einfach nur an dieser PostMessage, die der Thread bei Beendigung des Processes geschickt hat. nun habe ich einfach die Variable ohne Message geändert und schon hat es funktioniert.

Ja wer soll das denn wissen???!

Danke an alle, die mir geholfen haben!!