233 lines
6.5 KiB
C#
233 lines
6.5 KiB
C#
using System;
|
|||
|
|
using System.CodeDom.Compiler;
|
||
|
|
using System.Collections;
|
||
|
|
using System.Collections.ObjectModel;
|
||
|
|
using System.ComponentModel;
|
||
|
|
using System.Diagnostics;
|
||
|
|
using System.IO;
|
||
|
|
using System.Linq;
|
||
|
|
using System.Windows;
|
||
|
|
using System.Windows.Controls;
|
||
|
|
using System.Windows.Controls.Primitives;
|
||
|
|
using System.Windows.Data;
|
||
|
|
using System.Windows.Input;
|
||
|
|
using System.Windows.Markup;
|
||
|
|
using System.Windows.Media;
|
||
|
|
using System.Windows.Media.Imaging;
|
||
|
|
using System.Windows.Threading;
|
||
|
|
using Crysome.Common.Network.Packets.Client;
|
||
|
|
using Crysome.Server.Model;
|
||
|
|
using Crysome.Server.ViewModel;
|
||
|
|
using Wpf.Ui.Controls;
|
||
|
|
|
||
|
|
namespace Crysome.Server.View;
|
||
|
|
|
||
|
|
public class ProcessManagerWindow : FluentWindow, IComponentConnector, IStyleConnector
|
||
|
|
{
|
||
|
|
private readonly ClientInfo _client;
|
||
|
|
|
||
|
|
private readonly ManageClientsViewModel _vm;
|
||
|
|
|
||
|
|
private readonly ObservableCollection<ProcessItemViewModel> _processes = new ObservableCollection<ProcessItemViewModel>();
|
||
|
|
|
||
|
|
private readonly ICollectionView _processView;
|
||
|
|
|
||
|
|
internal TextBlock TitleText;
|
||
|
|
|
||
|
|
internal Button RefreshBtn;
|
||
|
|
|
||
|
|
internal Button CloseBtn;
|
||
|
|
|
||
|
|
internal TextBox SearchBox;
|
||
|
|
|
||
|
|
internal ListView ProcessList;
|
||
|
|
|
||
|
|
internal TextBlock StatusText;
|
||
|
|
|
||
|
|
private bool _contentLoaded;
|
||
|
|
|
||
|
|
public ProcessManagerWindow(ClientInfo client, ManageClientsViewModel vm)
|
||
|
|
{
|
||
|
|
InitializeComponent();
|
||
|
|
_client = client;
|
||
|
|
_vm = vm;
|
||
|
|
((Window)this).Title = "Process Manager — " + (client?.Address ?? "?");
|
||
|
|
TitleText.Text = ((Window)this).Title;
|
||
|
|
_processView = CollectionViewSource.GetDefaultView(_processes);
|
||
|
|
ProcessList.ItemsSource = (IEnumerable)_processView;
|
||
|
|
((FrameworkElement)this).Loaded += delegate
|
||
|
|
{
|
||
|
|
Refresh();
|
||
|
|
};
|
||
|
|
}
|
||
|
|
|
||
|
|
private void Refresh()
|
||
|
|
{
|
||
|
|
_processes.Clear();
|
||
|
|
StatusText.Text = "Loading...";
|
||
|
|
_vm.RequestProcessList(_client, delegate(GetProcessListResponsePacket packet)
|
||
|
|
{
|
||
|
|
if (((packet != null) ? packet.Processes : null) != null)
|
||
|
|
{
|
||
|
|
foreach (ProcessListEntry process in packet.Processes)
|
||
|
|
{
|
||
|
|
ImageSource icon = LoadIcon(process.IconData);
|
||
|
|
_processes.Add(new ProcessItemViewModel
|
||
|
|
{
|
||
|
|
Name = process.Name,
|
||
|
|
Pid = process.Pid,
|
||
|
|
Icon = icon
|
||
|
|
});
|
||
|
|
}
|
||
|
|
((DispatcherObject)Application.Current).Dispatcher.Invoke((Action)delegate
|
||
|
|
{
|
||
|
|
ApplySearchFilter();
|
||
|
|
});
|
||
|
|
}
|
||
|
|
});
|
||
|
|
}
|
||
|
|
|
||
|
|
private void SearchBox_TextChanged(object sender, TextChangedEventArgs e)
|
||
|
|
{
|
||
|
|
ApplySearchFilter();
|
||
|
|
}
|
||
|
|
|
||
|
|
private void ApplySearchFilter()
|
||
|
|
{
|
||
|
|
string q = (SearchBox?.Text ?? "").Trim().ToLowerInvariant();
|
||
|
|
_processView.Filter = (string.IsNullOrEmpty(q) ? null : ((Predicate<object>)((object o) => o is ProcessItemViewModel processItemViewModel && ((processItemViewModel.Name ?? "").ToLowerInvariant().Contains(q) || processItemViewModel.Pid.ToString().Contains(q)))));
|
||
|
|
int num = (string.IsNullOrEmpty(q) ? _processes.Count : ((IEnumerable)_processView).Cast<object>().Count());
|
||
|
|
StatusText.Text = (string.IsNullOrEmpty(q) ? (_processes.Count + " processes") : (num + " of " + _processes.Count + " processes"));
|
||
|
|
}
|
||
|
|
|
||
|
|
private static ImageSource LoadIcon(byte[] data)
|
||
|
|
{
|
||
|
|
if (data == null || data.Length == 0)
|
||
|
|
{
|
||
|
|
return null;
|
||
|
|
}
|
||
|
|
try
|
||
|
|
{
|
||
|
|
BitmapImage bitmapImage = new BitmapImage();
|
||
|
|
bitmapImage.BeginInit();
|
||
|
|
bitmapImage.StreamSource = new MemoryStream(data);
|
||
|
|
bitmapImage.CacheOption = BitmapCacheOption.OnLoad;
|
||
|
|
bitmapImage.EndInit();
|
||
|
|
((Freezable)bitmapImage).Freeze();
|
||
|
|
return bitmapImage;
|
||
|
|
}
|
||
|
|
catch
|
||
|
|
{
|
||
|
|
return null;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
private void RefreshBtn_Click(object sender, RoutedEventArgs e)
|
||
|
|
{
|
||
|
|
Refresh();
|
||
|
|
}
|
||
|
|
|
||
|
|
private void CloseBtn_Click(object sender, RoutedEventArgs e)
|
||
|
|
{
|
||
|
|
((Window)this).Close();
|
||
|
|
}
|
||
|
|
|
||
|
|
private void Header_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
|
||
|
|
{
|
||
|
|
try
|
||
|
|
{
|
||
|
|
((Window)this).DragMove();
|
||
|
|
}
|
||
|
|
catch
|
||
|
|
{
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
private void KillBtn_Click(object sender, RoutedEventArgs e)
|
||
|
|
{
|
||
|
|
if ((sender as FrameworkElement)?.DataContext is ProcessItemViewModel processItemViewModel)
|
||
|
|
{
|
||
|
|
_vm.KillProcessOnClient(_client, processItemViewModel.Pid);
|
||
|
|
_processes.Remove(processItemViewModel);
|
||
|
|
StatusText.Text = "Kill sent for PID " + processItemViewModel.Pid;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
private void ProcessList_MouseDoubleClick(object sender, MouseButtonEventArgs e)
|
||
|
|
{
|
||
|
|
if (ProcessList.SelectedItem is ProcessItemViewModel processItemViewModel)
|
||
|
|
{
|
||
|
|
_vm.KillProcessOnClient(_client, processItemViewModel.Pid);
|
||
|
|
_processes.Remove(processItemViewModel);
|
||
|
|
StatusText.Text = "Kill sent for PID " + processItemViewModel.Pid;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
[DebuggerNonUserCode]
|
||
|
|
[GeneratedCode("PresentationBuildTasks", "9.0.14.0")]
|
||
|
|
public void InitializeComponent()
|
||
|
|
{
|
||
|
|
if (!_contentLoaded)
|
||
|
|
{
|
||
|
|
_contentLoaded = true;
|
||
|
|
Uri resourceLocator = new Uri("/Crysome.Server;component/view/processmanagerwindow.xaml", UriKind.Relative);
|
||
|
|
Application.LoadComponent(this, resourceLocator);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
[DebuggerNonUserCode]
|
||
|
|
[GeneratedCode("PresentationBuildTasks", "9.0.14.0")]
|
||
|
|
[EditorBrowsable(EditorBrowsableState.Never)]
|
||
|
|
void IComponentConnector.Connect(int connectionId, object target)
|
||
|
|
{
|
||
|
|
//IL_0054: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_005e: Expected O, but got Unknown
|
||
|
|
//IL_0078: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_0082: Expected O, but got Unknown
|
||
|
|
switch (connectionId)
|
||
|
|
{
|
||
|
|
case 1:
|
||
|
|
((Border)target).MouseLeftButtonDown += Header_MouseLeftButtonDown;
|
||
|
|
break;
|
||
|
|
case 2:
|
||
|
|
TitleText = (TextBlock)target;
|
||
|
|
break;
|
||
|
|
case 3:
|
||
|
|
RefreshBtn = (Button)target;
|
||
|
|
((ButtonBase)(object)RefreshBtn).Click += RefreshBtn_Click;
|
||
|
|
break;
|
||
|
|
case 4:
|
||
|
|
CloseBtn = (Button)target;
|
||
|
|
((ButtonBase)(object)CloseBtn).Click += CloseBtn_Click;
|
||
|
|
break;
|
||
|
|
case 5:
|
||
|
|
SearchBox = (TextBox)target;
|
||
|
|
SearchBox.TextChanged += SearchBox_TextChanged;
|
||
|
|
break;
|
||
|
|
case 6:
|
||
|
|
ProcessList = (ListView)target;
|
||
|
|
ProcessList.MouseDoubleClick += ProcessList_MouseDoubleClick;
|
||
|
|
break;
|
||
|
|
case 8:
|
||
|
|
StatusText = (TextBlock)target;
|
||
|
|
break;
|
||
|
|
default:
|
||
|
|
_contentLoaded = true;
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
[DebuggerNonUserCode]
|
||
|
|
[GeneratedCode("PresentationBuildTasks", "9.0.14.0")]
|
||
|
|
[EditorBrowsable(EditorBrowsableState.Never)]
|
||
|
|
void IStyleConnector.Connect(int connectionId, object target)
|
||
|
|
{
|
||
|
|
//IL_0005: Unknown result type (might be due to invalid IL or missing references)
|
||
|
|
//IL_001b: Expected O, but got Unknown
|
||
|
|
if (connectionId == 7)
|
||
|
|
{
|
||
|
|
((ButtonBase)(Button)target).Click += KillBtn_Click;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|