Files

258 lines
7.9 KiB
C#

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<IEnumerable<LauncherItem>> GetItemsAsync(string query, CancellationToken ct)
{
string q = query.Trim();
List<LauncherItem> list = new List<LauncherItem>();
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<LauncherItem>)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<LauncherItem>)list);
}
}
try
{
ServiceController[] services = ServiceController.GetServices();
IEnumerable<ServiceController> 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<LauncherItem>)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<object>());
}
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;
}
}