ProcessStartInfo "WaitForExit" पर लटका हुआ है? क्यों?


186

मेरे पास निम्नलिखित कोड हैं:

info = new System.Diagnostics.ProcessStartInfo("TheProgram.exe", String.Join(" ", args));
info.CreateNoWindow = true;
info.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden;
info.RedirectStandardOutput = true;
info.UseShellExecute = false;
System.Diagnostics.Process p = System.Diagnostics.Process.Start(info);
p.WaitForExit();
Console.WriteLine(p.StandardOutput.ReadToEnd()); //need the StandardOutput contents

मुझे पता है कि मैं जो प्रक्रिया शुरू कर रहा हूं उसका आउटपुट लगभग 7 एमबी लंबा है। विंडोज कंसोल में इसे चलाने से ठीक काम होता है। दुर्भाग्य से प्रोग्रामेटिक रूप से यह WaitForExit पर अनिश्चित काल तक लटका रहता है। नोट यह भी छोटे आउटपुट (जैसे 3KB) के लिए कोड हैंग नहीं करता है।

क्या यह संभव है कि ProcessStartInfo में आंतरिक StandardOutput 7MB को बफर नहीं कर सकता है? यदि हां, तो मुझे इसके बजाय क्या करना चाहिए? यदि नहीं, तो मैं क्या गलत कर रहा हूँ?


इसके बारे में पूर्ण स्रोत कोड के साथ कोई अंतिम समाधान?
किनिकेत

2
मैं एक ही मुद्दे पर चलता हूं और इस तरह से मैं इसे हल करने में सक्षम था stackoverflow.com/questions/2285288/…
बेडासो

6
हां, अंतिम समाधान: अंतिम दो लाइनों को स्वैप करें। यह मैनुअल में है
अमित नायडू

4
msdn से: कोड उदाहरण p.WaitForExit से पहले p.StandardOutput.ReadToEnd पर कॉल करके एक डेडलॉक स्थिति से बचा जाता है। यदि कोई पेरेंट प्रक्रिया p.StandardOutput.ReadToEnd से पहले पैरेंट कॉल p.WaitForExit कॉल करता है और एक चाइल्डलॉक स्थिति परिणाम कर सकते हैं और बच्चे की प्रक्रिया रीडायरेक्ट स्ट्रीम को भरने के लिए पर्याप्त पाठ लिखता है। मूल प्रक्रिया बच्चे की प्रक्रिया से बाहर निकलने के लिए अनिश्चित काल तक प्रतीक्षा करेगी। बच्चे की प्रक्रिया पूरी तरह से मानक Standardutut स्ट्रीम से पढ़ने के लिए माता-पिता की अनिश्चित प्रतीक्षा करेगी।
कार्लोस लियू

यह थोड़ा कष्टप्रद है कि इसे ठीक से करना कितना जटिल है। सरल कमांड लाइन के साथ इसके चारों ओर काम करने में प्रसन्न था> outputfile :)
eglasius

जवाबों:


392

समस्या यह है कि यदि आप पुनर्निर्देशित StandardOutputऔर / या StandardErrorआंतरिक बफर पूर्ण हो सकते हैं। आप जो भी आदेश का उपयोग करते हैं, वहाँ एक समस्या हो सकती है:

  • यदि आप प्रक्रिया को पढ़ने StandardOutputसे पहले बाहर निकलने की प्रतीक्षा करते हैं तो प्रक्रिया इसे लिखने की कोशिश को रोक सकती है, इसलिए प्रक्रिया कभी समाप्त नहीं होती है।
  • यदि आप StandardOutputReadToEnd का उपयोग करके पढ़ते हैं तो आपकी प्रक्रिया अवरुद्ध हो सकती है यदि प्रक्रिया कभी बंद नहीं होती है StandardOutput(उदाहरण के लिए यदि यह कभी समाप्त नहीं होती है, या यदि यह लेखन को अवरुद्ध है StandardError)।

समाधान अतुल्यकालिक रीड का उपयोग करना है ताकि यह सुनिश्चित किया जा सके कि बफर भरा हुआ नहीं है। किसी भी गतिरोध से बचने के लिए और दोनों से सभी आउटपुट एकत्र करें StandardOutputऔर StandardErrorआप यह कर सकते हैं:

संपादित करें: यदि टाइमआउट होता है तो किसी ObjectDisposedException से बचने के लिए नीचे दिए गए उत्तर देखें ।

using (Process process = new Process())
{
    process.StartInfo.FileName = filename;
    process.StartInfo.Arguments = arguments;
    process.StartInfo.UseShellExecute = false;
    process.StartInfo.RedirectStandardOutput = true;
    process.StartInfo.RedirectStandardError = true;

    StringBuilder output = new StringBuilder();
    StringBuilder error = new StringBuilder();

    using (AutoResetEvent outputWaitHandle = new AutoResetEvent(false))
    using (AutoResetEvent errorWaitHandle = new AutoResetEvent(false))
    {
        process.OutputDataReceived += (sender, e) => {
            if (e.Data == null)
            {
                outputWaitHandle.Set();
            }
            else
            {
                output.AppendLine(e.Data);
            }
        };
        process.ErrorDataReceived += (sender, e) =>
        {
            if (e.Data == null)
            {
                errorWaitHandle.Set();
            }
            else
            {
                error.AppendLine(e.Data);
            }
        };

        process.Start();

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

        if (process.WaitForExit(timeout) &&
            outputWaitHandle.WaitOne(timeout) &&
            errorWaitHandle.WaitOne(timeout))
        {
            // Process completed. Check process.ExitCode here.
        }
        else
        {
            // Timed out.
        }
    }
}

11
कोई विचार नहीं था कि आउटपुट को पुनर्निर्देशित करने से समस्या पैदा हो रही थी लेकिन निश्चित रूप से यह पर्याप्त था। इस पर मेरे सिर पर 4 घंटे का समय लगा और अपनी पोस्ट पढ़ने के बाद 5 मिनट में इसे ठीक कर दिया। अच्छा काम!
बेन ग्रिपका

1
@AlexPeck यह समस्या कंसोल ऐप के रूप में चल रही थी। हंस पसंत ने इस मुद्दे को यहां पहचाना: stackoverflow.com/a/16218470/279516
बॉब हॉर्न

5
हर बार कमांड प्रॉम्प्ट बंद हो जाता है, ऐसा प्रतीत होता है: mscorlib.dll में "System.ObjectDisposed" प्रकार का एक अनहेल्दी अपवाद अतिरिक्त जानकारी: सुरक्षित हैंडल बंद कर दिया गया है
user1663380

3
हमें उपरोक्त उपयोगकर्ता @1663380 द्वारा वर्णित एक समान समस्या थी। क्या आपको लगता है कि यह संभव है कि usingघटना संचालकों के लिए कथन प्रक्रिया के लिए कथन के ऊपर होने चाहिए using?
डेन फोर्ब्स

2
मुझे नहीं लगता कि प्रतीक्षा हैंडल की आवश्यकता है। Msdn के अनुसार, बस WaitForExit के गैर-टाइमआउट संस्करण के साथ समाप्त करें: जब मानक आउटपुट को अतुल्यकालिक ईवेंट हैंडलर्स पर पुनर्निर्देशित किया गया है, तो संभव है कि जब यह विधि वापस आती है तो आउटपुट प्रोसेसिंग पूरा नहीं हुआ होगा। यह सुनिश्चित करने के लिए कि अतुल्यकालिक ईवेंट हैंडलिंग पूरी हो गई है, WaitForExit () अधिभार को कॉल करें जो इस अधिभार से एक सच्चे प्राप्त करने के बाद कोई पैरामीटर नहीं लेता है।
पैट्रिक

98

प्रलेखन के लिए Process.StandardOutputपढ़ने के लिए इससे पहले कि आप इंतजार अन्यथा आप गतिरोध कर सकते हैं, नीचे की नकल की झलकी का कहना है:

 // Start the child process.
 Process p = new Process();
 // Redirect the output stream of the child process.
 p.StartInfo.UseShellExecute = false;
 p.StartInfo.RedirectStandardOutput = true;
 p.StartInfo.FileName = "Write500Lines.exe";
 p.Start();
 // Do not wait for the child process to exit before
 // reading to the end of its redirected stream.
 // p.WaitForExit();
 // Read the output stream first and then wait.
 string output = p.StandardOutput.ReadToEnd();
 p.WaitForExit();

14
मैं 100% निश्चित नहीं हूं अगर यह सिर्फ मेरे पर्यावरण का परिणाम है, लेकिन मैंने पाया कि अगर आपने सेट किया है RedirectStandardOutput = true;और p.StandardOutput.ReadToEnd();आप एक डेडलॉक / हैंग का उपयोग नहीं करते हैं।
क्रिस एस

3
सच। मैं ऐसी ही स्थिति में था। मैं बिना किसी कारण के लिए StandardError को पुनर्निर्देशित कर रहा था जब एक प्रक्रिया में ffmpeg के साथ परिवर्तित हो रहा था, यह एक गतिरोध बनाने के लिए StandardError स्ट्रीम में पर्याप्त रूप से लिख रहा था।
लीनो पेल्लेटियर

यह अभी भी मेरे लिए लटकी हुई है और यहां तक ​​कि मानक आउटपुट को रीडायरेक्ट करने और पढ़ने के लिए भी।
user3791372

@ user3791372 मुझे लगता है कि यह केवल तभी लागू होता है जब StandardOutput के पीछे का बफर पूरी तरह से भरा हुआ न हो। यहां MSDN अपना न्याय नहीं करता है। एक बढ़िया लेख जिसे मैं आपको पढ़ने के लिए सुझाऊंगा
Cary

19

मार्क बायर्स का उत्तर उत्कृष्ट है, लेकिन मैं निम्नलिखित जोड़ना चाहूंगा:

OutputDataReceivedऔर ErrorDataReceivedप्रतिनिधियों से पहले हटा दिया जाना करने की जरूरत है outputWaitHandleऔर errorWaitHandleनिपटारा मिलता है। यदि समय-सीमा पार होने के बाद प्रक्रिया डेटा को जारी रखती है और फिर समाप्त हो जाती है, outputWaitHandleऔर errorWaitHandleचर का निपटान होने के बाद पहुँचा जा सकेगा।

(FYI करें मुझे एक उत्तर के रूप में इस चेतावनी को जोड़ना था क्योंकि मैं उनकी पोस्ट पर टिप्पणी नहीं कर सकता था।)


2
शायद रद्द करना बेहतर होगा ।
मार्क बायर्स

मार्क के संपादित कोड को इस उत्तर में जोड़ना भयानक नहीं होगा! मैं मिनट में एक ही मुद्दा रहा हूँ।
इयानबेली

8
@ianbailey इसे हल करने का सबसे आसान तरीका है, (AutoResetEvent errorWaitHandle ...)
डिडिएर A.

17

जब प्रक्रिया समाप्त हो जाती है, तो बिना ऑब्जेक्ट किए गए ऑब्जेक्ट अपवाद के साथ समस्या होती है। ऐसी स्थिति में स्थिति के अन्य भाग:

if (process.WaitForExit(timeout) 
    && outputWaitHandle.WaitOne(timeout) 
    && errorWaitHandle.WaitOne(timeout))

निष्पादित नहीं कर रहे हैं। मैंने इस समस्या को निम्नलिखित तरीके से हल किया:

using (AutoResetEvent outputWaitHandle = new AutoResetEvent(false))
using (AutoResetEvent errorWaitHandle = new AutoResetEvent(false))
{
    using (Process process = new Process())
    {
        // preparing ProcessStartInfo

        try
        {
            process.OutputDataReceived += (sender, e) =>
                {
                    if (e.Data == null)
                    {
                        outputWaitHandle.Set();
                    }
                    else
                    {
                        outputBuilder.AppendLine(e.Data);
                    }
                };
            process.ErrorDataReceived += (sender, e) =>
                {
                    if (e.Data == null)
                    {
                        errorWaitHandle.Set();
                    }
                    else
                    {
                        errorBuilder.AppendLine(e.Data);
                    }
                };

            process.Start();

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

            if (process.WaitForExit(timeout))
            {
                exitCode = process.ExitCode;
            }
            else
            {
                // timed out
            }

            output = outputBuilder.ToString();
        }
        finally
        {
            outputWaitHandle.WaitOne(timeout);
            errorWaitHandle.WaitOne(timeout);
        }
    }
}

1
पूर्णता की खातिर, यह अनुप्रेषितों को सही करने में चूक कर रहा है
knocte

और मैंने अपने अंत समय में टाइमआउट निकाल दिया है क्योंकि प्रक्रिया उपयोगकर्ता इनपुट के लिए पूछ सकती है (उदाहरण के लिए कुछ टाइप करें) इसलिए मुझे उपयोगकर्ता को तेज होने की आवश्यकता नहीं है
नोवोक्टे

तुम क्यों बदल दिया है outputऔर errorकरने के लिए outputBuilder? क्या कोई कृपया पूर्ण उत्तर प्रदान कर सकता है जो काम करता है?
Marko Avlijaš

System.ObjectDisposedException: सुरक्षित हैंडल बंद कर दिया गया है इस संस्करण पर मेरे लिए भी होता है
मैट

17

यह एक और अधिक आधुनिक प्रतीक्षा योग्य है। टास्क पैरेलल लाइब्रेरी (टीपीएल) .NET 4.5 और इसके बाद के संस्करण के लिए आधारित समाधान है।

उपयोग उदाहरण

try
{
    var exitCode = await StartProcess(
        "dotnet", 
        "--version", 
        @"C:\",
        10000, 
        Console.Out, 
        Console.Out);
    Console.WriteLine($"Process Exited with Exit Code {exitCode}!");
}
catch (TaskCanceledException)
{
    Console.WriteLine("Process Timed Out!");
}

कार्यान्वयन

public static async Task<int> StartProcess(
    string filename,
    string arguments,
    string workingDirectory= null,
    int? timeout = null,
    TextWriter outputTextWriter = null,
    TextWriter errorTextWriter = null)
{
    using (var process = new Process()
    {
        StartInfo = new ProcessStartInfo()
        {
            CreateNoWindow = true,
            Arguments = arguments,
            FileName = filename,
            RedirectStandardOutput = outputTextWriter != null,
            RedirectStandardError = errorTextWriter != null,
            UseShellExecute = false,
            WorkingDirectory = workingDirectory
        }
    })
    {
        var cancellationTokenSource = timeout.HasValue ?
            new CancellationTokenSource(timeout.Value) :
            new CancellationTokenSource();

        process.Start();

        var tasks = new List<Task>(3) { process.WaitForExitAsync(cancellationTokenSource.Token) };
        if (outputTextWriter != null)
        {
            tasks.Add(ReadAsync(
                x =>
                {
                    process.OutputDataReceived += x;
                    process.BeginOutputReadLine();
                },
                x => process.OutputDataReceived -= x,
                outputTextWriter,
                cancellationTokenSource.Token));
        }

        if (errorTextWriter != null)
        {
            tasks.Add(ReadAsync(
                x =>
                {
                    process.ErrorDataReceived += x;
                    process.BeginErrorReadLine();
                },
                x => process.ErrorDataReceived -= x,
                errorTextWriter,
                cancellationTokenSource.Token));
        }

        await Task.WhenAll(tasks);
        return process.ExitCode;
    }
}

/// <summary>
/// Waits asynchronously for the process to exit.
/// </summary>
/// <param name="process">The process to wait for cancellation.</param>
/// <param name="cancellationToken">A cancellation token. If invoked, the task will return
/// immediately as cancelled.</param>
/// <returns>A Task representing waiting for the process to end.</returns>
public static Task WaitForExitAsync(
    this Process process,
    CancellationToken cancellationToken = default(CancellationToken))
{
    process.EnableRaisingEvents = true;

    var taskCompletionSource = new TaskCompletionSource<object>();

    EventHandler handler = null;
    handler = (sender, args) =>
    {
        process.Exited -= handler;
        taskCompletionSource.TrySetResult(null);
    };
    process.Exited += handler;

    if (cancellationToken != default(CancellationToken))
    {
        cancellationToken.Register(
            () =>
            {
                process.Exited -= handler;
                taskCompletionSource.TrySetCanceled();
            });
    }

    return taskCompletionSource.Task;
}

/// <summary>
/// Reads the data from the specified data recieved event and writes it to the
/// <paramref name="textWriter"/>.
/// </summary>
/// <param name="addHandler">Adds the event handler.</param>
/// <param name="removeHandler">Removes the event handler.</param>
/// <param name="textWriter">The text writer.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>A task representing the asynchronous operation.</returns>
public static Task ReadAsync(
    this Action<DataReceivedEventHandler> addHandler,
    Action<DataReceivedEventHandler> removeHandler,
    TextWriter textWriter,
    CancellationToken cancellationToken = default(CancellationToken))
{
    var taskCompletionSource = new TaskCompletionSource<object>();

    DataReceivedEventHandler handler = null;
    handler = new DataReceivedEventHandler(
        (sender, e) =>
        {
            if (e.Data == null)
            {
                removeHandler(handler);
                taskCompletionSource.TrySetResult(null);
            }
            else
            {
                textWriter.WriteLine(e.Data);
            }
        });

    addHandler(handler);

    if (cancellationToken != default(CancellationToken))
    {
        cancellationToken.Register(
            () =>
            {
                removeHandler(handler);
                taskCompletionSource.TrySetCanceled();
            });
    }

    return taskCompletionSource.Task;
}

2
तिथि करने के लिए सबसे अच्छा और सबसे पूरा जवाब
टर्मोक्स

1
कुछ रीऑन के लिए, यह एकमात्र समाधान था जो मेरे लिए काम करता था, आवेदन बंद हो गया।
जैक

1
ऐसा लगता है, आप उस स्थिति को नहीं संभालते हैं, जहां प्रक्रिया शुरू होने के बाद समाप्त हो जाती है, लेकिन इससे पहले कि एक्साइटेड घटना जुड़ी हुई थी। मेरा सुझाव है - सभी पंजीकरण के बाद प्रक्रिया शुरू करना।
स्टास बॉयरविंस

@StasBoyarincev धन्यवाद, अद्यतन। मैं इस बदलाव के साथ StackOverflow उत्तर को अपडेट करना भूल गया था।
मुहम्मद रेहान सईद

1
@MuhammadRehanSaeed फिर भी एक और बात - ऐसा लगता है कि कॉल प्रक्रिया की अनुमति नहीं है। BeginOutputReadLine () या process.BeginErrorReadLine () process.Start से पहले। इस मामले में मुझे त्रुटि मिलती है: StandardOut को पुनर्निर्देशित नहीं किया गया है या प्रक्रिया अभी तक शुरू नहीं हुई है।
स्टास बॉयरविंस

