Programm starten und mit Knopfdruck beenden...
-
Hallo Leute!
Suche jetzt seit einigen Stunden im Internet herum und fühle mich ziemlich erschlagen von den ganzen TerminateProcess, ExitProcess, CreateProcess, GetExitCode, PROCESS_INFORMATION, etc. und kann keinen klaren Gedanken mehr fassen. Leider hab ichs noch nicht mal geschafft irgendeinen funktionierende Code zu schreiben den ich euch zeigen könnte.
Was ich machen will:
1. Benutzer klickt auf Button (genannt: "Start")
2. Dadurch startet sich ein Programm
3. Der User macht etwas mit dem Programm. Das Programm erstellt unendlich viele Meldungsfenster (das ist beabsichtigt).
4. Der Benutzer klickt nocheinmal auf den Button (umbenannt auf "Stop") und dadurch schließt sich das Programm.Dieses Feature ist ziemliche essenziell, drum quäl ich mich schon solange damit herum.
Ich hoffe einer von euch kann mir helfen...
-
Hallo
Solange es nur um die ersten drei Punkte geht, reicht ein einfaches CreateProcess oder ShellExecute. Das bedeutet das aufgerufene Programm arbeitet dann unabhängig vom aufrufenden Programm.
Wenn das aufrufende Programm das aufrufende Programm noch beenden können soll, must du aus CreateProcess/ShellExecuteEx noch die Prozeß-ID ermitteln und über TerminateProcess beenden.
Wenn das aufrufende Programm in der Laufzeit des aufgerufenen Programms auch nichts anderes mehr erlauben soll auser das Abbrechen des aufgerufenen Programms, must du mit den Flags von CreateProcess/ShellExecuteEx arbeiten und/oder WaitForSingleObject benutzten.Das alles ist aber tiefste WinAPI.
bis bald
akari
-
Dieser Thread wurde von Moderator/in akari aus dem Forum VCL (C++ Builder) in das Forum WinAPI verschoben.
Im Zweifelsfall bitte auch folgende Hinweise beachten:
C/C++ Forum :: FAQ - Sonstiges :: Wohin mit meiner Frage?Dieses Posting wurde automatisch erzeugt.
-
Vielen Dank für deine Antwort Akari. Falls jemand Zeit findet könntet ihr mir vielleicht zeigen wie genau man die Process-ID über ShellExecute abfragt? (Code)
Den Rest hab ich soweit verstanden denke ich, vielen dank nochmal...
-
ich glaube das wird dir keiner machen können,
den soviel wie ich weis wird dir die ProcessId nicht von ShellExecute zurückgegeben.
-
Hmm, ich hab das auf den vorigen Post bezogen, weil ich das so verstanden hatte.
Wäre CreateProcess die bessere Lösung oder wie würdest du das lösen?
-
@rT!f@Ct schrieb:
ich glaube das wird dir keiner machen können,
den soviel wie ich weis wird dir die ProcessId nicht von ShellExecute zurückgegeben.Hallo,
doch, das ist machbar.
Aber bei so wenig Input seitens des Fragesteller schweigen die Geister.Mit ich drücke Knopf und das tut so und so, so erklärt man kein Problem.
-
ich denke das createprocess die besser wahl für dein vorhaben ist.
-
Hmm, ich bin eigentlich Schüler an einer Schule für Graphik und beschäftige mich privat mit Interaktionsdesign. Ein guter Freund von mir ist Programmierer und daher teilen wir uns meistens die Arbeit beim entwicklen (Ich: Interface Er: Code) und üblicherweise schreibe ich einfach meine Vorstellungen genau auf, wie das Programm funktionieren soll, drum hab ichs hier genau so gemacht.
Ich post euch einfach mal den SourceCode, ich glaub aber nicht das euch das viel nutzt. Mein Problem ist eigentlich das mir die MSDN Dokumentation (und deren mir kryptischen Variablenbezeichnungen) leider nicht wirklich helfen, obwohl ich mal schwer annehme das alles drinnen steht was ich wissen muss.
Grundsätzlich schreibt der Benutzer in dem Programm in ein Textfeld Code, mit dem er die Gestaltung eines Meldungsfensters bestimmen kann (jaja, nonsense). Um dann sofort zu sehen wie das Meldungsfenster aussieht gibts in dem Programm einen Testen Button. Dabei wird das Skript gespeichert und quasi der "Interpreter" gestartet, dem vorher noch gesagt wird wo sich die Datei befindet die er interpretieren soll. Da der Nutzer aber mit seinem Skript das Programm auch absichtlich zum Absturz bringen kann will ich einen Button im Editor mit dem der Interpreter beendet werden kann.
Der Code vom Button und der Funktion RunTest() sehen derweil so aus:
void __fastcall TInterface::TestClick(TObject *Sender) { if (IncorrectCode == true) //Jap, es gibt tatsächlich ne Analyse auf Fehler { int BugFound = Application->MessageBoxA(Language->Strings[25].c_str(), Language->Strings[20].c_str(), 4+48); //Fehler im Code. Fortfahren? if (BugFound == IDYES) { RunTest (); } } if (IncorrectCode == false) { RunTest (); } }
void RunTest () { String ActivatedFileBackup; //Er testet ja nur, der Interpreter soll also nicht bei jedem Start dieses Skript ausführen, also stellt er dann den Ursprungszustand nachher wieder her. if (FilePath == "") { ActivatedFileBackup = Config->Strings[5]; Script->Assign(Interface->Edit->Lines); while (Script->Count <= 11) Script->Add (""); //nicht wundern, das passt schon so^^ Script->SaveToFile ("temp.msb"); Config->Strings[5] = "temp.msb"; Config->SaveToFile ("config.ini"); ShellExecute(0, "open", "Interpreter.exe", 0, 0, SW_SHOWNORMAL); //Bis dato hab ich also das Starten vom Interpreter so gemacht. //CreateProcess("Interpreter.exe",0,0,0,0,0,0,0,0,0); // Das war der andere Versuch, viele Nullen aber ja funktioniert eh nicht^^ Sleep (250); //wart ein bisschen und stell dann den Ursprungszustand wieder her... Config->Strings[5] = ActivatedFileBackup; Config->SaveToFile ("config.ini"); } if (FilePath != "") //Und das selbe nur halt ohne temporäres Speichern weil die Datei schonmal gespeichert wurde { ActivatedFileBackup = Config->Strings[5]; Script->Assign(Interface->Edit->Lines); Script->Assign (Interface->Edit->Lines); while (Script->Count <= 11) Script->Add(""); Script->SaveToFile (FilePath); LastSavedState->Assign (Interface->Edit->Lines); Config->Strings[5] = FilePath; Config->SaveToFile ("config.ini"); ShellExecute(0, "open", "Interpreter.exe", 0, 0, SW_SHOWNORMAL); //CreateProcess("Interpreter.exe",0,0,0,0,0,0,0,0,0); Sleep (250); Config->Strings[5] = ActivatedFileBackup; Config->SaveToFile ("config.ini"); } }
So, und zu diesem Code soll sich jetzt eben noch die Möglichkeit dazu gesellen, den verehrten Interpreter zu beenden. Wie gesagt hab ich es leider nicht geschafft das ganze selber herauszubekommen.
Ich hoffe jetzt sind die Dinge klarer
Edit: Hab den Beitrag nochmal korrigiert, ErrorPlayer.exe überall mit Interpreter.exe ersetzt.
-
Solange Du keine vernünftige IPC (Interprocess Communication) baust kann man ein gestartetes Programm nicht verlässlich und scher schließen.
- TerminateProcess ist keine wahl, es besteht das Risiko des Datenverlustes
- Du kannst WM_CLOSE an Dein programm posten, dazu benötigst Du aber das Fensterhandle, wenn der Interpreter aber keines hat, funktioniert das auch nicht.Es gibt keine einheitliche sichere Methode ein Desktop UI Programm ohne Datenverlust gezeilt zu beenden. Man kann alles mögliche versuchen, aber jedes Programm ist eben anders.
Hast Du Einfluss auf Interpreter und Player? Wenn ja ist es das sichereste hier COM zu verwenden, man kann direkt den Playerund Interpreter steuern (benötigt keine INI Datei mehr) und kann das Programm auch gezielt beenden.
-
Ich habe den Interpreter und den Editor selber geschrieben. Die config.ini enthält noch wesentlich mehr Informationen (Sprache, Einstellungen,...) daher benötige ich diese sowieso.
Sowohl Interpreter als auch Editor hab ich selber geschrieben, bzw. habe die Projektdateien und Einfluss darauf.
Inwiefern kann es zu Datenverlust kommen (welche Dateien)? Der Interpreter verändert nämlich (wissentlich) keine Dateien sondern lädt sie nur.
Der Interpreter ist ansich ein ziemlich zusammengehacktes Programm. Er besitzt ansich ein TForm Element, welches aber von Beginn an unsichtbar bleibt, da der Interpreter eigentlich nur über "Application->MessageBox ()" Informationen ausgibt.
-
Hallo
Nur der Vorständigkeit halber
@rT!f@Ct schrieb:
ich glaube das wird dir keiner machen können,
den soviel wie ich weis wird dir die ProcessId nicht von ShellExecute zurückgegeben.Nicht von ShellExecute, aber (wie ich auch im ersten Post geschrieben habe) von ShellExecuteEx. Der Übergabeparameter enthält nach der Ausführung den Handle des gestarteten Prozesses.
bis bald
akari
-
Wenn alles von Dir ist, dann kanst Du ein Event mit Namen verwenden um den Programm sein Ende mitzuteilen...
siehe CreateEvent, WaitForSingleObject