Sometimes, the cmd gets stuck when executed from C#

41 Views Asked by At

The code below is the method I'm using to execute CMD commands. On the production server, it sometimes gets stuck for no apparent reason, even though I have already applied a timeout method. Despite this, it still occasionally gets stuck.

using System.Diagnostics;
using System.Text;

namespace SharedLibraries.Helpers
{

    public class CommandExecutor
    {
        private readonly Logger _logger;
        private const int DefaultTimeoutMilliseconds = 10000;
        public CommandExecutor(Logger logger)
        {
            _logger = logger;
        }
        public bool ExecuteCommand(string command, out string result, int timeoutMilliseconds = DefaultTimeoutMilliseconds)
        {
            Process? process = new()
            {
                StartInfo = new ProcessStartInfo
                {
                    FileName = "cmd.exe",
                    Arguments = $"/c {command}",
                    RedirectStandardOutput = true,
                    RedirectStandardError = true,
                    UseShellExecute = false,
                    CreateNoWindow = true,
                    StandardOutputEncoding = Encoding.UTF8,
                    StandardErrorEncoding = Encoding.UTF8
                }
            };

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

            try
            {
                _logger.Log(message: $"Executing command: '{command}'", LogLevel.INFO);
                process.OutputDataReceived += (object sender, DataReceivedEventArgs args) => { output.AppendLine(args.Data); };
                process.ErrorDataReceived += (object sender, DataReceivedEventArgs args) => { error.AppendLine(args.Data); };

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

                if (!process.WaitForExit(milliseconds: timeoutMilliseconds))
                {
                    process.Kill();
                    result = "Command execution timed out.";
                    _logger.Log(message: $"Command timeout. Command: '{command}', Timeout: {timeoutMilliseconds}ms", LogLevel.ERROR);
                    return false;
                }

                process.WaitForExit();

                string errorOutput = error.ToString().Trim();
                if (process.ExitCode != 0 || !string.IsNullOrEmpty(value: errorOutput))
                {
                    result = $"Command execution failed with exit code {process.ExitCode}:\n{errorOutput}";
                    _logger.Log(message: $"Command execution failed. Command: '{command}', Exit Code: {process.ExitCode}, Error: {errorOutput}", LogLevel.ERROR);
                    return false;
                }

                result = output.ToString().Trim();
                _logger.Log(message: $"Command executed successfully. Command: '{command}', Result:\n{result}", LogLevel.INFO);
                return true;
            }
            catch (Exception ex)
            {
                result = $"Error executing command: {ex.Message}";
                _logger.Log(message: $"Exception during command execution. Command: '{command}', Exception: {ex}", LogLevel.ERROR);
                return false;
            }
        }


    }

}

Can anyone help me understand what's going on and suggest a method to improve the timeout mechanism? I'm looking for a solution that will allow the system to return 'false' when it becomes stuck.

0

There are 0 best solutions below