8

रोब ने इसका उत्तर दिया और मुझे कुछ घंटों के परीक्षण से बचाया। प्रतीक्षा से पहले आउटपुट / त्रुटि बफर पढ़ें:

// Read the output stream first and then wait.
string output = p.StandardOutput.ReadToEnd();
p.WaitForExit();

1
लेकिन क्या होगा यदि आपके द्वारा कॉल किए जाने के बाद अधिक डेटा आता है WaitForExit()?
नोवोक्टे

मेरे परीक्षण के आधार पर @knocte, ReadToEndया सभी डेटा पढ़ने के StandardOutput.BaseStream.CopyToबाद इसी तरह के तरीके (जैसे ) वापस आ जाएंगे । इसके बाद कुछ नहीं आएगा
S.Serpooshan

आप कह रहे हैं कि ReadToEnd () भी बाहर निकलने का इंतजार करता है?
knocte

2
@knocte आप Microsoft द्वारा बनाए गए API की समझ बनाने की कोशिश कर रहे हैं?
आगा

संबंधित MSDN पृष्ठ की समस्या यह है कि यह नहीं बताया कि StandardOutput के पीछे बफ़र भरा हो सकता है और उस स्थिति में बच्चे को लिखना बंद कर देना चाहिए और जब तक कि बफर ख़त्म नहीं हो जाता है (अभिभावक बफ़र में डेटा को दूर पढ़ते हैं) । ReadToEnd () केवल तब तक synch-ly पढ़ सकता है जब तक कि बफर बंद नहीं होता है या बफर भरा हुआ है, या बच्चा बफर से भरा हुआ है। यही मेरी समझ है।
Cary

7

हमारे पास यह मुद्दा (या एक संस्करण) भी है।

निम्नलिखित प्रयास करें:

1) p.WaFForExit (nnnn) के लिए एक समय सीमा जोड़ें; जहां nnnn मिलीसेकंड में है।

2) WaitForExit कॉल से पहले ReadToEnd कॉल लगाएं। यह वही है जो हमने एमएस की सिफारिश को देखा है।


5

करने के लिए क्रेडिट EM0 के लिए https://stackoverflow.com/a/17600012/4151626

अन्य समाधान (EM0 सहित) अभी भी मेरे आवेदन के लिए गतिरोध, आंतरिक समयबाह्य और मानक अनुप्रयोग और मानक अनुप्रयोग के द्वारा दोनों के उपयोग के कारण गतिरोध है। यहाँ मेरे लिए क्या काम किया गया है:

Process p = new Process()
{
  StartInfo = new ProcessStartInfo()
  {
    FileName = exe,
    Arguments = args,
    UseShellExecute = false,
    RedirectStandardOutput = true,
    RedirectStandardError = true
  }
};
p.Start();

string cv_error = null;
Thread et = new Thread(() => { cv_error = p.StandardError.ReadToEnd(); });
et.Start();

string cv_out = null;
Thread ot = new Thread(() => { cv_out = p.StandardOutput.ReadToEnd(); });
ot.Start();

p.WaitForExit();
ot.Join();
et.Join();

संपादित करें: कोड नमूने के लिए StartInfo का जोड़ा गया प्रारंभ


यह वही है जो मैं उपयोग करता हूं और कभी भी गतिरोध के साथ कोई समस्या नहीं थी।
रोमर

3

मैंने इसे इस तरह हल किया:

            Process proc = new Process();
            proc.StartInfo.FileName = batchFile;
            proc.StartInfo.UseShellExecute = false;
            proc.StartInfo.CreateNoWindow = true;
            proc.StartInfo.RedirectStandardError = true;
            proc.StartInfo.RedirectStandardInput = true;
            proc.StartInfo.RedirectStandardOutput = true;
            proc.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;      
            proc.Start();
            StreamWriter streamWriter = proc.StandardInput;
            StreamReader outputReader = proc.StandardOutput;
            StreamReader errorReader = proc.StandardError;
            while (!outputReader.EndOfStream)
            {
                string text = outputReader.ReadLine();                    
                streamWriter.WriteLine(text);
            }

            while (!errorReader.EndOfStream)
            {                   
                string text = errorReader.ReadLine();
                streamWriter.WriteLine(text);
            }

            streamWriter.Close();
            proc.WaitForExit();

मैंने इनपुट, आउटपुट और एरर दोनों को रीडायरेक्ट किया और आउटपुट और एरर स्ट्रीम से रीडिंग को हैंडल किया। यह समाधान एसडीके 7- 8.1, विंडोज 7 और विंडोज 8 दोनों के लिए काम करता है


2
एलिना: आपके उत्तर के लिए धन्यवाद। इस MSDN doc ( msdn.microsoft.com/en-us/library/… ) के निचले भाग में कुछ नोट्स हैं जो संभावित गतिरोधों के बारे में चेतावनी देते हैं यदि आप दोनों रीडायरेक्ट स्टडआउट और स्ट्राइडर स्ट्रीम के अंत में पढ़ते हैं। यह बताना मुश्किल है कि क्या आपका समाधान इस मुद्दे के लिए अतिसंवेदनशील है। इसके अलावा, ऐसा प्रतीत होता है कि आप प्रक्रिया 'stdout / stderr आउटपुट' को वापस इनपुट के रूप में भेज रहे हैं। क्यों? :)
मैथ्यू पियाट

3

मैंने एक वर्ग बनाने की कोशिश की जो आपकी समस्या को अतुल्यकालिक स्ट्रीम रीड का उपयोग करके हल करेगा, मार्क बायर्स, रोब, स्टीवन संजय जवाबों को ध्यान में रखकर। ऐसा करने से मुझे महसूस हुआ कि अतुल्यकालिक प्रक्रिया आउटपुट स्ट्रीम से संबंधित एक बग है।

मैंने Microsoft पर उस बग की सूचना दी: https://connect.microsoft.com/VisualStudio/feedback/details/3119304

सारांश:

आप ऐसा नहीं कर सकते:

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

आपको System.InvalidOperationException प्राप्त होगी: StandardOut को पुनर्निर्देशित नहीं किया गया है या प्रक्रिया अभी तक शुरू नहीं हुई है।

================================================== ================================================== ========================

