547 lines
12 KiB
C#
547 lines
12 KiB
C#
using System;
|
|
using System.CodeDom.Compiler;
|
|
using System.Collections.Generic;
|
|
using System.Collections.ObjectModel;
|
|
using System.ComponentModel;
|
|
using System.Diagnostics;
|
|
using System.IO;
|
|
using System.Linq;
|
|
using System.Runtime.CompilerServices;
|
|
using System.Runtime.InteropServices;
|
|
using System.Windows;
|
|
using System.Windows.Controls;
|
|
using System.Windows.Input;
|
|
using System.Windows.Interop;
|
|
using System.Windows.Markup;
|
|
using System.Windows.Media;
|
|
using System.Windows.Threading;
|
|
using Microsoft.Win32;
|
|
|
|
namespace AxCopilot.Views;
|
|
|
|
public class ResourceMonitorWindow : Window, IComponentConnector
|
|
{
|
|
[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;
|
|
}
|
|
|
|
public sealed class DriveDisplayItem : INotifyPropertyChanged
|
|
{
|
|
private string _label = "";
|
|
|
|
private string _detail = "";
|
|
|
|
private double _barWidth = 0.0;
|
|
|
|
private Brush _barColor = Brushes.Green;
|
|
|
|
public string Label
|
|
{
|
|
get
|
|
{
|
|
return _label;
|
|
}
|
|
set
|
|
{
|
|
_label = value;
|
|
OnPropertyChanged("Label");
|
|
}
|
|
}
|
|
|
|
public string Detail
|
|
{
|
|
get
|
|
{
|
|
return _detail;
|
|
}
|
|
set
|
|
{
|
|
_detail = value;
|
|
OnPropertyChanged("Detail");
|
|
}
|
|
}
|
|
|
|
public double BarWidth
|
|
{
|
|
get
|
|
{
|
|
return _barWidth;
|
|
}
|
|
set
|
|
{
|
|
_barWidth = value;
|
|
OnPropertyChanged("BarWidth");
|
|
}
|
|
}
|
|
|
|
public Brush BarColor
|
|
{
|
|
get
|
|
{
|
|
return _barColor;
|
|
}
|
|
set
|
|
{
|
|
_barColor = value;
|
|
OnPropertyChanged("BarColor");
|
|
}
|
|
}
|
|
|
|
public ICommand OpenCommand { get; init; } = null;
|
|
|
|
public event PropertyChangedEventHandler? PropertyChanged;
|
|
|
|
private void OnPropertyChanged([CallerMemberName] string? n = null)
|
|
{
|
|
this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(n));
|
|
}
|
|
}
|
|
|
|
public sealed class ProcessDisplayItem
|
|
{
|
|
public string Rank { get; init; } = "";
|
|
|
|
public string Name { get; init; } = "";
|
|
|
|
public string MemText { get; init; } = "";
|
|
|
|
public double BarWidth { get; init; }
|
|
}
|
|
|
|
private sealed class RelayCommand(Action execute) : ICommand
|
|
{
|
|
public event EventHandler? CanExecuteChanged
|
|
{
|
|
add
|
|
{
|
|
}
|
|
remove
|
|
{
|
|
}
|
|
}
|
|
|
|
public bool CanExecute(object? _)
|
|
{
|
|
return true;
|
|
}
|
|
|
|
public void Execute(object? _)
|
|
{
|
|
execute();
|
|
}
|
|
}
|
|
|
|
private const int WM_NCLBUTTONDOWN = 161;
|
|
|
|
private const int HTBOTTOMRIGHT = 17;
|
|
|
|
private readonly DispatcherTimer _timer;
|
|
|
|
private static PerformanceCounter? _cpuCounter;
|
|
|
|
private static float _cpuCached;
|
|
|
|
private static DateTime _cpuUpdated = DateTime.MinValue;
|
|
|
|
private readonly ObservableCollection<DriveDisplayItem> _drives = new ObservableCollection<DriveDisplayItem>();
|
|
|
|
private const double MaxBarWidth = 160.0;
|
|
|
|
internal TextBlock RefreshLabel;
|
|
|
|
internal TextBlock CpuValueText;
|
|
|
|
internal Border CpuBar;
|
|
|
|
internal TextBlock CpuNameText;
|
|
|
|
internal TextBlock RamValueText;
|
|
|
|
internal Border RamBar;
|
|
|
|
internal TextBlock RamDetailText;
|
|
|
|
internal ItemsControl DriveList;
|
|
|
|
internal ItemsControl ProcessList;
|
|
|
|
internal TextBlock UptimeText;
|
|
|
|
private bool _contentLoaded;
|
|
|
|
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
|
|
[return: MarshalAs(UnmanagedType.Bool)]
|
|
private static extern bool GlobalMemoryStatusEx(ref MEMORYSTATUSEX lpBuffer);
|
|
|
|
[DllImport("user32.dll")]
|
|
private static extern void ReleaseCapture();
|
|
|
|
[DllImport("user32.dll")]
|
|
private static extern nint SendMessage(nint hWnd, int msg, nint wParam, nint lParam);
|
|
|
|
public ResourceMonitorWindow()
|
|
{
|
|
//IL_006f: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0074: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_008e: Expected O, but got Unknown
|
|
InitializeComponent();
|
|
DriveList.ItemsSource = _drives;
|
|
if (_cpuCounter == null)
|
|
{
|
|
try
|
|
{
|
|
_cpuCounter = new PerformanceCounter("Processor", "% Processor Time", "_Total");
|
|
_cpuCounter.NextValue();
|
|
}
|
|
catch
|
|
{
|
|
}
|
|
}
|
|
InitDrives();
|
|
_timer = new DispatcherTimer
|
|
{
|
|
Interval = TimeSpan.FromSeconds(1.0)
|
|
};
|
|
_timer.Tick += delegate
|
|
{
|
|
Refresh();
|
|
};
|
|
_timer.Start();
|
|
Refresh();
|
|
}
|
|
|
|
private void InitDrives()
|
|
{
|
|
_drives.Clear();
|
|
foreach (DriveInfo item in from d in DriveInfo.GetDrives()
|
|
where d.IsReady && d.DriveType == DriveType.Fixed
|
|
select d)
|
|
{
|
|
string root = item.RootDirectory.FullName;
|
|
_drives.Add(new DriveDisplayItem
|
|
{
|
|
OpenCommand = new RelayCommand(delegate
|
|
{
|
|
try
|
|
{
|
|
Process.Start(new ProcessStartInfo("explorer.exe", root)
|
|
{
|
|
UseShellExecute = true
|
|
});
|
|
}
|
|
catch
|
|
{
|
|
}
|
|
})
|
|
});
|
|
}
|
|
}
|
|
|
|
private void Refresh()
|
|
{
|
|
RefreshCpu();
|
|
RefreshRam();
|
|
RefreshDrives();
|
|
RefreshProcesses();
|
|
RefreshUptime();
|
|
}
|
|
|
|
private void RefreshCpu()
|
|
{
|
|
try
|
|
{
|
|
if (_cpuCounter == null)
|
|
{
|
|
CpuValueText.Text = "—";
|
|
return;
|
|
}
|
|
if ((DateTime.Now - _cpuUpdated).TotalMilliseconds > 800.0)
|
|
{
|
|
_cpuCached = _cpuCounter.NextValue();
|
|
_cpuUpdated = DateTime.Now;
|
|
}
|
|
int num = (int)Math.Clamp(_cpuCached, 0f, 100f);
|
|
CpuValueText.Text = $"{num}%";
|
|
SolidColorBrush solidColorBrush = ((num > 80) ? new SolidColorBrush(Color.FromRgb(220, 38, 38)) : ((num > 50) ? new SolidColorBrush(Color.FromRgb(217, 119, 6)) : new SolidColorBrush(Color.FromRgb(75, 158, 252))));
|
|
CpuValueText.Foreground = solidColorBrush;
|
|
CpuBar.Background = solidColorBrush;
|
|
Border cpuBar = CpuBar;
|
|
FrameworkElement obj = CpuBar.Parent as FrameworkElement;
|
|
cpuBar.Width = ((obj != null) ? (obj.ActualWidth * (double)num / 100.0) : 0.0);
|
|
if (string.IsNullOrEmpty(CpuNameText.Text))
|
|
{
|
|
CpuNameText.Text = GetProcessorName();
|
|
}
|
|
}
|
|
catch
|
|
{
|
|
CpuValueText.Text = "—";
|
|
}
|
|
}
|
|
|
|
private void RefreshRam()
|
|
{
|
|
MEMORYSTATUSEX lpBuffer = new MEMORYSTATUSEX
|
|
{
|
|
dwLength = (uint)Marshal.SizeOf<MEMORYSTATUSEX>()
|
|
};
|
|
if (GlobalMemoryStatusEx(ref lpBuffer))
|
|
{
|
|
double value = (double)lpBuffer.ullTotalPhys / 1024.0 / 1024.0 / 1024.0;
|
|
double value2 = (double)(lpBuffer.ullTotalPhys - lpBuffer.ullAvailPhys) / 1024.0 / 1024.0 / 1024.0;
|
|
double value3 = (double)lpBuffer.ullAvailPhys / 1024.0 / 1024.0 / 1024.0;
|
|
int dwMemoryLoad = (int)lpBuffer.dwMemoryLoad;
|
|
RamValueText.Text = $"{dwMemoryLoad}%";
|
|
RamDetailText.Text = $"사용: {value2:F1} GB / 전체: {value:F1} GB / 여유: {value3:F1} GB";
|
|
Border ramBar = RamBar;
|
|
FrameworkElement obj = RamBar.Parent as FrameworkElement;
|
|
ramBar.Width = ((obj != null) ? (obj.ActualWidth * (double)dwMemoryLoad / 100.0) : 0.0);
|
|
SolidColorBrush solidColorBrush = ((dwMemoryLoad > 85) ? new SolidColorBrush(Color.FromRgb(220, 38, 38)) : ((dwMemoryLoad > 65) ? new SolidColorBrush(Color.FromRgb(217, 119, 6)) : new SolidColorBrush(Color.FromRgb(124, 58, 237))));
|
|
RamValueText.Foreground = solidColorBrush;
|
|
RamBar.Background = solidColorBrush;
|
|
}
|
|
}
|
|
|
|
private void RefreshDrives()
|
|
{
|
|
List<DriveInfo> list = (from d in DriveInfo.GetDrives()
|
|
where d.IsReady && d.DriveType == DriveType.Fixed
|
|
select d).ToList();
|
|
if (list.Count != _drives.Count)
|
|
{
|
|
InitDrives();
|
|
}
|
|
for (int num = 0; num < list.Count && num < _drives.Count; num++)
|
|
{
|
|
DriveInfo driveInfo = list[num];
|
|
double num2 = (double)driveInfo.TotalSize / 1024.0 / 1024.0 / 1024.0;
|
|
double num3 = (double)driveInfo.AvailableFreeSpace / 1024.0 / 1024.0 / 1024.0;
|
|
double num4 = num2 - num3;
|
|
int num5 = (int)(num4 / num2 * 100.0);
|
|
string label = (string.IsNullOrWhiteSpace(driveInfo.VolumeLabel) ? driveInfo.Name.TrimEnd('\\') : (driveInfo.Name.TrimEnd('\\') + " (" + driveInfo.VolumeLabel + ")"));
|
|
_drives[num].Label = label;
|
|
_drives[num].Detail = $"{num3:F1}GB 여유";
|
|
_drives[num].BarWidth = 160.0 * (double)num5 / 100.0;
|
|
_drives[num].BarColor = ((num5 > 90) ? new SolidColorBrush(Color.FromRgb(220, 38, 38)) : ((num5 > 75) ? new SolidColorBrush(Color.FromRgb(217, 119, 6)) : new SolidColorBrush(Color.FromRgb(5, 150, 105))));
|
|
}
|
|
}
|
|
|
|
private void RefreshProcesses()
|
|
{
|
|
try
|
|
{
|
|
List<Process> list = Process.GetProcesses().OrderByDescending(delegate(Process p)
|
|
{
|
|
try
|
|
{
|
|
return p.WorkingSet64;
|
|
}
|
|
catch
|
|
{
|
|
return 0L;
|
|
}
|
|
}).Take(7)
|
|
.ToList();
|
|
long maxMem = ((list.Count <= 0) ? 1 : ((list[0].WorkingSet64 > 0) ? list[0].WorkingSet64 : 1));
|
|
List<ProcessDisplayItem> itemsSource = list.Select(delegate(Process p, int i)
|
|
{
|
|
long num = 0L;
|
|
string text = "";
|
|
try
|
|
{
|
|
num = p.WorkingSet64;
|
|
text = p.ProcessName;
|
|
}
|
|
catch
|
|
{
|
|
text = "—";
|
|
}
|
|
double num2 = (double)num / 1024.0 / 1024.0;
|
|
return new ProcessDisplayItem
|
|
{
|
|
Rank = $"{i + 1}",
|
|
Name = text,
|
|
MemText = ((num2 > 1024.0) ? $"{num2 / 1024.0:F1} GB" : $"{num2:F0} MB"),
|
|
BarWidth = Math.Max(2.0, 46.0 * (double)num / (double)maxMem)
|
|
};
|
|
}).ToList();
|
|
ProcessList.ItemsSource = itemsSource;
|
|
}
|
|
catch
|
|
{
|
|
}
|
|
}
|
|
|
|
private void RefreshUptime()
|
|
{
|
|
TimeSpan timeSpan = TimeSpan.FromMilliseconds(Environment.TickCount64);
|
|
int num = (int)timeSpan.TotalDays;
|
|
int hours = timeSpan.Hours;
|
|
int minutes = timeSpan.Minutes;
|
|
UptimeText.Text = ((num > 0) ? $"가동: {num}일 {hours}시간 {minutes}분" : ((hours > 0) ? $"가동: {hours}시간 {minutes}분" : $"가동: {minutes}분 {timeSpan.Seconds}초"));
|
|
}
|
|
|
|
private void ResizeGrip_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
|
|
{
|
|
if (e.ButtonState == MouseButtonState.Pressed)
|
|
{
|
|
ReleaseCapture();
|
|
SendMessage(new WindowInteropHelper(this).Handle, 161, 17, IntPtr.Zero);
|
|
}
|
|
}
|
|
|
|
private void Close_Click(object sender, RoutedEventArgs e)
|
|
{
|
|
Close();
|
|
}
|
|
|
|
private void Window_KeyDown(object sender, KeyEventArgs e)
|
|
{
|
|
//IL_0002: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0009: Invalid comparison between Unknown and I4
|
|
if ((int)e.Key == 13)
|
|
{
|
|
Close();
|
|
}
|
|
}
|
|
|
|
private void Window_MouseDown(object sender, MouseButtonEventArgs e)
|
|
{
|
|
if (e.ChangedButton == MouseButton.Left && e.LeftButton == MouseButtonState.Pressed)
|
|
{
|
|
try
|
|
{
|
|
DragMove();
|
|
}
|
|
catch
|
|
{
|
|
}
|
|
}
|
|
}
|
|
|
|
protected override void OnMouseWheel(MouseWheelEventArgs e)
|
|
{
|
|
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0007: Invalid comparison between Unknown and I4
|
|
if ((int)Keyboard.Modifiers == 2)
|
|
{
|
|
int num = ((e.Delta > 0) ? 40 : (-40));
|
|
double num2 = base.Height + (double)num;
|
|
if (num2 >= base.MinHeight && num2 <= 900.0)
|
|
{
|
|
base.Height = num2;
|
|
}
|
|
e.Handled = true;
|
|
}
|
|
else
|
|
{
|
|
base.OnMouseWheel(e);
|
|
}
|
|
}
|
|
|
|
protected override void OnClosed(EventArgs e)
|
|
{
|
|
_timer.Stop();
|
|
base.OnClosed(e);
|
|
}
|
|
|
|
private static string GetProcessorName()
|
|
{
|
|
try
|
|
{
|
|
using RegistryKey registryKey = Registry.LocalMachine.OpenSubKey("HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0");
|
|
return (registryKey?.GetValue("ProcessorNameString") as string) ?? "";
|
|
}
|
|
catch
|
|
{
|
|
return "";
|
|
}
|
|
}
|
|
|
|
[DebuggerNonUserCode]
|
|
[GeneratedCode("PresentationBuildTasks", "10.0.5.0")]
|
|
public void InitializeComponent()
|
|
{
|
|
if (!_contentLoaded)
|
|
{
|
|
_contentLoaded = true;
|
|
Uri resourceLocator = new Uri("/AxCopilot;component/views/resourcemonitorwindow.xaml", UriKind.Relative);
|
|
Application.LoadComponent(this, resourceLocator);
|
|
}
|
|
}
|
|
|
|
[DebuggerNonUserCode]
|
|
[GeneratedCode("PresentationBuildTasks", "10.0.5.0")]
|
|
[EditorBrowsable(EditorBrowsableState.Never)]
|
|
void IComponentConnector.Connect(int connectionId, object target)
|
|
{
|
|
switch (connectionId)
|
|
{
|
|
case 1:
|
|
((ResourceMonitorWindow)target).MouseDown += Window_MouseDown;
|
|
((ResourceMonitorWindow)target).KeyDown += Window_KeyDown;
|
|
break;
|
|
case 2:
|
|
RefreshLabel = (TextBlock)target;
|
|
break;
|
|
case 3:
|
|
((Button)target).Click += Close_Click;
|
|
break;
|
|
case 4:
|
|
CpuValueText = (TextBlock)target;
|
|
break;
|
|
case 5:
|
|
CpuBar = (Border)target;
|
|
break;
|
|
case 6:
|
|
CpuNameText = (TextBlock)target;
|
|
break;
|
|
case 7:
|
|
RamValueText = (TextBlock)target;
|
|
break;
|
|
case 8:
|
|
RamBar = (Border)target;
|
|
break;
|
|
case 9:
|
|
RamDetailText = (TextBlock)target;
|
|
break;
|
|
case 10:
|
|
DriveList = (ItemsControl)target;
|
|
break;
|
|
case 11:
|
|
ProcessList = (ItemsControl)target;
|
|
break;
|
|
case 12:
|
|
((Border)target).MouseLeftButtonDown += ResizeGrip_MouseLeftButtonDown;
|
|
break;
|
|
case 13:
|
|
UptimeText = (TextBlock)target;
|
|
break;
|
|
case 14:
|
|
((Button)target).Click += Close_Click;
|
|
break;
|
|
default:
|
|
_contentLoaded = true;
|
|
break;
|
|
}
|
|
}
|
|
}
|