using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.ServiceProcess; using System.Threading; using System.Threading.Tasks; using System.Windows; using System.Windows.Threading; using AxCopilot.SDK; using AxCopilot.Services; namespace AxCopilot.Handlers; public class ServiceHandler : IActionHandler { private readonly ClipboardHistoryService? _clipboardService; public string? Prefix => "svc"; public PluginMetadata Metadata => new PluginMetadata("Service", "Windows 서비스 관리 — svc", "1.0", "AX"); public ServiceHandler(ClipboardHistoryService? clipboardService = null) { _clipboardService = clipboardService; } public Task> GetItemsAsync(string query, CancellationToken ct) { string q = query.Trim(); List list = new List(); if (q.Equals("restart clipboard", StringComparison.OrdinalIgnoreCase) || q.Equals("클립보드 재시작", StringComparison.OrdinalIgnoreCase)) { list.Add(new LauncherItem("AX 클립보드 히스토리 서비스 재시작", "클립보드 감지가 작동하지 않을 때 사용 · Enter로 실행", null, "__RESTART_CLIPBOARD__", null, "\ue777")); return Task.FromResult((IEnumerable)list); } if (q.StartsWith("start ", StringComparison.OrdinalIgnoreCase) || q.StartsWith("stop ", StringComparison.OrdinalIgnoreCase) || q.StartsWith("restart ", StringComparison.OrdinalIgnoreCase)) { string[] array = q.Split(' ', 2, StringSplitOptions.TrimEntries); string text = array[0].ToLowerInvariant(); string svcName = ((array.Length > 1) ? array[1] : ""); if (!string.IsNullOrWhiteSpace(svcName)) { try { ServiceController serviceController = ServiceController.GetServices().FirstOrDefault((ServiceController s) => s.ServiceName.Contains(svcName, StringComparison.OrdinalIgnoreCase) || s.DisplayName.Contains(svcName, StringComparison.OrdinalIgnoreCase)); if (serviceController != null) { if (1 == 0) { } string text2 = text switch { "start" => "시작", "stop" => "중지", "restart" => "재시작", _ => text, }; if (1 == 0) { } string text3 = text2; list.Add(new LauncherItem("[" + text3 + "] " + serviceController.DisplayName, $"서비스명: {serviceController.ServiceName} · 현재 상태: {StatusText(serviceController.Status)} · Enter로 실행", null, ("__" + text.ToUpperInvariant() + "__", serviceController.ServiceName), null, (text == "stop") ? "\uea39" : "\ue777")); } else { list.Add(new LauncherItem("'" + svcName + "' 서비스를 찾을 수 없습니다", "서비스 이름 또는 표시 이름으로 검색", null, null, null, "\ue7ba")); } } catch (Exception ex) { list.Add(new LauncherItem("서비스 조회 실패", ex.Message, null, null, null, "\uea39")); } return Task.FromResult((IEnumerable)list); } } try { ServiceController[] services = ServiceController.GetServices(); IEnumerable enumerable = (string.IsNullOrWhiteSpace(q) ? (from s in services where s.Status == ServiceControllerStatus.Running orderby s.DisplayName select s).Take(20) : (from s in services where s.ServiceName.Contains(q, StringComparison.OrdinalIgnoreCase) || s.DisplayName.Contains(q, StringComparison.OrdinalIgnoreCase) orderby s.DisplayName select s).Take(20)); list.Add(new LauncherItem("AX 클립보드 히스토리 서비스 재시작", "svc restart clipboard · 클립보드 감지 문제 시 사용", null, "__RESTART_CLIPBOARD__", null, "\ue777")); foreach (ServiceController item in enumerable) { string text4 = StatusText(item.Status); string symbol = ((item.Status == ServiceControllerStatus.Running) ? "\ue73e" : "\ue711"); list.Add(new LauncherItem("[" + text4 + "] " + item.DisplayName, item.ServiceName + " · svc start/stop/restart " + item.ServiceName, null, item.ServiceName, null, symbol)); } } catch (Exception ex2) { list.Add(new LauncherItem("서비스 조회 실패", ex2.Message, null, null, null, "\uea39")); } return Task.FromResult((IEnumerable)list); } public Task ExecuteAsync(LauncherItem item, CancellationToken ct) { if (item.Data is string text && text == "__RESTART_CLIPBOARD__") { RestartClipboardService(); return Task.CompletedTask; } if (!(item.Data is (string, string) tuple)) { object data = item.Data; string name = data as string; if (name != null) { try { Application current = Application.Current; if (current != null) { ((DispatcherObject)current).Dispatcher.Invoke((Action)delegate { Clipboard.SetText(name); }); } } catch { } } return Task.CompletedTask; } var (action, svcName) = tuple; return ExecuteServiceAction(action, svcName); } private void RestartClipboardService() { try { if (_clipboardService == null) { NotificationService.Notify("AX Copilot", "클립보드 서비스 참조를 찾을 수 없습니다."); return; } _clipboardService.Dispose(); Application current = Application.Current; if (current == null) { return; } ((DispatcherObject)current).Dispatcher.BeginInvoke((Delegate)(Action)delegate { try { _clipboardService.Reinitialize(); NotificationService.Notify("AX Copilot", "클립보드 히스토리 서비스가 재시작되었습니다."); LogService.Info("클립보드 히스토리 서비스 강제 재시작 완료"); } catch (Exception ex2) { NotificationService.Notify("AX Copilot", "클립보드 재시작 실패: " + ex2.Message); LogService.Error("클립보드 재시작 실패: " + ex2.Message); } }, (DispatcherPriority)4, Array.Empty()); } catch (Exception ex) { NotificationService.Notify("AX Copilot", "클립보드 재시작 실패: " + ex.Message); } } private static async Task ExecuteServiceAction(string action, string svcName) { try { if (1 == 0) { } string text = action switch { "__START__" => "start", "__STOP__" => "stop", "__RESTART__" => "stop", _ => null, }; if (1 == 0) { } string verb = text; if (verb != null) { ProcessStartInfo psi = new ProcessStartInfo("sc.exe", verb + " \"" + svcName + "\"") { Verb = "runas", UseShellExecute = true, CreateNoWindow = true, WindowStyle = ProcessWindowStyle.Hidden }; Process.Start(psi)?.WaitForExit(5000); if (action == "__RESTART__") { await Task.Delay(1000); ProcessStartInfo startPsi = new ProcessStartInfo("sc.exe", "start \"" + svcName + "\"") { Verb = "runas", UseShellExecute = true, CreateNoWindow = true, WindowStyle = ProcessWindowStyle.Hidden }; Process.Start(startPsi)?.WaitForExit(5000); } if (1 == 0) { } text = action switch { "__START__" => "시작", "__STOP__" => "중지", "__RESTART__" => "재시작", _ => action, }; if (1 == 0) { } string label = text; NotificationService.Notify("서비스 관리", svcName + " " + label + " 요청 완료"); } } catch (Exception ex) { Exception ex2 = ex; NotificationService.Notify("AX Copilot", "서비스 제어 실패: " + ex2.Message); } } private static string StatusText(ServiceControllerStatus status) { if (1 == 0) { } string result = status switch { ServiceControllerStatus.Running => "실행 중", ServiceControllerStatus.Stopped => "중지됨", ServiceControllerStatus.StartPending => "시작 중", ServiceControllerStatus.StopPending => "중지 중", ServiceControllerStatus.Paused => "일시 중지", ServiceControllerStatus.ContinuePending => "재개 중", ServiceControllerStatus.PausePending => "일시 중지 중", _ => status.ToString(), }; if (1 == 0) { } return result; } }