質問

I am running a program that runs driverquery.exe command and gets back the ouput

        pProcess.StartInfo.CreateNoWindow = true;
        debugLog.WriteToLog("");
        pProcess.StartInfo.UseShellExecute = false;
        pProcess.StartInfo.RedirectStandardOutput = true;
        pProcess.StartInfo.WindowStyle =  System.Diagnostics.ProcessWindowStyle.Hidden;
        debugLog.WriteToLog("before start method");
        pProcess.Start();
        debugLog.WriteToLog("after start method");
        if (windowTitleToHide.Length > 0)
        {
            WindowsUtil.HideWindow(windowTitleToHide);
        }
        if (null != attributeName && !"".Equals(attributeName))
            Console.WriteLine(attributeName + " : ");
        debugLog.WriteToLog("before read to end");

        StreamReader reader = pProcess.StandardOutput;
        String strOutput = string.Empty;

        while (reader.Peek() > -1)
            strOutput += reader.ReadLine();

        debugLog.WriteToLog("after read to end");
        Console.WriteLine(strOutput);
        debugLog.WriteToLog("before wait for exit");
        pProcess.WaitForExit();
        debugLog.WriteToLog("after wait for exit");
        pProcess.Close();

The process takes about 30 minutes to finish.If i run the same process via cmd it always finishes in 2 minutes. I have tried using readtoend instead of readline but that also did not help. Can some tell what is wrong here? in my logs i can see the last line getting printed as before wait for exit

PS: When i see the processes in the taskmanager the driverquery.exe is running but not consuming any CPU cycles. The process calling this code is consuming about 99% CPU. I know for sure that the calling code is not doing any other task while running this code.

役に立ちましたか?

解決

I might guess the problem is related to :

while (reader.Peek() > -1)
    strOutput += reader.ReadLine();

You probably are not reading the full output of your application. If there is any pause in its output then reader.Peek() will return -1 before the application is finished its full output. If it is outputting a lot of data you may even be overflowing the output stream since your process will have given up reading after emptying the stream once. If this is the case, the child process may be generating a lot of exceptions outputting to a full stream (which will dramatically increase execution time). Profiling and debugging would tell you more about what is actually going on.

You might try an async approach like this :

pProcess.StartInfo.RedirectStandardOutput = true;
pProcess.EnableRaisingEvents = true;  // Enable events
pProcess.OutputDataReceived += outputRedirection; // hook up
pProcess.Start();
pProcess.BeginOutputReadLine();  // use async BeginOutputReadLine
pProcess.WaitForExit();

where

static void outputRedirection(object sendingProcess, 
                              DataReceivedEventArgs outLine)
{
    try
    {
        if (outLine.Data != null)
            Console.WriteLine(outLine.Data);
            // or collect the data, etc
    }
    catch (Exception ex)
    {
        Console.WriteLine(ex.Message);
        return;
    }
}

Rather than polling in a tight loop (which is likely to empty the output stream faster than the child process will fill it, and therefore fail), this waits for data to come in. Your main process will still block on the call to WaitForExit but a threadpool thread will handle the incoming events.

EDIT

Here is an SSCCE that works just fine :

    static void Main(string[] args)
    {            
        Stopwatch spw = new Stopwatch();
        spw.Start();
        Process pProcess = new Process();
        pProcess.StartInfo.FileName = "driverquery.exe";
        pProcess.StartInfo.CreateNoWindow = true;
        pProcess.StartInfo.UseShellExecute = false;
        pProcess.StartInfo.RedirectStandardOutput = true;
        pProcess.EnableRaisingEvents = true;
        pProcess.OutputDataReceived += outputRedirection;
        pProcess.Start();
        pProcess.BeginOutputReadLine();
        pProcess.WaitForExit();        
        pProcess.Close();
        spw.Stop();
        Console.WriteLine();
        Console.WriteLine("Completed in : " + 
                           spw.ElapsedMilliseconds.ToString() 
                           + "ms");
    }

Using outputRedirection as define above --> output :

enter image description here

If this isn't working for you, then please show us your complete, real code. Something else you are doing is wrong.

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top