programing

Process.start: 출력을 얻는 방법은 무엇입니까?

magicmemo 2023. 5. 16. 22:28
반응형

Process.start: 출력을 얻는 방법은 무엇입니까?

Mono/에서 외부 명령줄 프로그램을 실행하고 싶습니다.NET 앱.예를 들어, 저는 멘코더를 실행하고 싶습니다.가능합니까?

  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()문자열을 숫자 값으로 변환합니다.읽은 문자열에 잘못된 숫자 문자가 있는 경우 먼저 문자열을 조작해야 할 수 있습니다.

출력을 동기식 또는 비동기식으로 처리할 수 있습니다.

동기식 예제

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().

비동기 예제

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 설명을 읽고 구축한 솔루션이 있습니다.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(ErrorOutputHandler);
    //* 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 ErrorOutputHandler(object sendingProcess, DataReceivedEventArgs outLine) 
{
    //* Do your stuff with the output (write to console/log/StringBuilder)
    Console.WriteLine(outLine.Data);
}

기준.NET 방법은 프로세스의 표준 출력 스트림에서 읽는 것입니다.연결된 MSDN 문서에 예제가 있습니다.마찬가지로 표준 오류에서 읽고 표준 입력에 쓸 수 있습니다.

  1. 여기에 설명된 대로 프로세스의 명령줄 셸 출력을 가져올 수 있습니다. http://www.c-sharpcorner.com/UploadFile/edwinlima/SystemDiagnosticProcess12052005035444AM/SystemDiagnosticProcess.aspx

  2. 이는 멘코더에 따라 다릅니다.이 상태를 명령줄에 출력하면 예:)

공유 메모리를 사용하여 두 프로세스를 통해 통신할 수 있습니다. 체크아웃.

은 주로 메모리 을 만들입니다.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그리고.parentDirectoryPC에 있는 당신의 프로젝트의 폴더 이름들은 행운을 빕니다 :)

아래 코드를 사용하여 프로세스 출력을 기록할 수 있습니다.

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) { 
}

프로세스(예: 배트 파일, 펄 스크립트, 콘솔 프로그램)를 시작하고 표준 출력을 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이 링크에서: 프로세스 시작 및 표준 출력 표시

전화를 걸었을 때 악명 높은 교착 상태 문제에 봉착했습니다.Process.StandardOutput.ReadLine그리고.Process.StandardOutput.ReadToEnd.

목표/사용 사례는 간단합니다.프로세스를 시작하고 출력을 리디렉션하면 해당 출력을 캡처하고 를 통해 콘솔에 기록할 수 있습니다.NET Core의ILogger<T>리디렉션된 출력을 파일 로그에 추가합니다.

기본 제공 비동기 이벤트 핸들러를 사용하는 내 솔루션은 다음과 같습니다.Process.OutputDataReceived그리고.Process.ErrorDataReceived.

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


// Asynchronously pushes StdOut and StdErr lines to a thread safe FIFO queue
var logQueue = new ConcurrentQueue<string>();
p.OutputDataReceived += (sender, args) => logQueue.Enqueue(args.Data);
p.ErrorDataReceived += (sender, args) => logQueue.Enqueue(args.Data);

// Start the process and begin streaming StdOut/StdErr
p.Start();
p.BeginOutputReadLine();
p.BeginErrorReadLine();

// Loop until the process has exited or the CancellationToken is triggered
do
{
    var lines = new List<string>();
    while (logQueue.TryDequeue(out var log))
    {
        lines.Add(log);
        _logger.LogInformation(log)
    }
    File.AppendAllLines(_logFilePath, lines);

    // Asynchronously sleep for some time
    try
    {
        Task.Delay(5000, stoppingToken).Wait(stoppingToken);
    }
    catch(OperationCanceledException) {}

} while (!p.HasExited && !stoppingToken.IsCancellationRequested);

win과 linux에서 저에게 효과가 있었던 솔루션은 다음과 같습니다.

// 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 };
            }
        }

언급URL : https://stackoverflow.com/questions/4291912/process-start-how-to-get-the-output

반응형