using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Threading; using System.Threading.Tasks; using AxCopilot.SDK; using AxCopilot.Services; namespace AxCopilot.Handlers; public class ProcessHandler : IActionHandler { private record ProcessKillData(string Name, List Pids); private static readonly HashSet ProtectedProcesses = new HashSet(StringComparer.OrdinalIgnoreCase) { "system", "smss", "csrss", "wininit", "winlogon", "services", "lsass", "svchost", "explorer", "dwm", "fontdrvhost", "spoolsv", "registry" }; public string? Prefix => "kill "; public PluginMetadata Metadata => new PluginMetadata("ProcessKiller", "프로세스 종료 — kill 뒤에 프로세스명 입력", "1.0", "AX"); public Task> GetItemsAsync(string query, CancellationToken ct) { if (string.IsNullOrWhiteSpace(query)) { return Task.FromResult((IEnumerable)new _003C_003Ez__ReadOnlySingleElementList(new LauncherItem("종료할 프로세스명을 입력하세요", "예: kill chrome · kill notepad · kill explorer", null, null, null, "\ue7e8"))); } string q = query.Trim().ToLowerInvariant(); try { List list = (from p in Process.GetProcesses() where !ProtectedProcesses.Contains(p.ProcessName) && p.ProcessName.ToLowerInvariant().Contains(q) orderby p.ProcessName select p).Take(12).ToList(); if (list.Count == 0) { return Task.FromResult((IEnumerable)new _003C_003Ez__ReadOnlySingleElementList(new LauncherItem("'" + query + "' 프로세스를 찾을 수 없습니다", "실행 중인 프로세스가 없거나 이름이 다릅니다", null, null, null, "\ue7ba"))); } List result = list.GroupBy((Process p) => p.ProcessName, StringComparer.OrdinalIgnoreCase).Select(delegate(IGrouping g) { List list2 = g.Select((Process p) => p.Id).ToList(); long value = g.Sum(delegate(Process p) { try { return p.WorkingSet64 / 1024 / 1024; } catch { return 0L; } }); string title = ((g.Count() > 1) ? $"{g.Key} ({g.Count()}개 인스턴스)" : g.Key); string subtitle = $"PID: {string.Join(", ", list2)} · 메모리: {value} MB · Enter로 종료"; return new LauncherItem(title, subtitle, null, new ProcessKillData(g.Key, list2), null, "\ue7e8"); }).ToList(); return Task.FromResult((IEnumerable)result); } catch (Exception ex) { LogService.Warn("프로세스 목록 조회 실패: " + ex.Message); return Task.FromResult((IEnumerable)new _003C_003Ez__ReadOnlySingleElementList(new LauncherItem("프로세스 목록 조회 실패", ex.Message, null, null, null, "\uea39"))); } } public Task ExecuteAsync(LauncherItem item, CancellationToken ct) { if (!(item.Data is ProcessKillData processKillData)) { return Task.CompletedTask; } int num = 0; int num2 = 0; foreach (int pid in processKillData.Pids) { try { Process processById = Process.GetProcessById(pid); processById.Kill(entireProcessTree: false); num++; } catch { num2++; } } LogService.Info($"프로세스 종료: {processKillData.Name} — {num}개 성공, {num2}개 실패"); return Task.CompletedTask; } }