2016-07-08 4 views
1

Требование:C# запускать несколько команд в cmd.exe одновременно и записать вывод в текстовый файл

запускать несколько команд в cmd.exe одновременно и записывать вывод в один текстовый файл с помощью C#, включая время начала и время окончания выполненной команды

Обратите внимание, что я хочу использовать dot net version 2.0, потому что этот код необходимо запускать на устаревшей ОС, например XP. Параллельная и ConcurrentBag функция находится в .net 4.5 версии

Код Резюме:

  1. Создан список строк который содержит все команды, которые будут выполнены.
  2. перебирать список строк и передать команду в качестве параметра класса, который имеет статический метод RunCommand (командная строка)

  3. используя нить, чтобы убедиться, что каждая команда выполняется в отдельном потоке параллельно.

Проблема:

код работает нормально, но на выходе смешивается с возвратами из всех команд при записи на консоль и я уверен, что та же самая проблема возникнет при записи в файл! Как обеспечить, чтобы все команды, выполняемые параллельно + вывод, выглядели аккуратно и не смешивались. Также обратите внимание, что когда я пытаюсь записать в файл, он ошибочно, потому что несколько процессов пытаются записать в один и тот же файл.

Главная

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(); 


     } 

    } 
} 

Класс

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

Чем лучше вы можете сделать, это иметь некоторый тип коллекции (в примере словаря PID и строки), а затем добавить выходы к нему и, когда все команды закончили писать словарной содержимое в файл. – Gusman

+1

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

+0

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

ответ

1

Вы можете работать с Параллельное и ConcurrentBag. Bellow - пример, но вы должны его улучшить.

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

Обратите внимание, что Я хочу использовать dot net версии 2.0, потому что этот код нужно запускать на устаревшей ОС, такой как XP. Параллельная и ConcurrentBag функция находится под версией .net 4.5 – Cryptonology