95 lines
3.3 KiB
C#
95 lines
3.3 KiB
C#
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<int> Pids);
|
|
|
|
private static readonly HashSet<string> ProtectedProcesses = new HashSet<string>(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<IEnumerable<LauncherItem>> GetItemsAsync(string query, CancellationToken ct)
|
|
{
|
|
if (string.IsNullOrWhiteSpace(query))
|
|
{
|
|
return Task.FromResult((IEnumerable<LauncherItem>)new _003C_003Ez__ReadOnlySingleElementList<LauncherItem>(new LauncherItem("종료할 프로세스명을 입력하세요", "예: kill chrome · kill notepad · kill explorer", null, null, null, "\ue7e8")));
|
|
}
|
|
string q = query.Trim().ToLowerInvariant();
|
|
try
|
|
{
|
|
List<Process> 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<LauncherItem>)new _003C_003Ez__ReadOnlySingleElementList<LauncherItem>(new LauncherItem("'" + query + "' 프로세스를 찾을 수 없습니다", "실행 중인 프로세스가 없거나 이름이 다릅니다", null, null, null, "\ue7ba")));
|
|
}
|
|
List<LauncherItem> result = list.GroupBy<Process, string>((Process p) => p.ProcessName, StringComparer.OrdinalIgnoreCase).Select(delegate(IGrouping<string, Process> g)
|
|
{
|
|
List<int> 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<LauncherItem>)result);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
LogService.Warn("프로세스 목록 조회 실패: " + ex.Message);
|
|
return Task.FromResult((IEnumerable<LauncherItem>)new _003C_003Ez__ReadOnlySingleElementList<LauncherItem>(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;
|
|
}
|
|
}
|