2009-05-03 8 views
3

J'essaye d'obtenir l'analyseur PHP pour exécuter une page, puis renvoyer les résultats à mon serveur, mais quand j'exécute la commande via mon code, il ne renvoie rien. Je sais que la commande est correcte parce que si je l'exécute manuellement avec le même chemin, cela fonctionne très bien. Heres mon code:C#: Problème lors de l'exécution des commandes du shell

var p = new Process 
{ 
     StartInfo = new ProcessStartInfo("C:\\xampp\\php\\php.exe", path) 
     { 
      RedirectStandardOutput = true, 
      RedirectStandardError = true, 
      UseShellExecute = false, 
      CreateNoWindow = true 
     } 
}; 
var output = new StringWriter(); 
var error = new StringWriter(); 
p.OutputDataReceived += (sender, args) => output.WriteLine(args.Data); 
p.ErrorDataReceived += (sender, args) => error.WriteLine(args.Data); 
p.Start(); 
p.BeginOutputReadLine(); 
p.BeginErrorReadLine(); 
p.WaitForExit(); 
if (p.ExitCode != 0) 
{ 
     throw new Exception(string.Format(
      "PHP failed with the following output:{0}{1}", 
     /* {0} */ Environment.NewLine, 
     /* {1} */ error.GetStringBuilder().ToString())); 
} 
var res = output.GetStringBuilder().ToString(); 
Console.WriteLine(res); 

EDIT: Avec ce code actuel, il jette l'exception dans le code sans sortie.

+0

Peut-être que si vous expliquez en détail ce que vous Essayons de faire, nous pourrions trouver de meilleures solutions. –

+0

Quand vous dites, "il ne retourne rien", voulez-vous dire res est vide après que le processus s'exécute ou qu'il ne se rétablit jamais? –

+0

Désolé, renvoie une chaîne vide –

Répondre

5

Set WorkingDirectory Chemin

var p = new Process 
      { 
       StartInfo = new ProcessStartInfo("php", path) 
       { 
        RedirectStandardOutput = true, 
        RedirectStandardError = true, 
        UseShellExecute = false, 
        CreateNoWindow = true, 
        WorkingDirectory = workingDir 
       } 
      }; 
+0

Lève une exception sur p.Start() avec ce message: "Le système ne trouve pas le fichier spécifié" –

+0

pouvez-vous élaborer sur l'erreur que vous avez? si elle ne peut pas trouver le php.exe, essayez le chemin complet par exemple: StartInfo = new ProcessStartInfo ("C: \\ xampp \\ php \\ php.exe", chemin) –

+0

Cela a fonctionné. Merci! –

5

Le problème est que vous lisez la sortie avant la fin du programme. Vous devez attendre la sortie du programme pour traiter la sortie. Sinon, vous allez traiter la sortie avant la fin de l'analyse. Ajoutez la ligne suivante dans.

p.Start(); 
p.WaitForExit(); // New line 

EDIT OP ont dit qu'ils ont encore des problèmes.

Essayez de supprimer la partie CMD de la commande. Il suffit de lancer la commande PHP directement. Il peut également être utile de permettre la création d'une fenêtre à des fins de débogage afin que vous puissiez voir les erreurs qui peuvent résulter de l'exécution de la commande.

+0

Vous m'avez, +1 :) –

+0

hrm, j'ai essayé cela, mais je semble toujours avoir le même problème –

+0

Hrm, j'ai essayé de supprimer la partie cmd, mais alors il me donne une exception qui dit "Le nom de fichier, le nom du répertoire , ou syntaxe d'étiquette de volume est incorrecte " –

1

ReadToEnd() lit simplement tout le contenu du flux tel qu'il est à ce moment-là. Étant donné que vous appelez cela immédiatement après Start(), le flux est probablement vide. Vous avez deux options

  • Appel ReadLine() à la place, mais cela ne lit qu'une ligne
  • p.WaitForExit() puis appelez ReadToEnd(), mais je ne suis pas certain ce qui maintient le flux ouvert. Si c'est le cas, alors c'est votre meilleure option.
1

Vous devez ajouter p.WaitForExit(); après le p.Start(); Sinon, la sortie n'est pas prête lorsque vous essayez de le lire.

0

Existe-t-il une raison pour laquelle vous exécutez php via cmd? Tu ne peux pas l'exécuter directement?

D'après mon expérience, l'exécution de processus via .NET est le pire moyen d'exécuter un autre processus. fork() sous unix est incroyablement beaucoup mieux. J'ai eu tellement de problèmes que mon conseil est que vous FORTEMENT envisager de regarder Process.BeginOutputReadLine() et aller la route asynchrone dans votre lecture. ReadToEnd et ReadToLine peuvent se bloquer indéfiniment, surtout si vous avez une sortie longue à capturer.

Je voudrais coller un exemple mais il est plutôt long.

+0

Je voudrais essayer cela, mais à mon avis, l'exemple sur MSDN est plutôt pauvre, pourriez-vous s'il vous plaît poster votre exemple? –

+0

La classe que j'ai écrite pour envelopper tout cela est au travail. Entre temps, la classe Gist est une classe qui définit Process.OutputDataReceived sur une méthode statique de classe qui concatène la chaîne à une chaîne de classe privée croissante. Une fois l'exécution du processus terminée, vous accédez à la chaîne via une propriété publique. Vous pouvez faire la même chose pour stderr que stdout. Effectivement, c'est ce que le processus devrait être. :) –

+0

J'ai essayé, mais ça n'a pas marché non plus. –

2

La façon la plus robuste pour invoquer le processus et capturer sa sortie ou erreur serait d'essayer de la manière suivante:

var p = new Process { 
    StartInfo = new ProcessStartInfo("php", path) { 
     RedirectStandardOutput = true, 
     RedirectStandardError = true, 
     UseShellExecute = false, 
     CreateNoWindow = true 
    } 
}; 
var output = new StringWriter(); 
var error = new StringWriter(); 
p.OutputDataReceived += (sender, args) => output.WriteLine(args.Data); 
p.ErrorDataReceived += (sender, args) => error.WriteLine(args.Data); 
p.Start(); 
p.BeginOutputReadLine(); 
p.BeginErrorReadLine(); 
p.WaitForExit(); 
if (p.ExitCode != 0) { 
    throw new Exception(string.Format(
     "PHP failed with the following output:{0}{1}", 
     /* {0} */ Environment.NewLine, 
     /* {1} */ error.GetStringBuilder().ToString())); 
} 
var res = output.GetStringBuilder().ToString(); 
Console.WriteLine(res); 
+0

OK, j'ai essayé, j'ai dû modifier la partie commande. changé pour "cmd", "/ c php" + chemin. et puis j'ai eu comme la sortie d'erreur: "'php' n'est pas reconnu comme une commande interne ou externe, programme exécutable ou fichier batch." Mais la chose étrange à propos de ceci est que la commande php fonctionne si j'ouvre l'invite de commande et l'exécute ... –

+0

Essayez de spécifier le chemin complet et absolu de l'exécutable php en tant que premier argument du constructeur ProcessStartupInfo. L'utilisation de "cmd" est une surcharge. –

+0

Ok, j'ai essayé ceci et il a jeté l'exception avec une sortie vide. –

Questions connexes