简体   繁体   中英

Dotnet core 2 process start with timeout

I have a method to start process from my c# code in dotnet core 2. This method is like following:

    internal static string[] RunCommand(string filename, string args, string workingDirectory = null)
    {
        var proc = new Process
        {
            StartInfo = new ProcessStartInfo
            {
                FileName = filename,
                Arguments = args,
                UseShellExecute = false,
                RedirectStandardOutput = true,
                //WindowStyle = ProcessWindowStyle.Hidden
            }
        };

        if (workingDirectory != null)
        {
            proc.StartInfo.WorkingDirectory = workingDirectory;
        }

        //Console.WriteLine(proc.StartInfo.FileName + " " + proc.StartInfo.Arguments);

        List<string> lines = new List<string>();

        proc.Start();
        while (!proc.StandardOutput.EndOfStream)
        {
            string line = proc.StandardOutput.ReadLine();
            if (!string.IsNullOrEmpty(line))
            {

                lines.Add(line);
            }
        }
        proc.Dispose();

        return lines.ToArray();
    }

The problem is that some started processes fall in a loop and it make my vps run into problem.

So the question is that is there any solution to run a process with deadline?

Update

According to the recommendation of 'Jacek Blaszczynski' I have tried the code bellow:

    internal static string[] RunCommand(string filename, string args, string workingDirectory = null, int timeoutInSeconds = 60)
    {
        var proc = new Process
        {
            StartInfo = new ProcessStartInfo
            {
                FileName = filename,
                Arguments = args,
                UseShellExecute = false,
                RedirectStandardOutput = true,
                //WindowStyle = ProcessWindowStyle.Hidden
            }
        };

        if (workingDirectory != null)
        {
            proc.StartInfo.WorkingDirectory = workingDirectory;
        }

        //Console.WriteLine(proc.StartInfo.FileName + " " + proc.StartInfo.Arguments);

        List<string> lines = new List<string>();

        bool isKilled = false;

        new Thread(() =>
        {
            Thread.CurrentThread.IsBackground = true;
            Thread.Sleep(timeoutInSeconds * 1000);
            try
            {
                if (proc != null && !proc.HasExited)
                {
                    isKilled = true;
                    proc.Kill();
                    Console.WriteLine("Annoying process killed.");
                }
            }
            catch
            {
                // just let it go
            }
        }).Start();

        try
        {
            proc.Start();
            while (!proc.StandardOutput.EndOfStream)
            {
                string line = proc.StandardOutput.ReadLine();
                if (!string.IsNullOrEmpty(line))
                {

                    lines.Add(line);
                }
            }
            proc.Dispose();
        }
        catch
        {
            // just look what happens
        }

        return isKilled ? new string[] { "" } : lines.ToArray();
    }

But still I have some wander processes. As debugging of multi thread processes are very hard and the case that causes this situation is unknown to me, Do you have any idea why should some process get out live of my trap?

This can be simplified if you use a library like CliWrap :

using CliWrap;
using CliWrap.Buffered;

// Timeout setup
using var cts = new CancellationTokenSource();
cts.CancelAfter(TimeSpan.FromMinutes(1));

// Run the process
var result = await Cli.Wrap("path/to/exe")
    .WithArguments("--foo bar")
    .ExecuteBufferedAsync(cts.Token);

// The process will be killed automatically if the execution is cancelled

First I need to make some assumptions about missing information: (i) you run your code on Windows, (ii) your process does not have graphical user interface (window). There are two recommended methods to stop Windows processes where preferred choice depends on the type of process: (i) GUI process, (ii) non-GUI process. In the second case you should call Process.Kill() method to have a reliable process exit immediately followed by Process.WaitForExit() . Microsoft docs state that:

Kill is the only way to terminate processes that do not have graphical interfaces.

It does not relieve you from cleaning up processes resources ( Dispose or Close call), however, this task is somehow orthogonal to Process.Kill() which according to docs may lead to:

Data edited by the process or resources allocated to the process can be lost if you call Kill .

There are a lot of different exceptions which may be thrown so some more than basic exception handling code is warranted.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM