using System; using System.Diagnostics; using System.IO; using System.Runtime.InteropServices; using System.Text; using System.Threading.Tasks; namespace JJServiceManager { /// /// Windows 명령(schtasks, netsh 등)을 실행하고 출력을 읽음. /// 시스템 설정에 따라 출력이 UTF-8 또는 CP949(OEM)일 수 있어, /// 바이트로 받은 뒤 UTF-8로 올바르게 읽히면 UTF-8, 아니면 시스템 OEM 코드페이지로 해석함. /// public static class ConsoleRunner { [DllImport("kernel32.dll")] private static extern uint GetOEMCP(); public static (int exitCode, string output) Run(string file, string args, int timeoutMs = 15000) { try { var psi = new ProcessStartInfo(file, args) { UseShellExecute = false, CreateNoWindow = true, RedirectStandardOutput = true, RedirectStandardError = true }; using var p = Process.Start(psi); var outTask = ReadAllAsync(p.StandardOutput.BaseStream); var errTask = ReadAllAsync(p.StandardError.BaseStream); if (!p.WaitForExit(timeoutMs)) { try { p.Kill(); } catch { } return (-1, "시간 초과"); } var bytes = Combine(outTask.Result, errTask.Result); return (p.ExitCode, Decode(bytes).Trim()); } catch (Exception ex) { return (-1, ex.Message); } } private static async Task ReadAllAsync(Stream s) { using var ms = new MemoryStream(); await s.CopyToAsync(ms).ConfigureAwait(false); return ms.ToArray(); } private static byte[] Combine(byte[] a, byte[] b) { var r = new byte[a.Length + b.Length]; Buffer.BlockCopy(a, 0, r, 0, a.Length); Buffer.BlockCopy(b, 0, r, a.Length, b.Length); return r; } public static string Decode(byte[] bytes) { if (bytes.Length == 0) return ""; try { var strict = new UTF8Encoding(false, throwOnInvalidBytes: true); return strict.GetString(bytes); } catch { } try { return Encoding.GetEncoding((int)GetOEMCP()).GetString(bytes); } catch { } try { return Encoding.GetEncoding(949).GetString(bytes); } catch { return Encoding.UTF8.GetString(bytes); } } } }