سؤال

أرغب في تشغيل برنامج سطر أوامر خارجي من تطبيق Mono/.NET الخاص بي. على سبيل المثال ، أود الجري mencoder. هل هو ممكن:

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

المحلول

عند إنشاء الخاص بك Process مجموعة الكائن StartInfo بشكل مناسب:

var proc = new Process 
{
    StartInfo = new ProcessStartInfo
    {
        FileName = "program.exe",
        Arguments = "command line arguments to your executable",
        UseShellExecute = false,
        RedirectStandardOutput = true,
        CreateNoWindow = true
    }
};

ثم ابدأ العملية وقراءة منها:

proc.Start();
while (!proc.StandardOutput.EndOfStream)
{
    string line = proc.StandardOutput.ReadLine();
    // do something with line
}

يمكنك استخدام int.Parse() أو int.TryParse() لتحويل الأوتار إلى القيم الرقمية. قد تضطر إلى القيام ببعض معالجة السلسلة أولاً إذا كانت هناك أحرف رقمية غير صالحة في الأوتار التي تقرأها.

نصائح أخرى

يمكنك معالجة الإخراج الخاص بك بشكل متزامن أو بشكل غير متزامن.

1: مثال متزامن

static void runCommand()
{
    Process process = new Process();
    process.StartInfo.FileName = "cmd.exe";
    process.StartInfo.Arguments = "/c DIR"; // Note the /c command (*)
    process.StartInfo.UseShellExecute = false;
    process.StartInfo.RedirectStandardOutput = true;
    process.StartInfo.RedirectStandardError = true;
    process.Start();
    //* Read the output (or the error)
    string output = process.StandardOutput.ReadToEnd();
    Console.WriteLine(output);
    string err = process.StandardError.ReadToEnd();
    Console.WriteLine(err);
    process.WaitForExit();
}

ملحوظة من الأفضل معالجة كليهما انتاج و الأخطاء: يجب التعامل معها بشكل منفصل.

(*) لبعض الأوامر (هنا StartInfo.Arguments) يجب عليك إضافة /c التوجيه, ، وإلا فإن العملية تتجمد في WaitForExit().

2: مثال غير متزامن

static void runCommand() 
{
    //* Create your Process
    Process process = new Process();
    process.StartInfo.FileName = "cmd.exe";
    process.StartInfo.Arguments = "/c DIR";
    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();
}

static void OutputHandler(object sendingProcess, DataReceivedEventArgs outLine) 
{
    //* Do your stuff with the output (write to console/log/StringBuilder)
    Console.WriteLine(outLine.Data);
}

إذا لم تكن بحاجة إلى القيام بعمليات معقدة مع الإخراج ، فيمكنك تجاوز طريقة Outputhandler ، فقط إضافة المعالجات مباشرة:

//* Set your output and error (asynchronous) handlers
process.OutputDataReceived += (s, e) => Console.WriteLine(e.Data);
process.ErrorDataReceived += (s, e) => Console.WriteLine(e.Data);

حسنًا ، بالنسبة لأي شخص يريد قراءة الأخطاء والمخرجات ، ولكن يحصل على مسدود مع أي من الحلول ، المقدمة في إجابات أخرى (مثلي) ، إليك حل قمت ببنيه بعد قراءة MSDN Explanation لعلامة StandardOutput.

تعتمد الإجابة على رمز T30:

static void runCommand()
{
    //* Create your Process
    Process process = new Process();
    process.StartInfo.FileName = "cmd.exe";
    process.StartInfo.Arguments = "/c DIR";
    process.StartInfo.UseShellExecute = false;
    process.StartInfo.RedirectStandardOutput = true;
    process.StartInfo.RedirectStandardError = true;
    //* Set ONLY ONE handler here.
    process.ErrorDataReceived += new DataReceivedEventHandler(OutputHandler);
    //* Start process
    process.Start();
    //* Read one element asynchronously
    process.BeginErrorReadLine();
    //* Read the other one synchronously
    string output = process.StandardOutput.ReadToEnd();
    Console.WriteLine(output);
    process.WaitForExit();
}

static void OutputHandler(object sendingProcess, DataReceivedEventArgs outLine) 
{
    //* Do your stuff with the output (write to console/log/StringBuilder)
    Console.WriteLine(outLine.Data);
}

طريقة .NET القياسية للقيام بذلك هي القراءة من العملية " StandardOutput مجرى. هناك مثال في مستندات MSDN المرتبطة. مماثل ، يمكنك القراءة من خطأ تقليدي, واكتب إلى StandardInput.

  1. من الممكن الحصول على إخراج قذيفة سطر الأوامر لعملية كما هو موضح هنا: http://www.c-sharpcorner.com/uploadfile/edwinlima/systemdiagnosticprocess12052005035444 am/systemdiagnosticprocess.aspx

  2. هذا يعتمد على mencoder. إذا كان هذا الحالة على سطر الأوامر ، نعم :)

يمكنك استخدام الذاكرة المشتركة للعملية 2 للتواصل ، تحقق من MemoryMappedFile

ستقوم بإنشاء ملف تم تعيين ذاكرة بشكل أساسي mmf في عملية الأصل باستخدام عبارة "استخدام" ثم قم بإنشاء العملية الثانية حتى تنتهي ودعها تكتب النتيجة إلى mmf استخدام BinaryWriter, ، ثم اقرأ النتيجة من mmf باستخدام عملية الأصل ، يمكنك أيضًا تمرير ملف mmf الاسم باستخدام وسيطات سطر الأوامر أو رمز صلب.

