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