.NET आउटपुट से कंसोल आउटपुट कैप्चर करना (C #)


130

मैं अपने .NET एप्लिकेशन से कंसोल एप्लिकेशन को कैसे लागू करूं और कंसोल में उत्पन्न सभी आउटपुट को कैप्चर करूं?

(याद रखें, मैं पहले जानकारी को किसी फ़ाइल में सहेजना नहीं चाहता और फिर उसे पुनः प्राप्त करना चाहूंगा क्योंकि मैं इसे लाइव के रूप में प्राप्त करना चाहूंगा।)



कृपया दोनों प्रश्नों पर तारीखें देखें और देखें कि कौन सा "डुप्लिकेट" है
ग्रिप्सॉफ्ट

"संभावित डुप्लिकेट" सफाई का एक तरीका है - समान प्रश्नों को बंद करने और सबसे अच्छे उत्तरों के साथ एक रखने के लिए। तारीख जरूरी नहीं है। देखें कि क्या मुझे एक डुप्लिकेट प्रश्न को बंद करने के लिए वोट देना चाहिए, भले ही यह बहुत नया हो, और उत्तर की तारीख तक अधिक हो? यदि आप सहमत हैं कि इसे स्पष्टीकरण की आवश्यकता है तो कृपया "संभावित डुप्लिकेट" स्वचालित टिप्पणी के लिए स्पष्टीकरण स्पष्टीकरण लिंक
माइकल फ्रीजिम

जवाबों:


163

यह ProcessStartInfo.RedirectStandardOutput संपत्ति का उपयोग करके आसानी से प्राप्त किया जा सकता है । एक पूर्ण नमूना लिंक्ड MSDN प्रलेखन में निहित है; एकमात्र चेतावनी यह है कि आपको अपने आवेदन के सभी आउटपुट को देखने के लिए मानक त्रुटि स्ट्रीम को पुनर्निर्देशित करना पड़ सकता है।

Process compiler = new Process();
compiler.StartInfo.FileName = "csc.exe";
compiler.StartInfo.Arguments = "/r:System.dll /out:sample.exe stdstr.cs";
compiler.StartInfo.UseShellExecute = false;
compiler.StartInfo.RedirectStandardOutput = true;
compiler.Start();    

Console.WriteLine(compiler.StandardOutput.ReadToEnd());

compiler.WaitForExit();

3
यदि आप अंत में अतिरिक्त नई लाइन नहीं चाहते हैं, तो Console.Writeइसके बजाय उपयोग करें ।
tm1

2
यह ध्यान दिया जाना चाहिए कि यदि आप कंसोल एप्लिकेशन के साथ ReadToEnd () का उपयोग करते हैं, जिसमें इनपुट के लिए उपयोगकर्ता को संकेत देने की क्षमता है। जैसे: ओवरराइट फ़ाइल: Y या N? आदि फिर ReadToEnd एक मेमोरी लीक में परिणाम कर सकता है, क्योंकि उपयोगकर्ता इनपुट की प्रतीक्षा करते समय प्रक्रिया कभी भी बाहर नहीं निकलती है। आउटपुट कैप्चर करने का सुरक्षित तरीका प्रक्रिया का उपयोग करना है ।utputDataReceived इवेंट हैंडलर और प्रक्रिया को प्राप्त करने के लिए आउटपुट के अपने आवेदन को सूचित करने दें।
बालेओस

यदि कंपाइलर .tartInfo.FileName = "csc.exe" के बाद से कोड azure webapp पर तैनात है, तो कैसे कब्जा करें; मौजूद नहीं हो सकता है!
आसिफ इकबाल

यदि कंपाइलर .tartInfo.FileName = "csc.exe" के बाद से कोड azure webapp पर तैनात है, तो कैसे कब्जा करें; मौजूद नहीं हो सकता है!
आसिफ इकबाल

37

यह @mdb से स्वीकृत उत्तर पर थोड़ा सुधार है । विशेष रूप से, हम प्रक्रिया के त्रुटि आउटपुट को भी कैप्चर करते हैं। इसके अतिरिक्त, हम इन आउटपुट को घटनाओं के माध्यम से कैप्चर करते हैं क्योंकि ReadToEnd()यदि आप त्रुटि और नियमित आउटपुट दोनों को कैप्चर करना चाहते हैं तो यह काम नहीं करता है । मुझे यह काम करने में समय लगा, क्योंकि इसके BeginxxxReadLine()बाद वास्तव में कॉल की भी आवश्यकता होती है Start()

अतुल्यकालिक तरीका:

using System.Diagnostics;

Process process = new Process();

void LaunchProcess()
{
    process.EnableRaisingEvents = true;
    process.OutputDataReceived += new System.Diagnostics.DataReceivedEventHandler(process_OutputDataReceived);
    process.ErrorDataReceived += new System.Diagnostics.DataReceivedEventHandler(process_ErrorDataReceived);
    process.Exited += new System.EventHandler(process_Exited);

    process.StartInfo.FileName = "some.exe";
    process.StartInfo.Arguments = "param1 param2";
    process.StartInfo.UseShellExecute = false;
    process.StartInfo.RedirectStandardError = true;
    process.StartInfo.RedirectStandardOutput = true;

    process.Start();
    process.BeginErrorReadLine();
    process.BeginOutputReadLine();          

    //below line is optional if we want a blocking call
    //process.WaitForExit();
}

void process_Exited(object sender, EventArgs e)
{
    Console.WriteLine(string.Format("process exited with code {0}\n", process.ExitCode.ToString()));
}

void process_ErrorDataReceived(object sender, DataReceivedEventArgs e)
{
    Console.WriteLine(e.Data + "\n");
}

void process_OutputDataReceived(object sender, DataReceivedEventArgs e)
{
    Console.WriteLine(e.Data + "\n");
}

5
धन्यवाद, युगों से यही चाह रहा था!
सी बाउर

3
धन्यवाद। यह पूर्ण है।
DrFloyd5

1
मेरे आवेदन की धन्यवाद-सूची में आपको सम्मान का स्थान मिलेगा।
मार्श-

13

अपने कंसोल प्रक्रिया को बनाते समय आउटपुट पुनर्निर्देशित करने के लिए ProcessInfo.RedirectStandardOutput का उपयोग करें ।

तब आप प्रोग्राम आउटपुट को पढ़ने के लिए Process.StandardOutput का उपयोग कर सकते हैं ।

दूसरे लिंक में एक नमूना कोड है कि यह कैसे करना है।


7

ConsoleAppLauncher एक खुला स्रोत पुस्तकालय है जो विशेष रूप से उस प्रश्न का उत्तर देने के लिए बनाया गया है। यह कंसोल में उत्पन्न सभी आउटपुट को कैप्चर करता है और कंसोल एप्लिकेशन को प्रारंभ और बंद करने के लिए सरल इंटरफ़ेस प्रदान करता है।

कंसोलऑउटपुट ईवेंट को हर बार निकाल दिया जाता है जब कंसोल द्वारा मानक / त्रुटि आउटपुट के लिए एक नई लाइन लिखी जाती है। उत्पादन क्रम का पालन करने के लिए लाइनों को कतारबद्ध और गारंटीकृत किया जाता है।

NuGet पैकेज के रूप में भी उपलब्ध है ।

पूर्ण कंसोल आउटपुट प्राप्त करने के लिए नमूना कॉल:

// Run simplest shell command and return its output.
public static string GetWindowsVersion()
{
    return ConsoleApp.Run("cmd", "/c ver").Output.Trim();
}

लाइव प्रतिक्रिया के साथ नमूना:

// Run ping.exe asynchronously and return roundtrip times back to the caller in a callback
public static void PingUrl(string url, Action<string> replyHandler)
{
    var regex = new Regex("(time=|Average = )(?<time>.*?ms)", RegexOptions.Compiled);
    var app = new ConsoleApp("ping", url);
    app.ConsoleOutput += (o, args) =>
    {
        var match = regex.Match(args.Line);
        if (match.Success)
        {
            var roundtripTime = match.Groups["time"].Value;
            replyHandler(roundtripTime);
        }
    };
    app.Run();
}

2

मैंने O2 प्लेटफ़ॉर्म (ओपन सोर्स प्रोजेक्ट) में कई सहायक तरीके जोड़े हैं जो आपको कंसोल आउटपुट और इनपुट के माध्यम से एक अन्य प्रक्रिया के साथ आसानी से बातचीत करने की अनुमति देते हैं (देखें http://code.google.com/p/o2platform/ स्रोत / ब्राउज़ / ट्रंक / O2_Scripts / एपीआई / विंडोज / CmdExe / CmdExeAPI.cs )

आपके लिए उपयोगी एपीआई भी हो सकता है जो वर्तमान प्रक्रिया के कंसोल आउटपुट (मौजूदा नियंत्रण या पॉपअप विंडो में) को देखने की अनुमति देता है। अधिक जानकारी के लिए इस ब्लॉग पोस्ट को देखें: http://o2platform.wordpress.com/2011/11/26/api_consoleout-cs-inprocess-capture-of-the-console-output/ (इस ब्लॉग में उपभोग करने के तरीके का विवरण भी है। नई प्रक्रियाओं का कंसोल आउटपुट)


तब से मैंने ConsoleOut का उपयोग करने के लिए और अधिक समर्थन जोड़ा है (इस मामले में यदि आप .NET प्रक्रिया को स्वयं शुरू करते हैं)। पर एक नज़र डालें: सी # आरईपीएल में कंसोल आउटपुट का उपयोग कैसे करें , एक देशी विंडो के रूप में VisualStudio आईडीई के लिए 'कंसोल आउट' जोड़ा जा रहा है , देखना 'कंसोल आउट' संदेश UserControls अंदर बनाया
Dinis क्रूज़

2

मैंने एक प्रतिक्रियाशील संस्करण बनाया जो stdOut और StdErr के लिए कॉलबैक स्वीकार करता है।
onStdOutऔर जैसे ही डेटा आता है (प्रक्रिया से बाहर निकलने से पहले) onStdErrको अतुल्यकालिक
रूप से कहा जाता है ।

public static Int32 RunProcess(String path,
                               String args,
                       Action<String> onStdOut = null,
                       Action<String> onStdErr = null)
    {
        var readStdOut = onStdOut != null;
        var readStdErr = onStdErr != null;

        var process = new Process
        {
            StartInfo =
            {
                FileName = path,
                Arguments = args,
                CreateNoWindow = true,
                UseShellExecute = false,
                RedirectStandardOutput = readStdOut,
                RedirectStandardError = readStdErr,
            }
        };

        process.Start();

        if (readStdOut) Task.Run(() => ReadStream(process.StandardOutput, onStdOut));
        if (readStdErr) Task.Run(() => ReadStream(process.StandardError, onStdErr));

        process.WaitForExit();

        return process.ExitCode;
    }

    private static void ReadStream(TextReader textReader, Action<String> callback)
    {
        while (true)
        {
            var line = textReader.ReadLine();
            if (line == null)
                break;

            callback(line);
        }
    }


उदाहरण उपयोग

निम्नलिखित प्रिंट के executableसाथ चलेगाargs

  • stdOut सफेद में
  • stdErr लाल रंग में

सांत्वना देने के लिए।

RunProcess(
    executable,
    args,
    s => { Console.ForegroundColor = ConsoleColor.White; Console.WriteLine(s); },
    s => { Console.ForegroundColor = ConsoleColor.Red;   Console.WriteLine(s); } 
);


1

जोड़ा process.StartInfo.**CreateNoWindow** = true;और timeout

private static void CaptureConsoleAppOutput(string exeName, string arguments, int timeoutMilliseconds, out int exitCode, out string output)
{
    using (Process process = new Process())
    {
        process.StartInfo.FileName = exeName;
        process.StartInfo.Arguments = arguments;
        process.StartInfo.UseShellExecute = false;
        process.StartInfo.RedirectStandardOutput = true;
        process.StartInfo.CreateNoWindow = true;
        process.Start();

        output = process.StandardOutput.ReadToEnd();

        bool exited = process.WaitForExit(timeoutMilliseconds);
        if (exited)
        {
            exitCode = process.ExitCode;
        }
        else
        {
            exitCode = -1;
        }
    }
}

जब आप इसका उपयोग करते हैं तो StandardOutput.ReadToEnd()यह ऐप के अंत तक अगले स्टेटमेंट में वापस नहीं आएगा। इसलिए WaitForExit (timeoutMilliseconds) में आपका टाइमआउट काम नहीं करता है! (आपका कोड हैंग हो जाएगा!)
एस codeपोरासन
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.