फिर आपको प्रक्रिया शुरू होने के बाद एसिंक्रोनस आउटपुट पढ़ना शुरू करना होगा:

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

ऐसा करने से, एक दौड़ की स्थिति बनाएं क्योंकि आउटपुट स्ट्रीम डेटा प्राप्त कर सकती है इससे पहले कि आप इसे अतुल्यकालिक में सेट करें:

process.Start(); 
// Here the operating system could give the cpu to another thread.  
// For example, the newly created thread (Process) and it could start writing to the output
// immediately before next line would execute. 
// That create a race condition.
process.BeginOutputReadLine();

================================================== ================================================== ========================

फिर कुछ लोग कह सकते हैं कि आपको बस एसिंक्रोनस पर सेट करने से पहले स्ट्रीम को पढ़ना होगा। लेकिन वही समस्या होती है। सिंक्रोनस रीड और स्ट्रीम को अतुल्यकालिक मोड में सेट करने के बीच एक दौड़ की स्थिति होगी।

================================================== ================================================== ========================

वास्तविक तरीके से "प्रोसेस" और "प्रोसेसस्टार्टइन्फो" की एक प्रक्रिया के आउटपुट स्ट्रीम के सुरक्षित एसिंक्रोनस रीड को प्राप्त करने का कोई तरीका नहीं है।

आप शायद अपने मामले के लिए अन्य उपयोगकर्ताओं द्वारा सुझाए गए अतुल्यकालिक पाठ का उपयोग करके बेहतर हैं। लेकिन आपको इस बात की जानकारी होनी चाहिए कि आप दौड़ की स्थिति के कारण कुछ जानकारी को मिस कर सकते हैं।


1

मुझे लगता है कि यह सरल और बेहतर तरीका है (हमें इसकी आवश्यकता नहीं है AutoResetEvent):

public static string GGSCIShell(string Path, string Command)
{
    using (Process process = new Process())
    {
        process.StartInfo.WorkingDirectory = Path;
        process.StartInfo.FileName = Path + @"\ggsci.exe";
        process.StartInfo.CreateNoWindow = true;
        process.StartInfo.RedirectStandardOutput = true;
        process.StartInfo.RedirectStandardInput = true;
        process.StartInfo.UseShellExecute = false;

        StringBuilder output = new StringBuilder();
        process.OutputDataReceived += (sender, e) =>
        {
            if (e.Data != null)
            {
                output.AppendLine(e.Data);
            }
        };

        process.Start();
        process.StandardInput.WriteLine(Command);
        process.BeginOutputReadLine();


        int timeoutParts = 10;
        int timeoutPart = (int)TIMEOUT / timeoutParts;
        do
        {
            Thread.Sleep(500);//sometimes halv scond is enough to empty output buff (therefore "exit" will be accepted without "timeoutPart" waiting)
            process.StandardInput.WriteLine("exit");
            timeoutParts--;
        }
        while (!process.WaitForExit(timeoutPart) && timeoutParts > 0);

        if (timeoutParts <= 0)
        {
            output.AppendLine("------ GGSCIShell TIMEOUT: " + TIMEOUT + "ms ------");
        }

        string result = output.ToString();
        return result;
    }
}

यह सच है, लेकिन क्या आपको .FileName = Path + @"\ggsci.exe" + @" < obeycommand.txt"अपना कोड भी आसान नहीं करना चाहिए ? या हो सकता है कि "echo command | " + Path + @"\ggsci.exe"अगर आप वास्तव में एक अलग obeycommand.txt फ़ाइल का उपयोग नहीं करना चाहते हैं तो इसके बराबर कुछ ।
अमित नायडू

3
आपके समाधान के लिए AutoResetEvent की आवश्यकता नहीं है लेकिन आप मतदान करते हैं। जब आप ईवेंट का उपयोग करने के बजाय चुनाव करते हैं (जब वे उपलब्ध होते हैं) तब आप बिना किसी कारण के सीपीयू का उपयोग कर रहे हैं और यह दर्शाता है कि आप एक खराब प्रोग्रामर हैं। AutoResetEvent का उपयोग करते हुए दूसरे के साथ तुलना करने पर आपका समाधान वास्तव में खराब है। (लेकिन मैंने आपको -1 नहीं दिया क्योंकि आपने मदद करने की कोशिश की थी!)।
एरिक ओउलेट

1

ऊपर दिए गए जवाबों में से कोई भी काम नहीं कर रहा है।

रॉब सॉल्यूशन हैंग हो जाता है और 'मार्क बायर्स' सॉल्यूशन को डिस्पोजल अपवाद मिल जाता है। (मैंने दूसरे जवाबों के "सॉल्यूशंस" की कोशिश की)।

इसलिए मैंने एक और उपाय सुझाने का फैसला किया:

public void GetProcessOutputWithTimeout(Process process, int timeoutSec, CancellationToken token, out string output, out int exitCode)
{
    string outputLocal = "";  int localExitCode = -1;
    var task = System.Threading.Tasks.Task.Factory.StartNew(() =>
    {
        outputLocal = process.StandardOutput.ReadToEnd();
        process.WaitForExit();
        localExitCode = process.ExitCode;
    }, token);

    if (task.Wait(timeoutSec, token))
    {
        output = outputLocal;
        exitCode = localExitCode;
    }
    else
    {
        exitCode = -1;
        output = "";
    }
}

using (var process = new Process())
{
    process.StartInfo = ...;
    process.Start();
    string outputUnicode; int exitCode;
    GetProcessOutputWithTimeout(process, PROCESS_TIMEOUT, out outputUnicode, out exitCode);
}

यह कोड डीबग किया गया और पूरी तरह से काम करता है।


1
अच्छा! बस ध्यान दें कि टोकन पैरामीटर कॉलिंग GetProcessOutputWithTimeoutविधि प्रदान नहीं किया जाता है ।
एस। सेरपोशन

1

परिचय

वर्तमान में स्वीकृत उत्तर काम नहीं करता है (अपवाद को फेंकता है) और बहुत सारे वर्कआर्ड हैं, लेकिन कोई पूर्ण कोड नहीं है। यह स्पष्ट रूप से बहुत से लोगों का समय बर्बाद कर रहा है क्योंकि यह एक लोकप्रिय प्रश्न है।

मार्क बायर्स के उत्तर और करोल टायल के उत्तर को मिलाते हुए मैंने पूर्ण कोड लिखा कि मैं प्रक्रिया का उपयोग कैसे करना चाहता हूं।

