J'ai écrit les deux fonctions suivantes et appelez la seconde ("callandwait") de JavaScript exécutant à l'intérieur de l'hôte de script Windows. Mon intention globale est d'appeler un programme de ligne de commande d'un autre. C'est-à-dire que je suis en train d'exécuter les scripts initiaux à l'aide de cscript, puis d'essayer d'exécuter quelque chose d'autre (fourmi) à partir de ce script.
function readAllFromAny(oExec) { if (!oExec.StdOut.AtEndOfStream) return oExec.StdOut.ReadLine(); if (!oExec.StdErr.AtEndOfStream) return "STDERR: " + oExec.StdErr.ReadLine(); return -1; } // Execute a command line function.... function callAndWait(execStr) { var oExec = WshShell.Exec(execStr); while (oExec.Status == 0) { WScript.Sleep(100); var output; while ( (output = readAllFromAny(oExec)) != -1) { WScript.StdOut.WriteLine(output); } } }
5 Réponses :
Oui, la fonction EXED semble être brisée en matière de sortie terminale. P>
J'ai utilisé une fonction similaire ConsumestD (E) {wscript.stdout.write (e.stdout.readall ()); wscript.sderr.write (e.sderr.readall ());} code> que j'appelle dans une boucle similaire à la vôtre. Je ne sais pas si la vérification de la ligne EOF et de lecture par ligne est meilleure ou pire. P>
Merci, j'ai eu le même problème. Cette approche semble être la seule qui fonctionne.
Tout d'abord, votre boucle est cassée en ce sens qu'elle tente toujours de lire depuis Quant à l'utilisation Une autre alternative peut être d'utiliser les méthodes de création de processus dans WMI. La manière dont les E / S standard sont traités ne sont pas claires et il ne semble pas être un moyen d'attribuer des flux spécifiques comme Fondamentalement, le système de script n'est pas conçu pour une communication / synchronisation interprocessée compliquée. p>
Remarque: les tests confirmant ce qui précède ont été effectués sur Windows XP SP2 à l'aide de la version 5.6 de script. Référence aux manuels actuels (5.8) suggère aucun changement. P> oexec.stdout code> d'abord. S'il n'y a pas de sortie réelle, il sera suspendu jusqu'à ce qu'il y soit. Vous ne verrez aucun
starr code> de sortie jusqu'à
stdout.Atendofstream code> devient vrai (probablement lorsque l'enfant se termine). Malheureusement, il n'y a pas de concept d'E / S non bloquant dans le moteur de script. Cela signifie appeler
lire code> et le recevoir immédiatement s'il n'y a pas de données dans le tampon. Ainsi, il n'y a probablement aucun moyen de faire fonctionner cette boucle comme vous le souhaitez. Deuxièmement,
wshell.run code> ne fournit aucune propriété ni méthodes pour accéder aux E / S standard du processus d'enfant. Il crée l'enfant dans une fenêtre séparée, totalement isolée du parent, à l'exception du code de retour. Cependant, si tout ce que vous voulez, c'est pouvoir voir la sortie de l'enfant, cela pourrait être acceptable. Vous pourrez également interagir avec l'enfant (entrée) mais uniquement via la nouvelle fenêtre (voir
SendKeys code>). P>
Readall () CODE>, cela serait encore pire car il collecte toutes les entrées du flux avant de revenir afin que vous ne voyiez rien du tout avant la fermeture du ruisseau. Je ne sais pas pourquoi le exemple Place le
Readall code> dans une boucle qui construit une chaîne, un seul
si (! wscript.stdin.atendofstream) code> devrait être suffisant pour éviter les exceptions. P>
stdin code> /
out code> /
ERR code >. Le seul espoir serait que l'enfant hériterait de ceux-ci du parent, mais c'est ce que vous voulez, n'est-ce pas? (Ce commentaire basé sur une idée et un peu de recherche mais pas de test réel.) P>
Une autre technique qui pourrait aider dans cette situation est de rediriger le flux d'erreur standard de la commande pour accompagner la sortie standard.
Faites cela en ajoutant "% ComSpec% / C" à l'avant et "2> & 1" à la fin de la chaîne Execstr.
C'est-à-dire, changez la commande que vous exécutez de: à: p> "2> & 1" est une instruction redirection qui provoque La sortie STDERR (descripteur de fichier 2) à écrire dans le flux STDOUT (descripteur de fichier 1).
Vous devez inclure la partie "% ComSpec% / C" car c'est l'interpréteur de commande qui comprend la redirection de la ligne de commande. Voir http://technet.microsoft.com/en-us/library/ee156605. Aspx avec ceci, votre script n'a besoin que de lire le flux STDOUT et recevra à la fois une sortie standard et une erreur standard.
J'ai utilisé cela avec "Net Stop wuauserv", qui écrit à STDOUT sur le succès (si le service est en cours d'exécution)
et STDERR sur l'échec (si le service est déjà arrêté). P> P>
L'utilisation de "% ComSpec%" au lieu de "CMD" donne une portabilité à une plage plus large de versions Windows.
Si votre commande contient des arguments de chaîne cités, il peut être difficile de les obtenir correctement:
Les spécifications pour la manière dont CMD gère des citations après "/ c" semble être incomplète. p>
Voir mon commentaire sur la réponse de Ben sur la redirection et l'utilisation de citations sur les arguments (peut être effectuée si l'exécutable n'a pas de citations)
Vous ne pouvez pas lire de cette manière sur STDERR et STDOUT dans le moteur de script, car il n'y a pas d'IO non bloquante en tant que code Master Bob Bob. Si le processus appelé remplit le tampon (environ 4 ko) sur STDERR pendant que vous essayez de lire de stdout ou inversement, vous allez alors vous échapperez / accrocherez. Vous mourrez de faim en attendant que STDOUT et il vous empêchera d'attendre que vous lisez de STDRERR.
La solution pratique consiste à rediriger stardr vers stdout comme ceci: p> Voici d'autres mots, ce qui est transmis à CreateProcess, c'est ceci: p> ceci invoque cmd.exe, qui interprète la ligne de commande. l'incantation Vous pouvez maintenant réussir en lisant de stdout et en ignorant STDOUT et STDERR. P> L'inconvénient est que la sortie STDERR et STDOUT se mélangent. Tant qu'ils sont reconnaissables, vous pouvez probablement travailler avec cela. P> p> / S / C CODE> invoque une règle d'analyse spéciale de sorte que la première et la dernière citation soit désactivée et que le reste utilisé tel est em> strong> et exécuté par cmd.exe. Donc, cmd.exe exécute ceci: p>
2> & 1 code> redirige
prog.exe code> STDROUT . Cmd.exe va propager le code de sortie. P>
Vous avez peut-être touché le problème de l'impasse décrite sur ce Site Microsoft Support .
Une suggestion est de toujours lire à partir de stdout code> et
starr code>.
Vous pouvez modifier
readallfromanany code> à: p>
Je ne pense pas qu'il y ait un moyen de faire cela, je cherchais un moment moi-même. Ma "solution" est d'avoir une fonction qui repend une commande qui définit les variables d'environnement requises chaque fois qu'une commande est appelée, comme dans wshell.exec ("% comspec% setenvars.bat & réal_program.exe"). Assez maladroit.