2016-07-08 4 views
1

Exigence:C# exécuter plusieurs commandes cmd.exe simultanément et écrire la sortie vers un fichier texte

exécuter plusieurs commandes cmd.exe simultanément et écrire la sortie vers un fichier texte en utilisant C# y compris le temps de démarrage et L'heure de fin de la commande exécutée

Notez que je veux utiliser la version 2.0 de dot net car ce code doit être exécuté sur un système d'exploitation hérité comme XP. Parallèle et fonctionnalité ConcurrentBag est sous .net version 4.5

code Résumé:

  1. créé une liste de chaînes qui contient toutes les commandes à exécuter.
  2. parcourir la liste de chaînes et de passer la commande en tant que paramètre à une classe qui a une méthode RunCommand statique (commande de chaîne)

  3. en utilisant un fil à assurer que chaque commande est exécutée dans un thread séparé en parallèle.

Problème:

Le code fonctionne très bien, mais la sortie se mélange avec des rendements de toutes les commandes lors de l'écriture à la console et je suis sûr que le même problème se poserait lors de l'écriture à déposer! Comment puis-je m'assurer que toutes les commandes exécutées en parallèle + sortie semblent soignées et non mélangées. Notez également que lorsque j'essaie d'écrire dans un fichier, cela entraîne une erreur car plusieurs processus tentent d'écrire dans le même fichier.

principal

using System; 
using System.Collections.Generic; 
using System.Diagnostics; 
using System.IO; 
using System.Text; 
using System.Threading; 
using BaileySoft.Utility; 

namespace Diagnostic_Commands 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 

      // Log file creation 
      string strDestopPath = System.Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory); 
      strDestopPath += "\\Diagnostic_Today.txt"; 
      StreamWriter w = File.AppendText(strDestopPath); 

      List<String> commands = new List<String>(); 
      commands.Add("nslookup www.google.com"); 
      commands.Add("Tracert -d www.apple.com");   
      commands.Add("ipconfig /all"); 
      commands.Add("ping www.google.com -n 10");  
      commands.Add("nslookup www.apple.com"); 


      foreach (string cmd in commands) 
      { 


        Thread tReturn = new Thread(() => { Test_Con.runCommand(cmd); }); 
        tReturn.IsBackground = true; 
        tReturn.Priority = ThreadPriority.AboveNormal; 
        tReturn.IsBackground = true; 
        tReturn.Start(); 

      } 

      Console.ReadLine(); 


     } 

    } 
} 

Classe

using System; 
using System.Collections.Generic; 
using System.Diagnostics; 
using System.Linq; 
using System.Text; 
using System.IO; 
using System.Threading; 

public static class Test_Con 
{ 
    static string d = null; 

    public static void runCommand(string command) 
    { 
     string starttime; 
     string endtime; 

     //* Create your Process 
     Process process = new Process(); 
     process.StartInfo.FileName = "cmd.exe"; 
     process.StartInfo.Arguments = "/c" + command; 

     starttime = "Started at " + DateTime.Now + "\n"; 

     process.StartInfo.UseShellExecute = false; 
     process.StartInfo.RedirectStandardOutput = true; 
     process.StartInfo.RedirectStandardError = true; 
     //* Set your output and error (asynchronous) handlers 
     process.OutputDataReceived += new DataReceivedEventHandler(OutputHandler); 
     process.ErrorDataReceived += new DataReceivedEventHandler(OutputHandler); 
     //* Start process and handlers 
     process.Start(); 
     process.BeginOutputReadLine(); 
     process.BeginErrorReadLine(); 

     process.WaitForExit(); 
     endtime = "Completed at " + DateTime.Now + "\n"; 

     d+= "========================================================================"; 
     d+= starttime + endtime ; 

     Console.WriteLine(d); 
    } 
    static void OutputHandler(object sendingProcess, DataReceivedEventArgs outLine) 
    { 
     //* Do your stuff with the output (write to console/log/StringBuilder) 
     Console.WriteLine(outLine.Data); //This will keep writing all the command output irrespective  

    } 

    } 

} 
+1

Le mieux que vous pouvez faire est d'avoir un certain type de collection (par exemple un dictionnaire de pid et chaîne), puis ajouter les sorties et quand toutes les commandes ont fini d'écrire le contenu dictionnaire au fichier. – Gusman

+1

http://stackoverflow.com/a/8055430/366904 –

+0

http://stackoverflow.com/questions/8035029/how-to-write-in-a-single-file-with-multiple-threads –

Répondre

1

Vous pouvez travailler avec parallèle et ConcurrentBag. Bellow est un exemple, mais vous devez l'améliorer.

static void Main(string[] args) 
     { 
      // Log file creation 
      var strDestopPath = System.Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory); 
      strDestopPath += "\\Diagnostic_Today.txt"; 
      var w = File.AppendText(strDestopPath); 

      var commands = new ConcurrentBag<string>(); 
      //List<String> commands = new List<String>(); 
      commands.Add("nslookup www.google.com"); 
      commands.Add("Tracert -d www.apple.com"); 
      commands.Add("ipconfig /all"); 
      commands.Add("ping www.google.com -n 10"); 
      commands.Add("nslookup www.apple.com"); 

      var results = new ConcurrentBag<Tuple<string, string>>(); 

      Parallel.ForEach(commands, cmd => { 
       new Test_Con(results).runCommand(cmd); 
      }); 


      //Your results are here: 
      foreach (var result in results) 
      { 
       Console.WriteLine("Command: {0}",result.Item1); 
       Console.WriteLine("OutPut: {0}",result.Item1); 
       Console.WriteLine("----------------------------"); 
      } 

      Console.ReadLine(); 
     } 
    } 

    public class Test_Con 
    { 
     static string d = null; 
     private ConcurrentBag<Tuple<string, string>> results; 
     private string command; 

     public Test_Con(ConcurrentBag<Tuple<string, string>> results) 
     { 
      this.results = results; 
     } 

     public void runCommand(string command) 
     { 
      this.command = command; 
      string starttime; 
      string endtime; 

      //* Create your Process 
      Process process = new Process(); 
      process.StartInfo.FileName = "cmd.exe"; 
      process.StartInfo.Arguments = "/c" + command; 

      starttime = "Started at " + DateTime.Now + "\n"; 

      process.StartInfo.UseShellExecute = false; 
      process.StartInfo.RedirectStandardOutput = true; 
      process.StartInfo.RedirectStandardError = true; 
      //* Set your output and error (asynchronous) handlers 
      process.OutputDataReceived += new DataReceivedEventHandler(OutputHandler); 
      process.ErrorDataReceived += new DataReceivedEventHandler(OutputHandler); 
      //* Start process and handlers 
      process.Start(); 
      process.BeginOutputReadLine(); 
      process.BeginErrorReadLine(); 

      process.WaitForExit(); 
      endtime = "Completed at " + DateTime.Now + "\n"; 

      d += "========================================================================"; 
      d += starttime + endtime; 

      Console.WriteLine(d); 
     } 
     void OutputHandler(object sendingProcess, DataReceivedEventArgs outLine) 
     { 
      //* Do your stuff with the output (write to console/log/StringBuilder) 
      Console.WriteLine(outLine.Data); //This will keep writing all the command output irrespective  

      results.Add(new Tuple<string, string>(command, outLine.Data)); 
     } 

    } 
+0

Notez que Je veux utiliser la version 2.0 de dot net car ce code doit être exécuté sur un système d'exploitation hérité comme XP. La fonctionnalité Parallel et ConcurrentBag est sous .net version 4.5 – Cryptonology