प्रयोग

मैंने इसे git कमांड के आसपास प्रोग्रेस डायलॉग बनाने के लिए उपयोग किया है। इस तरह मैंने इसका उपयोग किया है:

    private bool Run(string fullCommand)
    {
        Error = "";
        int timeout = 5000;

        var result = ProcessNoBS.Start(
            filename: @"C:\Program Files\Git\cmd\git.exe",
            arguments: fullCommand,
            timeoutInMs: timeout,
            workingDir: @"C:\test");

        if (result.hasTimedOut)
        {
            Error = String.Format("Timeout ({0} sec)", timeout/1000);
            return false;
        }

        if (result.ExitCode != 0)
        {
            Error = (String.IsNullOrWhiteSpace(result.stderr)) 
                ? result.stdout : result.stderr;
            return false;
        }

        return true;
    }

सिद्धांत रूप में आप stdout और stderr को भी जोड़ सकते हैं, लेकिन मैंने इसका परीक्षण नहीं किया है।

कोड

public struct ProcessResult
{
    public string stdout;
    public string stderr;
    public bool hasTimedOut;
    private int? exitCode;

    public ProcessResult(bool hasTimedOut = true)
    {
        this.hasTimedOut = hasTimedOut;
        stdout = null;
        stderr = null;
        exitCode = null;
    }

    public int ExitCode
    {
        get 
        {
            if (hasTimedOut)
                throw new InvalidOperationException(
                    "There was no exit code - process has timed out.");

            return (int)exitCode;
        }
        set
        {
            exitCode = value;
        }
    }
}

public class ProcessNoBS
{
    public static ProcessResult Start(string filename, string arguments,
        string workingDir = null, int timeoutInMs = 5000,
        bool combineStdoutAndStderr = false)
    {
        using (AutoResetEvent outputWaitHandle = new AutoResetEvent(false))
        using (AutoResetEvent errorWaitHandle = new AutoResetEvent(false))
        {
            using (var process = new Process())
            {
                var info = new ProcessStartInfo();

                info.CreateNoWindow = true;
                info.FileName = filename;
                info.Arguments = arguments;
                info.UseShellExecute = false;
                info.RedirectStandardOutput = true;
                info.RedirectStandardError = true;

                if (workingDir != null)
                    info.WorkingDirectory = workingDir;

                process.StartInfo = info;

                StringBuilder stdout = new StringBuilder();
                StringBuilder stderr = combineStdoutAndStderr
                    ? stdout : new StringBuilder();

                var result = new ProcessResult();

                try
                {
                    process.OutputDataReceived += (sender, e) =>
                    {
                        if (e.Data == null)
                            outputWaitHandle.Set();
                        else
                            stdout.AppendLine(e.Data);
                    };
                    process.ErrorDataReceived += (sender, e) =>
                    {
                        if (e.Data == null)
                            errorWaitHandle.Set();
                        else
                            stderr.AppendLine(e.Data);
                    };

                    process.Start();

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

                    if (process.WaitForExit(timeoutInMs))
                        result.ExitCode = process.ExitCode;
                    // else process has timed out 
                    // but that's already default ProcessResult

                    result.stdout = stdout.ToString();
                    if (combineStdoutAndStderr)
                        result.stderr = null;
                    else
                        result.stderr = stderr.ToString();

                    return result;
                }
                finally
                {
                    outputWaitHandle.WaitOne(timeoutInMs);
                    errorWaitHandle.WaitOne(timeoutInMs);
                }
            }
        }
    }
}

अभी भी System.ObjectDisposedException प्राप्त करें: इस संस्करण पर भी सुरक्षित हैंडल बंद कर दिया गया है।
मैट

1

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

वैसे भी, मेरे लिए जो समाधान काम करता था वह था स्टैंडर्डऑउटपुट और स्टैंडर्डएयर को पढ़ने और संदेशों को लिखने के लिए विभिन्न थ्रेड्स का उपयोग करना।

        StreamWriter sw = null;
        var queue = new ConcurrentQueue<string>();

        var flushTask = new System.Timers.Timer(50);
        flushTask.Elapsed += (s, e) =>
        {
            while (!queue.IsEmpty)
            {
                string line = null;
                if (queue.TryDequeue(out line))
                    sw.WriteLine(line);
            }
            sw.FlushAsync();
        };
        flushTask.Start();

        using (var process = new Process())
        {
            try
            {
                process.StartInfo.FileName = @"...";
                process.StartInfo.Arguments = $"...";
                process.StartInfo.UseShellExecute = false;
                process.StartInfo.RedirectStandardOutput = true;
                process.StartInfo.RedirectStandardError = true;

                process.Start();

                var outputRead = Task.Run(() =>
                {
                    while (!process.StandardOutput.EndOfStream)
                    {
                        queue.Enqueue(process.StandardOutput.ReadLine());
                    }
                });

                var errorRead = Task.Run(() =>
                {
                    while (!process.StandardError.EndOfStream)
                    {
                        queue.Enqueue(process.StandardError.ReadLine());
                    }
                });

                var timeout = new TimeSpan(hours: 0, minutes: 10, seconds: 0);

                if (Task.WaitAll(new[] { outputRead, errorRead }, timeout) &&
                    process.WaitForExit((int)timeout.TotalMilliseconds))
                {
                    if (process.ExitCode != 0)
                    {
                        throw new Exception($"Failed run... blah blah");
                    }
                }
                else
                {
                    throw new Exception($"process timed out after waiting {timeout}");
                }
            }
            catch (Exception e)
            {
                throw new Exception($"Failed to succesfully run the process.....", e);
            }
        }
    }

आशा है कि यह किसी को मदद करता है, जिसने सोचा कि यह इतना कठिन हो सकता है!


अपवाद: sw.FlushAsync(): Object is not set to an instance of an object. sw is null. कैसे / कहाँ swपरिभाषित किया जाना चाहिए?
wallyk

1

यहाँ सभी पोस्ट पढ़ने के बाद, मैं मार्को एविलाइज़ के समेकित समाधान पर बस गया। हालाँकि , इसने मेरे सभी मुद्दों को हल नहीं किया।