تأكد عند استخدام الملف المعين في العملية الأصل التي تجعل عملية الطفل تكتب النتيجة إلى الملف المعين قبل إصدار الملف المعين في العملية الأصل

مثال: عملية الوالدين

    private static void Main(string[] args)
    {
        using (MemoryMappedFile mmf = MemoryMappedFile.CreateNew("memfile", 128))
        {
            using (MemoryMappedViewStream stream = mmf.CreateViewStream())
            {
                BinaryWriter writer = new BinaryWriter(stream);
                writer.Write(512);
            }

            Console.WriteLine("Starting the child process");
            // Command line args are separated by a space
            Process p = Process.Start("ChildProcess.exe", "memfile");

            Console.WriteLine("Waiting child to die");

            p.WaitForExit();
            Console.WriteLine("Child died");

            using (MemoryMappedViewStream stream = mmf.CreateViewStream())
            {
                BinaryReader reader = new BinaryReader(stream);
                Console.WriteLine("Result:" + reader.ReadInt32());
            }
        }
        Console.WriteLine("Press any key to continue...");
        Console.ReadKey();
    }

عملية الطفل

    private static void Main(string[] args)
    {
        Console.WriteLine("Child process started");
        string mmfName = args[0];

        using (MemoryMappedFile mmf = MemoryMappedFile.OpenExisting(mmfName))
        {
            int readValue;
            using (MemoryMappedViewStream stream = mmf.CreateViewStream())
            {
                BinaryReader reader = new BinaryReader(stream);
                Console.WriteLine("child reading: " + (readValue = reader.ReadInt32()));
            }
            using (MemoryMappedViewStream input = mmf.CreateViewStream())
            {
                BinaryWriter writer = new BinaryWriter(input);
                writer.Write(readValue * 2);
            }
        }

        Console.WriteLine("Press any key to continue...");
        Console.ReadKey();
    }

لاستخدام هذه العينة ، ستحتاج إلى إنشاء حل مع مشروعين في الداخل ، ثم تأخذ نتيجة البناء لعملية الطفل من ٪ childdir ٪/bin/debug ونسخه إلى ٪ parentdirectory ٪/bin/debug ثم قم بتشغيل مشروع الوالدين

childDir و parentDirectory هي أسماء المجلد لمشاريعك على جهاز الكمبيوتر سعيد الحظ :)

كيفية إطلاق عملية (مثل ملف BAT و Perl Script وبرنامج وحدة التحكم) وعرض إخراجها القياسي على نموذج Windows:

processCaller = new ProcessCaller(this);
//processCaller.FileName = @"..\..\hello.bat";
processCaller.FileName = @"commandline.exe";
processCaller.Arguments = "";
processCaller.StdErrReceived += new DataReceivedHandler(writeStreamInfo);
processCaller.StdOutReceived += new DataReceivedHandler(writeStreamInfo);
processCaller.Completed += new EventHandler(processCompletedOrCanceled);
processCaller.Cancelled += new EventHandler(processCompletedOrCanceled);
// processCaller.Failed += no event handler for this one, yet.

this.richTextBox1.Text = "Started function.  Please stand by.." + Environment.NewLine;

// the following function starts a process and returns immediately,
// thus allowing the form to stay responsive.
processCaller.Start();    

يمكنك إيجاد ProcessCaller على هذا الرابط: إطلاق عملية وعرض إخراجها القياسي

الحل الذي نجح لي في Win و Linux هو Folling

// GET api/values
        [HttpGet("cifrado/{xml}")]
        public ActionResult<IEnumerable<string>> Cifrado(String xml)
        {
            String nombreXML = DateTime.Now.ToString("ddMMyyyyhhmmss").ToString();
            String archivo = "/app/files/"+nombreXML + ".XML";
            String comando = " --armor --recipient bibankingprd@bi.com.gt  --encrypt " + archivo;
            try{
                System.IO.File.WriteAllText(archivo, xml);                
                //String comando = "C:\\GnuPG\\bin\\gpg.exe --recipient licorera@local.com --armor --encrypt C:\\Users\\Administrador\\Documents\\pruebas\\nuevo.xml ";
                ProcessStartInfo startInfo = new ProcessStartInfo() {FileName = "/usr/bin/gpg",  Arguments = comando }; 
                Process proc = new Process() { StartInfo = startInfo, };
                proc.StartInfo.RedirectStandardOutput = true;
                proc.StartInfo.RedirectStandardError = true;
                proc.Start();
                proc.WaitForExit();
                Console.WriteLine(proc.StandardOutput.ReadToEnd());
                return new string[] { "Archivo encriptado", archivo + " - "+ comando};
            }catch (Exception exception){
                return new string[] { archivo, "exception: "+exception.ToString() + " - "+ comando };
            }
        }

يمكنك تسجيل إخراج العملية باستخدام الكود أدناه:

ProcessStartInfo pinfo = new ProcessStartInfo(item);
pinfo.CreateNoWindow = false;
pinfo.UseShellExecute = true;
pinfo.RedirectStandardOutput = true;
pinfo.RedirectStandardInput = true;
pinfo.RedirectStandardError = true;
pinfo.WindowStyle = System.Diagnostics.ProcessWindowStyle.Normal;
var p = Process.Start(pinfo);
p.WaitForExit();
Process process = Process.Start(new ProcessStartInfo((item + '>' + item + ".txt"))
{
    UseShellExecute = false,
    RedirectStandardOutput = true
});
process.WaitForExit();
string output = process.StandardOutput.ReadToEnd();
if (process.ExitCode != 0) { 
}
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top