Files

463 lines
15 KiB
C#
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Net.NetworkInformation;
using System.Net.Sockets;
using System.Runtime.InteropServices;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Forms;
using System.Windows.Threading;
using AxCopilot.SDK;
using AxCopilot.Services;
using AxCopilot.Views;
using Microsoft.Win32;
namespace AxCopilot.Handlers;
public class SystemInfoHandler : IActionHandler
{
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
private struct MEMORYSTATUSEX
{
public uint dwLength;
public uint dwMemoryLoad;
public ulong ullTotalPhys;
public ulong ullAvailPhys;
public ulong ullTotalPageFile;
public ulong ullAvailPageFile;
public ulong ullTotalVirtual;
public ulong ullAvailVirtual;
public ulong ullAvailExtendedVirtual;
}
internal sealed record InfoAction(string Type, string? Payload = null);
private static volatile PerformanceCounter? _cpuCounter;
private static float _cpuCached;
private static DateTime _cpuUpdated;
private static readonly object _cpuLock;
public string? Prefix => "info";
public PluginMetadata Metadata => new PluginMetadata("SystemInfo", "시스템 정보 — IP, 배터리, 볼륨, 가동시간 등", "1.0", "AX");
[DllImport("winmm.dll")]
private static extern int waveOutGetVolume(nint hwo, out uint dwVolume);
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool GlobalMemoryStatusEx(ref MEMORYSTATUSEX lpBuffer);
static SystemInfoHandler()
{
_cpuUpdated = DateTime.MinValue;
_cpuLock = new object();
Task.Run(delegate
{
try
{
PerformanceCounter performanceCounter = new PerformanceCounter("Processor", "% Processor Time", "_Total");
performanceCounter.NextValue();
_cpuCounter = performanceCounter;
}
catch
{
}
});
}
private static float GetCpuUsage()
{
try
{
PerformanceCounter cpuCounter = _cpuCounter;
if (cpuCounter == null)
{
return -1f;
}
lock (_cpuLock)
{
if ((DateTime.Now - _cpuUpdated).TotalMilliseconds > 800.0)
{
_cpuCached = cpuCounter.NextValue();
_cpuUpdated = DateTime.Now;
}
return _cpuCached;
}
}
catch
{
return -1f;
}
}
public Task<IEnumerable<LauncherItem>> GetItemsAsync(string query, CancellationToken ct)
{
string text = query.Trim().ToLowerInvariant();
List<LauncherItem> list = new List<LauncherItem>();
try
{
bool flag = string.IsNullOrEmpty(text);
bool flag2 = flag || text.Contains("ip") || text.Contains("네트워크") || text.Contains("network");
bool flag3 = flag || text.Contains("bat") || text.Contains("배터리") || text.Contains("battery");
bool flag4 = flag || text.Contains("vol") || text.Contains("볼륨") || text.Contains("volume");
bool flag5 = flag || text.Contains("up") || text.Contains("가동") || text.Contains("uptime");
bool flag6 = flag || text.Contains("sys") || text.Contains("시스템") || text.Contains("system") || text.Contains("host") || text.Contains("호스트") || text.Contains("os");
bool flag7 = flag || text.Contains("user") || text.Contains("사용자");
bool flag8 = flag || text.Contains("cpu") || text.Contains("프로세서") || text.Contains("processor");
bool flag9 = flag || text.Contains("ram") || text.Contains("메모리") || text.Contains("memory");
bool flag10 = flag || text.Contains("disk") || text.Contains("디스크") || text.Contains("storage") || text.Contains("저장");
bool flag11 = flag || text.Contains("screen") || text.Contains("화면") || text.Contains("resolution") || text.Contains("display");
if (flag6)
{
list.Add(new LauncherItem("컴퓨터: " + Environment.MachineName, "OS: " + GetOsVersion() + " · Enter로 시스템 정보 열기", null, new InfoAction("shell", "msinfo32"), null, "\ue7f4"));
}
if (flag7)
{
string text2 = Environment.UserDomainName + "\\" + Environment.UserName;
list.Add(new LauncherItem("사용자: " + Environment.UserName, text2 + " · Enter로 사용자 계정 설정 열기", null, new InfoAction("shell", "netplwiz"), null, "\ue77b"));
}
if (flag2)
{
string localIpAddress = GetLocalIpAddress();
if (localIpAddress != null)
{
list.Add(new LauncherItem("로컬 IP: " + localIpAddress, "LAN / Wi-Fi 주소 · Enter로 네트워크 설정 열기", null, new InfoAction("ms_settings", "ms-settings:network"), null, "\ue968"));
}
string defaultGateway = GetDefaultGateway();
if (defaultGateway != null)
{
list.Add(new LauncherItem("게이트웨이: " + defaultGateway, "기본 게이트웨이 · Enter로 네트워크 설정 열기", null, new InfoAction("ms_settings", "ms-settings:network"), null, "\ue968"));
}
}
if (flag3)
{
LauncherItem batteryItem = GetBatteryItem();
if (batteryItem != null)
{
list.Add(batteryItem);
}
}
if (flag4)
{
LauncherItem volumeItem = GetVolumeItem();
if (volumeItem != null)
{
list.Add(volumeItem);
}
}
if (flag5)
{
TimeSpan timeSpan = TimeSpan.FromMilliseconds(Environment.TickCount64);
string text3 = FormatUptime(timeSpan);
DateTime value = DateTime.Now - timeSpan;
list.Add(MakeItem("가동 시간: " + text3, $"마지막 재시작: {value:MM/dd HH:mm}", text3, "\ue823"));
}
if (flag8)
{
float cpuUsage = GetCpuUsage();
string title = ((cpuUsage < 0f) ? "CPU: 측정 중…" : $"CPU: {(int)cpuUsage}%");
string processorName = GetProcessorName();
list.Add(new LauncherItem(title, (string.IsNullOrEmpty(processorName) ? "전체 CPU 사용률" : processorName) + " · Enter로 리소스 모니터 열기", null, new InfoAction("resource_mon"), null, "\ue950"));
}
if (flag9)
{
MEMORYSTATUSEX lpBuffer = new MEMORYSTATUSEX
{
dwLength = (uint)Marshal.SizeOf<MEMORYSTATUSEX>()
};
if (GlobalMemoryStatusEx(ref lpBuffer))
{
double value2 = (double)lpBuffer.ullTotalPhys / 1024.0 / 1024.0 / 1024.0;
double value3 = (double)(lpBuffer.ullTotalPhys - lpBuffer.ullAvailPhys) / 1024.0 / 1024.0 / 1024.0;
uint dwMemoryLoad = lpBuffer.dwMemoryLoad;
list.Add(new LauncherItem($"RAM: {value3:F1} / {value2:F1} GB ({dwMemoryLoad}%)", $"사용 중: {value3:F1} GB · 여유: {(double)lpBuffer.ullAvailPhys / 1024.0 / 1024.0 / 1024.0:F1} GB · Enter로 리소스 모니터 열기", null, new InfoAction("resource_mon"), null, "\ue950"));
}
}
if (flag10)
{
foreach (DriveInfo item in from d in DriveInfo.GetDrives()
where d.IsReady && d.DriveType == DriveType.Fixed
select d)
{
double num = (double)item.TotalSize / 1024.0 / 1024.0 / 1024.0;
double num2 = (double)item.AvailableFreeSpace / 1024.0 / 1024.0 / 1024.0;
double num3 = num - num2;
int value4 = (int)(num3 / num * 100.0);
string value5 = (string.IsNullOrWhiteSpace(item.VolumeLabel) ? item.Name.TrimEnd('\\') : item.VolumeLabel);
list.Add(new LauncherItem($"드라이브 {item.Name.TrimEnd('\\')} ({value5}) — {num3:F0} / {num:F0} GB ({value4}%)", $"여유 공간: {num2:F1} GB · Enter로 탐색기 열기", null, new InfoAction("open_drive", item.RootDirectory.FullName), null, "\ueda2"));
}
}
if (flag11)
{
double primaryScreenWidth = SystemParameters.PrimaryScreenWidth;
double primaryScreenHeight = SystemParameters.PrimaryScreenHeight;
list.Add(new LauncherItem($"화면: {(int)primaryScreenWidth} × {(int)primaryScreenHeight}", "기본 모니터 해상도 · Enter로 디스플레이 설정 열기", null, new InfoAction("ms_settings", "ms-settings:display"), null, "\ue7f4"));
}
}
catch (Exception ex)
{
LogService.Warn("시스템 정보 조회 오류: " + ex.Message);
list.Add(new LauncherItem("시스템 정보 조회 실패", ex.Message, null, null, null, "\uea39"));
}
if (list.Count == 0)
{
list.Add(new LauncherItem("시스템 정보 없음", "ip · battery · volume · uptime · system 키워드로 검색하세요", null, null, null, "\ue946"));
}
return Task.FromResult((IEnumerable<LauncherItem>)list);
}
public Task ExecuteAsync(LauncherItem item, CancellationToken ct)
{
object data = item.Data;
InfoAction action = data as InfoAction;
if ((object)action == null)
{
return Task.CompletedTask;
}
switch (action.Type)
{
case "copy":
if (string.IsNullOrWhiteSpace(action.Payload))
{
break;
}
try
{
((DispatcherObject)System.Windows.Application.Current).Dispatcher.Invoke((Action)delegate
{
System.Windows.Clipboard.SetText(action.Payload);
});
LogService.Info("클립보드 복사: " + action.Payload);
}
catch (Exception ex2)
{
LogService.Warn("클립보드 복사 실패: " + ex2.Message);
}
break;
case "open_drive":
if (!string.IsNullOrWhiteSpace(action.Payload))
{
try
{
Process.Start(new ProcessStartInfo("explorer.exe", action.Payload)
{
UseShellExecute = true
});
}
catch (Exception ex4)
{
LogService.Warn("드라이브 열기 실패: " + ex4.Message);
}
}
break;
case "resource_mon":
((DispatcherObject)System.Windows.Application.Current).Dispatcher.Invoke((Action)delegate
{
ResourceMonitorWindow resourceMonitorWindow = System.Windows.Application.Current.Windows.OfType<ResourceMonitorWindow>().FirstOrDefault();
if (resourceMonitorWindow != null)
{
resourceMonitorWindow.Activate();
}
else
{
new ResourceMonitorWindow().Show();
}
});
break;
case "shell":
if (!string.IsNullOrWhiteSpace(action.Payload))
{
try
{
Process.Start(new ProcessStartInfo(action.Payload)
{
UseShellExecute = true
});
}
catch (Exception ex3)
{
LogService.Warn("셸 명령 실행 실패: " + ex3.Message);
}
}
break;
case "ms_settings":
if (!string.IsNullOrWhiteSpace(action.Payload))
{
try
{
Process.Start(new ProcessStartInfo(action.Payload)
{
UseShellExecute = true
});
}
catch (Exception ex)
{
LogService.Warn("설정 열기 실패: " + ex.Message);
}
}
break;
}
return Task.CompletedTask;
}
private static LauncherItem MakeItem(string title, string subtitle, string? copyValue, string symbol)
{
return new LauncherItem(title, subtitle, null, (copyValue != null) ? new InfoAction("copy", copyValue) : null, null, symbol);
}
private static string? GetLocalIpAddress()
{
try
{
NetworkInterface[] allNetworkInterfaces = NetworkInterface.GetAllNetworkInterfaces();
foreach (NetworkInterface networkInterface in allNetworkInterfaces)
{
if (networkInterface.OperationalStatus != OperationalStatus.Up)
{
continue;
}
NetworkInterfaceType networkInterfaceType = networkInterface.NetworkInterfaceType;
if ((networkInterfaceType == NetworkInterfaceType.Loopback || networkInterfaceType == NetworkInterfaceType.Tunnel) ? true : false)
{
continue;
}
foreach (UnicastIPAddressInformation unicastAddress in networkInterface.GetIPProperties().UnicastAddresses)
{
if (unicastAddress.Address.AddressFamily == AddressFamily.InterNetwork)
{
return unicastAddress.Address.ToString();
}
}
}
}
catch
{
}
return null;
}
private static string? GetDefaultGateway()
{
try
{
NetworkInterface[] allNetworkInterfaces = NetworkInterface.GetAllNetworkInterfaces();
foreach (NetworkInterface networkInterface in allNetworkInterfaces)
{
if (networkInterface.OperationalStatus == OperationalStatus.Up)
{
GatewayIPAddressInformation gatewayIPAddressInformation = networkInterface.GetIPProperties().GatewayAddresses.FirstOrDefault((GatewayIPAddressInformation g) => g.Address.AddressFamily == AddressFamily.InterNetwork);
if (gatewayIPAddressInformation != null)
{
return gatewayIPAddressInformation.Address.ToString();
}
}
}
}
catch
{
}
return null;
}
private static LauncherItem? GetBatteryItem()
{
try
{
PowerStatus powerStatus = SystemInformation.PowerStatus;
float batteryLifePercent = powerStatus.BatteryLifePercent;
if (batteryLifePercent < 0f)
{
return new LauncherItem("배터리: 해당 없음", "데스크톱 PC 또는 항상 연결됨 · Enter로 전원 설정 열기", null, new InfoAction("ms_settings", "ms-settings:powersleep"), null, "\ue83f");
}
int num = (int)(batteryLifePercent * 100f);
bool flag = powerStatus.PowerLineStatus == System.Windows.Forms.PowerLineStatus.Online;
string text = ((powerStatus.BatteryLifeRemaining >= 0) ? (" · 잔여: " + FormatUptime(TimeSpan.FromSeconds(powerStatus.BatteryLifeRemaining))) : "");
string symbol = (flag ? "\ue83e" : ((num > 50) ? "\ue83f" : "\ueba0"));
return new LauncherItem($"배터리: {num}%{(flag ? " " : "")}", "전원: " + (flag ? "AC 연결됨" : "배터리 사용 중") + text + " · Enter로 전원 설정 열기", null, new InfoAction("ms_settings", "ms-settings:powersleep"), null, symbol);
}
catch
{
return null;
}
}
private static LauncherItem? GetVolumeItem()
{
try
{
if (waveOutGetVolume(IntPtr.Zero, out var dwVolume) == 0)
{
int num = (int)((double)(dwVolume & 0xFFFF) / 655.35);
int num2 = (int)((double)((dwVolume >> 16) & 0xFFFF) / 655.35);
int num3 = (num + num2) / 2;
return new LauncherItem($"볼륨: {num3}%", $"L: {num}% · R: {num2}% · Enter로 사운드 설정 열기", null, new InfoAction("ms_settings", "ms-settings:sound"), null, (num3 == 0) ? "\ue74f" : "\ue995");
}
}
catch
{
}
return null;
}
private static string GetOsVersion()
{
try
{
using RegistryKey registryKey = Registry.LocalMachine.OpenSubKey("SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion");
if (registryKey != null)
{
string text = (registryKey.GetValue("ProductName") as string) ?? "Windows";
string text2 = (registryKey.GetValue("CurrentBuildNumber") as string) ?? "";
object value = registryKey.GetValue("UBR");
return (value != null) ? $"{text} (빌드 {text2}.{value})" : (text + " (빌드 " + text2 + ")");
}
}
catch
{
}
return Environment.OSVersion.ToString();
}
private static string GetProcessorName()
{
try
{
using RegistryKey registryKey = Registry.LocalMachine.OpenSubKey("HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0");
return (registryKey?.GetValue("ProcessorNameString") as string) ?? "";
}
catch
{
return "";
}
}
private static string FormatUptime(TimeSpan t)
{
if (!(t.TotalDays >= 1.0))
{
if (!(t.TotalHours >= 1.0))
{
return $"{t.Minutes}분 {t.Seconds}초";
}
return $"{t.Hours}시간 {t.Minutes}분";
}
return $"{(int)t.TotalDays}일 {t.Hours}시간 {t.Minutes}분";
}
}