हमारे वातावरण में हमारे पास एक Windows सेवा है जो सैकड़ों विभिन्न .bat .cmd .exe, ... आदि फ़ाइलों को चलाने के लिए निर्धारित है जो वर्षों से संचित हैं और कई अलग-अलग लोगों द्वारा और विभिन्न शैलियों में लिखी गई थीं। कार्यक्रमों और पटकथा के लेखन पर हमारा कोई नियंत्रण नहीं है, हम केवल समयबद्धन, चलाने और सफलता / विफलता पर रिपोर्टिंग के लिए जिम्मेदार हैं।

इसलिए मैंने सफलता के विभिन्न स्तरों के साथ यहां सभी सुझावों की बहुत कोशिश की। मार्को का जवाब लगभग सही था, लेकिन जब एक सेवा के रूप में चलाया जाता है, तो यह हमेशा स्टडआउट पर कब्जा नहीं करता है। मैं कभी भी इसकी तह तक क्यों नहीं गया।

हमारे सभी मामलों में काम करने वाला एकमात्र समाधान यह है: http://csharptest.net/319/use-the-processrunner-class/index.html


मैं इस पुस्तकालय की कोशिश करने जा रहा हूं। मैंने कोड को स्कोप किया है, और यह प्रतिनिधियों को समझदारी से उपयोग करने के लिए लगता है। यह नुगेट में अच्छी तरह से पैक किया गया है। यह मूल रूप से व्यावसायिकता से बदबू आ रही है, कुछ ऐसा जिसका मुझ पर कभी आरोप नहीं लगाया जा सकता। अगर यह काटता है, तो बताएगा।
स्टीव हिबर्ट

स्रोत कोड का लिंक मृत है। कृपया अगली बार कोड को उत्तर में कॉपी करें।
विटाली ज़डनेविच

1

सभी जटिलता से बचने के लिए मैंने वर्कअराउंड का उपयोग किया:

var outputFile = Path.GetTempFileName();
info = new System.Diagnostics.ProcessStartInfo("TheProgram.exe", String.Join(" ", args) + " > " + outputFile + " 2>&1");
info.CreateNoWindow = true;
info.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden;
info.UseShellExecute = false;
System.Diagnostics.Process p = System.Diagnostics.Process.Start(info);
p.WaitForExit();
Console.WriteLine(File.ReadAllText(outputFile)); //need the StandardOutput contents

इसलिए मैं एक अस्थायी फ़ाइल बनाता हूं, आउटपुट और त्रुटि दोनों का उपयोग करके इसे पुनर्निर्देशित करता हूं > outputfile > 2>&1और फिर प्रक्रिया समाप्त होने के बाद बस फ़ाइल को पढ़ता हूं ।

अन्य समाधान उन परिदृश्यों के लिए ठीक हैं जहां आप आउटपुट के साथ अन्य सामान करना चाहते हैं, लेकिन साधारण सामान के लिए यह बहुत जटिलता से बचा जाता है।


1

मैंने कई उत्तर पढ़े हैं और मैंने अपना बनाया है। यह सुनिश्चित नहीं है कि यह किसी भी मामले में ठीक हो जाएगा, लेकिन यह मेरे वातावरण में ठीक करता है। मैं सिर्फ WaitForExit का उपयोग नहीं कर रहा हूं और दोनों आउटपुट और त्रुटि समाप्ति संकेतों पर WaitHandle.WaitAll का उपयोग करूंगा। मुझे खुशी होगी, अगर किसी को इसके साथ संभावित समस्याएं दिखाई देंगी। या अगर यह किसी की मदद करेगा। मेरे लिए यह बेहतर है क्योंकि टाइमआउट का उपयोग नहीं करता है।

private static int DoProcess(string workingDir, string fileName, string arguments)
{
    int exitCode;
    using (var process = new Process
    {
        StartInfo =
        {
            WorkingDirectory = workingDir,
            WindowStyle = ProcessWindowStyle.Hidden,
            CreateNoWindow = true,
            UseShellExecute = false,
            FileName = fileName,
            Arguments = arguments,
            RedirectStandardError = true,
            RedirectStandardOutput = true
        },
        EnableRaisingEvents = true
    })
    {
        using (var outputWaitHandle = new AutoResetEvent(false))
        using (var errorWaitHandle = new AutoResetEvent(false))
        {
            process.OutputDataReceived += (sender, args) =>
            {
                // ReSharper disable once AccessToDisposedClosure
                if (args.Data != null) Debug.Log(args.Data);
                else outputWaitHandle.Set();
            };
            process.ErrorDataReceived += (sender, args) =>
            {
                // ReSharper disable once AccessToDisposedClosure
                if (args.Data != null) Debug.LogError(args.Data);
                else errorWaitHandle.Set();
            };

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

            WaitHandle.WaitAll(new WaitHandle[] { outputWaitHandle, errorWaitHandle });

            exitCode = process.ExitCode;
        }
    }
    return exitCode;
}

मैंने इसे इस्तेमाल किया और टास्क के साथ लपेटा। टाइमआउट को संभालने के लिए, मैं टाइमआउट पर हत्या करने के लिए भी लौट
आया

0

मुझे लगता है कि async के साथ, यह एक और अधिक सुंदर समाधान और संभव नहीं है कि मानक मानक और मानक दोनों का उपयोग करते समय गतिरोध न हो:

using (Process process = new Process())
{
    process.StartInfo.FileName = filename;
    process.StartInfo.Arguments = arguments;
    process.StartInfo.UseShellExecute = false;
    process.StartInfo.RedirectStandardOutput = true;
    process.StartInfo.RedirectStandardError = true;

    process.Start();

    var tStandardOutput = process.StandardOutput.ReadToEndAsync();
    var tStandardError = process.StandardError.ReadToEndAsync();

    if (process.WaitForExit(timeout))
    {
        string output = await tStandardOutput;
        string errors = await tStandardError;

        // Process completed. Check process.ExitCode here.
    }
    else
    {
        // Timed out.
    }
}

यह मार्क बायर्स के जवाब पर आधारित है। यदि आप एक async विधि में नहीं हैं, तो आप string output = tStandardOutput.result;इसके बजाय उपयोग कर सकते हैंawait



-1

यह पोस्ट शायद पुरानी है, लेकिन मुझे मुख्य कारण पता चला कि यह आमतौर पर लटका क्यों होता है पुनर्निर्देशन के लिए स्टैक ओवरफ्लो के कारण होता है या यदि आपके पास पुनर्निर्देशन कम है।

