Comment puis-je envoyer ctrl+c pour un processus en c#?
Je suis en train d'écrire une classe wrapper pour une ligne de commande exécutable. Ce fichier exe accepte entrée à partir de stdin jusqu'à ce que j'appuie sur ctrl+c dans l'invite de commande shell, auquel cas il imprime à la sortie, l'entrée vers la sortie standard stdout. Je veux simuler que ctrl+c appuyez sur dans le code c#, l'envoi de la commande kill pour un .Net objet de processus. J'ai essayé d'appeler le Processus.kill(), mais qui ne semble pas me donner quoi que ce soit dans le processus de StandardOutput StreamReader. Pourrait-il y avoir quelque chose que je ne suis pas en train de faire? Voici le code que j'utilise:
ProcessStartInfo info = new ProcessStartInfo(exe, args);
info.RedirectStandardError = true;
info.RedirectStandardInput = true;
info.RedirectStandardOutput = true;
info.UseShellExecute = false;
Process p = Process.Start(info);
p.StandardInput.AutoFlush = true;
p.StandardInput.WriteLine(scriptcode);
p.Kill();
string error = p.StandardError.ReadToEnd();
if (!String.IsNullOrEmpty(error))
{
throw new Exception(error);
}
string output = p.StandardOutput.ReadToEnd();
cependant de sortie est toujours vide, même si je récupérer des données à partir de stdout quand je lance l'exe manuellement.
edit: c'est c# 2.0 btw
OriginalL'auteur Kevlar | 2008-11-12
Vous devez vous connecter pour publier un commentaire.
En fait, j'ai trouvé la réponse. Merci à vous deux pour vos réponses, mais il s'avère que tout ce que j'avais à faire était de ceci:
qui fait que le programme que j'ai donné naissance à terminer la lecture sur l'entrée standard et la sortie de ce dont j'ai besoin.
pourquoi il montre cette exception "StandardIn n'a pas été redirigé." ? j'utilise ffmpeg pour la capture d'écran
OriginalL'auteur Kevlar
@alonl: L'utilisateur tente d'enrouler un programme de ligne de commande. Programmes de ligne de commande n'ont pas de message pompes, sauf s'ils sont spécifiquement créés, et même si c'était le cas, Ctrl+C n'a pas la même sémantique dans un Windows-environnement (copie par défaut) comme il le fait dans un environnement de ligne de commande (Pause).
J'ai jeté cet ensemble. CtrlCClient.exe appelle tout simplement de la Console.ReadLine() et attend:
Ma sortie semble faire ce que vous voulez:
Espère que ça aide!
(À préciser: \x3 est un hex séquence d'échappement pour le hex caractère 3, qui est ctrl+c. Ce n'est pas seulement un nombre magique. 😉 )
Burg: peut-être une correction de bug dans le code de la structure? Le post a été rédigé en trois versions et > il y a 4 ans.
À préciser (Désolé pour gravedig), cela ne fonctionne pas si vous n'êtes pas la lecture à partir de stdin, comme il ne fait pas envoyer le signal
OriginalL'auteur Rob
En dépit du fait que l'utilisation de GenerateConsoleCtrlEvent pour envoyer Ctrl+C signal est une bonne réponse, il a besoin d'importantes précisions pour le faire fonctionner dans différents .NET les types d'application.
Si votre .NET application n'utilise pas sa propre console (WinForms/WPF/Service Windows/ASP.NET) flux de base est:
L'extrait de code suivant illustre comment le faire:
où SetConsoleCtrlHandler, FreeConsole, AttachConsole et GenerateConsoleCtrlEvent sont indigènes WinAPI méthodes:
Les choses deviennent plus compliquées si vous avez besoin d'envoyer Ctrl+C de .NET application console. L'approche ne fonctionnera pas car AttachConsole renvoie la valeur false dans le cas présent (console principale application dispose déjà d'une console). Il est possible d'appeler FreeConsole avant AttachConsole appel, mais comme le résultat d'origine .NET application console sera perdu qui n'est pas acceptable dans la plupart des cas.
Ma solution pour ce cas (qui fonctionne vraiment et n'a pas d'effets secondaires .NET processus principal de la console):
Cet extrait se ferme de l'application principale (WinForms) si elle est appelée deux fois. J'ai lié à une touche dans mon application, et elle le ferme, même lorsque la touche est enfoncée de plusieurs secondes d'intervalle, et l'ensemble de l'extrait est à l'intérieur d'un
lock
déclaration.OriginalL'auteur Vitaliy Fedorchenko
Ok, voici une solution.
Le moyen d'envoyer la combinaison de touches Ctrl-C signal est avec GenerateConsoleCtrlEvent. TOUTEFOIS, cet appel prend une processGroupdID paramètre, et envoie le Ctrl-C signal à tous les processus du groupe. Ce serait parfait si ce n'était pas pour le fait qu'il n'existe aucun moyen de spawn processus enfant .net qui est dans un autre groupe de processus que vous (les parents) sont dans. Alors, lorsque vous envoyez la GenerateConsoleCtrlEvent, tant pour l'enfant que VOUS (LES PARENTS), IL se. Donc, vous avez besoin pour capturer les touches ctrl-c de l'événement dans le parent de trop, et ensuite déterminer si vous nie à l'ignorent pas.
Dans mon cas, je veux que les parents d'être en mesure de gérer Ctrl-C des événements aussi, donc j'ai besoin de distnguish entre Ctrl-C événements envoyés par l'utilisateur sur la console, et ceux qui sont envoyés par le processus parent à l'enfant. Pour ce faire, j'juste hackishly réglage/annulation de la définition d'un indicateur booléen alors d'envoyer la combinaison de touches ctrl-c pour l'enfant, puis de vérification pour ce drapeau dans le parent du ctrl-c gestionnaire d'événements (ie. si envoyer ctrl-c pour l'enfant, puis de les ignorer.)
Donc, le code devrait ressembler à quelque chose comme ceci:
p.SessionId
n'est pas un bon paramètre pourGenerateConsoleCtrlEvent
.Ce code ne peut pas fonctionner. GenerateConsoleCtrlEvent nécessite des processus d'id de groupe, pas de terminal id de session.
Aux prises avec ce même problème, cette réponse ne l'a pas fait pour moi, toujours fourni une erreur 87 (paramètre non Valide). Au lieu de cela, j'ai utilisé p.Id et, bien qu'il n'a toujours pas envoyer la combinaison de touches Ctrl-C pour mon processus,
GenerateConsoleCtrlEvent
au moins ne donne pas d'erreur maintenant..Vous n'avez pas besoin d'attendre que le processus de sortie. Vous pouvez dormir pendant une période suffisamment longue pour s'assurer que tous les threads concernés par le signal ont été programmées
OriginalL'auteur James Schopp
Essayez en fait de l'envoi de la Combinaison de touches Ctrl+C, au lieu de directement la terminaison du processus:
De le rechercher sur le MSDN, vous devriez trouver ce que vous avez besoin dans le but d'y envoyer la combinaison de touches Ctrl+combinaison de touches...
Je sais que le message que vous avez besoin pour envoyer Alt+Touche est WM_SYSTEMKEYDOWN et WM_SYSTEMKEYUP, ne peut pas vous dire sur Ctrl...
OriginalL'auteur Alon L