أعد توجيه الإخراج (stdout ، stderr) لعملية الطفل إلى نافذة الإخراج في Visual Studio

StackOverflow https://stackoverflow.com/questions/3642147

سؤال

في الوقت الحالي ، أبدأ ملف دفعة من برنامج C# الخاص بي مع:

System.Diagnostics.Process.Start(@"DoSomeStuff.bat");

ما أود أن أكون قادرًا على القيام به هو إعادة توجيه الإخراج (STDOUT و STDERR) لعملية الطفل هذه إلى نافذة الإخراج في Visual Studio (على وجه التحديد C# Express 2008).

هل من طريقة لانجاز ذلك؟

(بالإضافة إلى ذلك: لا يتم تخزين كل شيء إلى الأعصاب ثم الصعود إلى نافذة الإخراج عندما تنتهي عملية الطفل.)


(راجع للشغل: في الوقت الحالي يمكنني الحصول على stdout (ولكن ليس stderr) من الأبوين العملية لتظهر في نافذة الإخراج ، من خلال جعل برناني "تطبيق Windows" بدلاً من "تطبيق وحدة التحكم". هذا ينفجر إذا تم تشغيل البرنامج خارج Visual Studio ، ولكن هذا جيد في حالتي الخاصة.)

هل كانت مفيدة؟

المحلول

process.StartInfo.CreateNoWindow = true;
process.StartInfo.UseShellExecute = false;
process.StartInfo.RedirectStandardOutput = true;
process.OutputDataReceived += (sender, args) => Console.WriteLine(args.Data);
process.Start();
process.BeginOutputReadLine();

process.WaitForExit();

نفس الفكرة ل Error, ، فقط استبدال Output في أسماء الطريقة/الممتلكات.

نصائح أخرى

هناك تباين في هذا الأمر بالنسبة لي -نشر هذا الآن لأنني أتمنى لو وجدته في وقت سابق. لاحظ أن هذا مجرد جزء مستخرج من الكود الحقيقي ، لذلك قد تكون هناك أخطاء تافهة.

تعتمد هذه التقنية على بعض كود MSDN. ما لم أتمكن من اكتشافه هو كيفية تحديث نافذة الإخراج "على الطيران". لا يتم تحديثه إلا بعد إرجاع هذه المهمة.

// Set this to your output window Pane
private EnvDTE.OutputWindowPane _OutputPane = null;

// Methods to receive standard output and standard error

private static void StandardOutputReceiver(object sendingProcess, DataReceivedEventArgs outLine)
{
   // Receives the child process' standard output
   if (! string.IsNullOrEmpty(outLine.Data)) {
       if (_OutputPane != null)
           _OutputPane.Write(outLine.Data + Environment.NewLine);
   }
}

private static void StandardErrorReceiver(object sendingProcess, DataReceivedEventArgs errLine)
{
   // Receives the child process' standard error
   if (! string.IsNullOrEmpty(errLine.Data)) {
       if (_OutputPane != null)
           _OutputPane.Write("Error> " + errLine.Data + Environment.NewLine);
   }
}

// main code fragment
{
    // Start the new process
    ProcessStartInfo startInfo = new ProcessStartInfo(PROGRAM.EXE);
    startInfo.Arguments = COMMANDLINE;
    startInfo.WorkingDirectory = srcDir;
    startInfo.UseShellExecute = false;
    startInfo.RedirectStandardOutput = true;
    startInfo.RedirectStandardError = true;
    startInfo.CreateNoWindow = true;
    Process p = Process.Start(startInfo);
    p.OutputDataReceived += new DataReceivedEventHandler(StandardOutputReceiver);
    p.BeginOutputReadLine();
    p.ErrorDataReceived += new DataReceivedEventHandler(StandardErrorReceiver);
    p.BeginErrorReadLine();
    bool completed = p.WaitForExit(20000);
    if (!completed)
    {
        // do something here if it didn't finish in 20 seconds
    }
    p.Close();
}

ما يحدث هنا هو أن Visual Studio يعرض ناتج التصحيح من البرنامج في نافذة الإخراج. هذا هو: إذا كنت تستخدم trace.writeline ، فسيظهر في نافذة الإخراج ، بسبب المستمع التتبع الافتراضي.

بطريقة ما ، فإن تطبيق نموذج Windows الخاص بك (عندما يستخدم Console.Writeline ؛ أفترض أنك تستخدم Console.Writeline) هو أيضًا كتابة ناتج التصحيح ، ويقوم Visual Studio باختيار هذا الأمر.

لن يفعل الشيء نفسه بالنسبة للعمليات الفرعية ، إلا إذا قمت بتقاط الإخراج بشكل صريح وإعادة توجيهه إلى جانب إخراجك.

هل فكرت في استخدام أ DefaultTraceListener ?

    //Create and add a new default trace listener.
    DefaultTraceListener defaultListener;
    defaultListener = new DefaultTraceListener();
    Trace.Listeners.Add(defaultListener);
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top