जैसा कि आउटपुट डेटा या त्रुटि डेटा बड़ा है, यह एक लटका समय का कारण होगा क्योंकि यह अभी भी अनिश्चित अवधि के लिए प्रसंस्करण कर रहा है।

तो इस समस्या को हल करने के लिए:

p.StartInfo.RedirectStandardoutput = False
p.StartInfo.RedirectStandarderror = False

11
समस्या यह है कि लोग स्पष्ट रूप से उन लोगों को सच करने के लिए निर्धारित करते हैं क्योंकि वे उन धाराओं का उपयोग करने में सक्षम होना चाहते हैं! और वास्तव में हम उन्हें केवल झूठे के लिए छोड़ सकते हैं।
user276648

-1

हमें यहां पर पोस्ट किए गए नमूना कोड को पुनर्निर्देशक और दूसरे कार्यक्रम को पुनर्निर्देशित कहते हैं। अगर यह मैं होता तो मैं शायद एक परीक्षण पुनर्निर्देशित कार्यक्रम लिखता, जिसका उपयोग समस्या की नकल करने के लिए किया जा सकता था।

तो मैंने किया। परीक्षण डेटा के लिए मैंने ECMA-334 C # भाषा विनिर्देश पीडीएफ का उपयोग किया; यह लगभग 5 एमबी है। निम्नलिखित उस का महत्वपूर्ण हिस्सा है।

StreamReader stream = null;
try { stream = new StreamReader(Path); }
catch (Exception ex)
{
    Console.Error.WriteLine("Input open error: " + ex.Message);
    return;
}
Console.SetIn(stream);
int datasize = 0;
try
{
    string record = Console.ReadLine();
    while (record != null)
    {
        datasize += record.Length + 2;
        record = Console.ReadLine();
        Console.WriteLine(record);
    }
}
catch (Exception ex)
{
    Console.Error.WriteLine($"Error: {ex.Message}");
    return;
}

डेटा का मान वास्तविक फ़ाइल आकार से मेल नहीं खाता, लेकिन इससे कोई फर्क नहीं पड़ता। यह स्पष्ट नहीं है कि क्या एक पीडीएफ फाइल हमेशा लाइनों के अंत में सीआर और एलएफ दोनों का उपयोग करती है लेकिन इसके लिए कोई फर्क नहीं पड़ता। आप परीक्षण करने के लिए किसी अन्य बड़ी पाठ फ़ाइल का उपयोग कर सकते हैं।

सैंपल रिडायरेक्टर कोड का उपयोग करने पर जब मैं बड़ी मात्रा में डेटा लिखता हूं, लेकिन तब नहीं जब मैं छोटी राशि लिखता हूं।

मैंने किसी तरह उस कोड के निष्पादन का पता लगाने की बहुत कोशिश की और मैं नहीं कर सका। मैंने रीडायरेक्ट प्रोग्राम की तर्ज पर टिप्पणी की, जो रीडायरेक्ट प्रोग्राम के लिए कंसोल की अक्षम रचना को एक अलग कंसोल विंडो प्राप्त करने का प्रयास करने के लिए बनाया था, लेकिन मैं नहीं कर सका।

फिर मैंने पाया कि एक नई विंडो, पेरेंट की विंडो या कोई विंडो में कंसोल ऐप कैसे शुरू करें । जाहिर तौर पर जब हम एक कंसोल प्रोग्राम को शेलएक्सक्यूट के बिना एक और कंसोल प्रोग्राम शुरू करते हैं तो आसानी से एक अलग कंसोल नहीं हो सकता है और चूंकि शेलएक्सक्यूट्यूट पुनर्निर्देशन का समर्थन नहीं करता है, भले ही हम कंसोल को साझा करें, भले ही हम अन्य प्रक्रिया के लिए कोई विंडो निर्दिष्ट न करें।

मेरा मानना ​​है कि यदि पुनर्निर्देशित कार्यक्रम कहीं बफर भरता है तो उसे डेटा के पढ़ने की प्रतीक्षा करनी चाहिए और यदि उस बिंदु पर रीडायरेक्टर द्वारा कोई डेटा नहीं पढ़ा जाता है तो यह एक गतिरोध है।

समाधान ReadToEnd का उपयोग नहीं करना है और डेटा को पढ़ने के दौरान डेटा लिखा जा रहा है, लेकिन अतुल्यकालिक रीड का उपयोग करना आवश्यक नहीं है। समाधान काफी सरल हो सकता है। निम्नलिखित मेरे लिए 5 एमबी पीडीएफ के साथ काम करता है।

ProcessStartInfo info = new ProcessStartInfo(TheProgram);
info.CreateNoWindow = true;
info.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden;
info.RedirectStandardOutput = true;
info.UseShellExecute = false;
Process p = Process.Start(info);
string record = p.StandardOutput.ReadLine();
while (record != null)
{
    Console.WriteLine(record);
    record = p.StandardOutput.ReadLine();
}
p.WaitForExit();

एक अन्य संभावना जीयूआई प्रोग्राम का उपयोग पुनर्निर्देशन करने के लिए है। पूर्ववर्ती कोड स्पष्ट संशोधनों को छोड़कर WPF आवेदन में काम करता है।


-3

मैं एक ही मुद्दा रहा था, लेकिन कारण अलग था। यह हालांकि विंडोज 8 के तहत होगा, लेकिन विंडोज 7 के तहत नहीं। निम्न लाइन से समस्या पैदा हुई है।

pProcess.StartInfo.UseShellExecute = False

समाधान UseShellExecute को अक्षम नहीं करना था। मुझे अब एक शेल पॉपअप विंडो मिली, जो अवांछित है, लेकिन कार्यक्रम से बेहतर कुछ होने के लिए इंतजार नहीं कर रही है। इसलिए मैंने उसके लिए निम्नलिखित काम को जोड़ा:

pProcess.StartInfo.WindowStyle = ProcessWindowStyle.Hidden

अब केवल एक चीज मुझे परेशान कर रही है कि यह विंडोज 8 के तहत पहले स्थान पर क्यों हो रहा है।


1
UseShellExecuteयदि आप आउटपुट को पुनर्निर्देशित करना चाहते हैं, तो आपको झूठे पर सेट होने की आवश्यकता है।
ब्रैड मूर
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.