├── EdgeMonitor ├── Resources │ ├── README.txt │ └── about.gif ├── icon.ico ├── icon.jpg ├── App.xaml ├── Services │ ├── IConfigurationService.cs │ ├── InputDialog.xaml.cs │ ├── DataService.cs │ ├── DialogService.cs │ ├── InputDialog.xaml │ ├── IStartupService.cs │ ├── ILogService.cs │ ├── VersionHelper.cs │ ├── PrivilegeService.cs │ ├── ConfigurationService.cs │ ├── LogService.cs │ ├── TrayService.cs │ ├── EdgeMonitorService.cs │ └── StartupService.cs ├── appsettings.json ├── Enums │ └── CloseActionEnums.cs ├── Converters │ ├── EnumToBooleanConverter.cs │ └── ValueConverters.cs ├── CloseOptionsDialog.xaml.cs ├── EdgeMonitor.csproj ├── Commands │ └── RelayCommand.cs ├── CloseOptionsDialog.xaml ├── Views │ ├── AboutWindow.xaml │ └── AboutWindow.xaml.cs ├── App.xaml.cs ├── MainWindow.xaml.cs ├── Styles │ └── AppStyles.xaml ├── MainWindow.xaml └── ViewModels │ └── MainViewModel.cs ├── image.png ├── .gitignore ├── README.md ├── EdgeMonitor.sln ├── LICENSE └── VersionExtractionTest.cs /EdgeMonitor/Resources/README.txt: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PrelinaMontelli/Edge-Monitor/HEAD/image.png -------------------------------------------------------------------------------- /EdgeMonitor/icon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PrelinaMontelli/Edge-Monitor/HEAD/EdgeMonitor/icon.ico -------------------------------------------------------------------------------- /EdgeMonitor/icon.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PrelinaMontelli/Edge-Monitor/HEAD/EdgeMonitor/icon.jpg -------------------------------------------------------------------------------- /EdgeMonitor/Resources/about.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PrelinaMontelli/Edge-Monitor/HEAD/EdgeMonitor/Resources/about.gif -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | bin/ 2 | obj/ 3 | *.user 4 | *.suo 5 | .vs/ 6 | packages/ 7 | *.log 8 | *.tmp 9 | *.cache 10 | *.DotSettings 11 | .vscode/ 12 | .idea/ 13 | *.userprefs 14 | *.pidb 15 | *.userprefs 16 | *.DS_Store 17 | Thumbs.db 18 | EdgeMonitorV1.1.zip 19 | Prelina Montelli_0xE53985E5_public.asc 20 | EdgeMonitorV1.1/ 21 | publish/ 22 | update-version.ps1 23 | UPDATE_v1.3.1.md 24 | -------------------------------------------------------------------------------- /EdgeMonitor/App.xaml: -------------------------------------------------------------------------------- 1 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /EdgeMonitor/Services/IConfigurationService.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.Extensions.Configuration; 2 | 3 | namespace EdgeMonitor.Services 4 | { 5 | public interface IConfigurationService 6 | { 7 | /// 8 | /// 获取配置值 9 | /// 10 | T GetValue(string key); 11 | 12 | /// 13 | /// 设置配置值 14 | /// 15 | void SetValue(string key, object value); 16 | 17 | /// 18 | /// 保存配置到文件 19 | /// 20 | Task SaveAsync(); 21 | 22 | /// 23 | /// 重新加载配置 24 | /// 25 | void Reload(); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /EdgeMonitor/appsettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Information", 5 | "Microsoft": "Warning", 6 | "Microsoft.Hosting.Lifetime": "Information" 7 | } 8 | }, 9 | "ApplicationSettings": { 10 | "DefaultMonitorInterval": 5, 11 | "AutoSaveEnabled": true, 12 | "NotificationsEnabled": true, 13 | "LogRetentionDays": 30, 14 | "MaxLogEntries": 1000 15 | }, 16 | "EdgeMonitoring": { 17 | "CpuThreshold": 30.0, 18 | "MemoryThresholdMB": 2048, 19 | "CheckInterval": 5, 20 | "EnableAutoKill": true, 21 | "RequireAdminRights": true 22 | }, 23 | "UI": { 24 | "Theme": "Light", 25 | "Language": "zh-CN", 26 | "WindowWidth": 800, 27 | "WindowHeight": 600, 28 | "CloseToTray": null, 29 | "RememberCloseChoice": false, 30 | "StartupHideToTray": false 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /EdgeMonitor/Services/InputDialog.xaml.cs: -------------------------------------------------------------------------------- 1 | using System.Windows; 2 | 3 | namespace EdgeMonitor.Services 4 | { 5 | public partial class InputDialog : Window 6 | { 7 | public string InputText { get; set; } = ""; 8 | 9 | public InputDialog(string title, string prompt, string defaultValue = "") 10 | { 11 | InitializeComponent(); 12 | Title = title; 13 | PromptLabel.Content = prompt; 14 | InputTextBox.Text = defaultValue; 15 | InputText = defaultValue; 16 | } 17 | 18 | private void OkButton_Click(object sender, RoutedEventArgs e) 19 | { 20 | InputText = InputTextBox.Text; 21 | DialogResult = true; 22 | } 23 | 24 | private void CancelButton_Click(object sender, RoutedEventArgs e) 25 | { 26 | DialogResult = false; 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Edge Monitor 2 | 3 | 主播发现自己的电脑在启动一些软件或游戏时Edge会在后台自动启动,占用大量内存和CPU时间,故编写本程序来解决这个问题。 4 | 5 | 这个程序治标不治本,只能结束Edge,无法完全修复自动启动和异常占用的问题 6 | 7 | ![alt text](image.png) 8 | 9 | ## 条件 10 | 11 | 程序会在同时满足以下两个条件时自动终止Edge进程: 12 | 13 | 1. **后台运行状态**:Edge进程正在运行,但没有可见的用户界面窗口 14 | 2. **资源占用异常**:满足以下任一条件 15 | - CPU使用率超过 30% 16 | - 内存使用量超过 2GB 17 | 18 | 19 | ## 技术栈 20 | 21 | - .NET 7 22 | - WPF (Windows Presentation Foundation) 23 | - Microsoft Extensions (DI, Logging, Configuration, Hosting) 24 | - MVVM 模式 25 | 26 | 27 | ## 许可证 28 | 29 | 本项目采用 CC BY-NC 4.0(Creative Commons Attribution-NonCommercial 4.0 International)许可证。 30 | 31 | **阁下可以:** 32 | - ✅ 分享 — 在任何媒介以任何形式复制、发行本作品 33 | - ✅ 演绎 — 修改、转换或以本作品为基础进行创作 34 | 35 | **惟须遵守下列条件:** 36 | - 📝 **署名** — 阁下必须给出适当的署名,提供指向本许可协议的链接,同时标明是否(对原始作品)作了修改 37 | - 🚫 **非商业性使用** — 阁下不得将本作品用于商业目的 38 | 39 | **原作者:** Prelina Montelli 40 | 41 | 详细许可条款请参见:https://creativecommons.org/licenses/by-nc/4.0/ 42 | -------------------------------------------------------------------------------- /EdgeMonitor.sln: -------------------------------------------------------------------------------- 1 | Microsoft Visual Studio Solution File, Format Version 12.00 2 | # Visual Studio Version 17 3 | VisualStudioVersion = 17.0.31903.59 4 | MinimumVisualStudioVersion = 10.0.40219.1 5 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EdgeMonitor", "EdgeMonitor\EdgeMonitor.csproj", "{A1B2C3D4-E5F6-7890-ABCD-123456789ABC}" 6 | EndProject 7 | Global 8 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 9 | Debug|Any CPU = Debug|Any CPU 10 | Release|Any CPU = Release|Any CPU 11 | EndGlobalSection 12 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 13 | {A1B2C3D4-E5F6-7890-ABCD-123456789ABC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 14 | {A1B2C3D4-E5F6-7890-ABCD-123456789ABC}.Debug|Any CPU.Build.0 = Debug|Any CPU 15 | {A1B2C3D4-E5F6-7890-ABCD-123456789ABC}.Release|Any CPU.ActiveCfg = Release|Any CPU 16 | {A1B2C3D4-E5F6-7890-ABCD-123456789ABC}.Release|Any CPU.Build.0 = Release|Any CPU 17 | EndGlobalSection 18 | EndGlobal 19 | -------------------------------------------------------------------------------- /EdgeMonitor/Enums/CloseActionEnums.cs: -------------------------------------------------------------------------------- 1 | namespace EdgeMonitor 2 | { 3 | /// 4 | /// 窗口关闭行为枚举 5 | /// 6 | public enum CloseAction 7 | { 8 | /// 9 | /// 每次询问用户 10 | /// 11 | Ask, 12 | 13 | /// 14 | /// 最小化到托盘 15 | /// 16 | MinimizeToTray, 17 | 18 | /// 19 | /// 直接退出程序 20 | /// 21 | Exit 22 | } 23 | 24 | /// 25 | /// 关闭选项对话框的选择结果 26 | /// 27 | public enum CloseOption 28 | { 29 | /// 30 | /// 取消关闭 31 | /// 32 | Cancel, 33 | 34 | /// 35 | /// 最小化到托盘 36 | /// 37 | MinimizeToTray, 38 | 39 | /// 40 | /// 退出程序 41 | /// 42 | Exit 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Creative Commons Attribution-NonCommercial 4.0 International License 2 | 3 | Copyright (c) 2025 Prelina Montelli 4 | 5 | This work is licensed under the Creative Commons Attribution-NonCommercial 4.0 International License. 6 | 7 | You are free to: 8 | - Share — copy and redistribute the material in any medium or format 9 | - Adapt — remix, transform, and build upon the material 10 | 11 | Under the following terms: 12 | - Attribution — You must give appropriate credit, provide a link to the license, and indicate if changes were made. You may do so in any reasonable manner, but not in any way that suggests the licensor endorses you or your use. 13 | - NonCommercial — You may not use the material for commercial purposes. 14 | 15 | No additional restrictions — You may not apply legal terms or technological measures that legally restrict others from doing anything the license permits. 16 | 17 | To view a copy of this license, visit: 18 | https://creativecommons.org/licenses/by-nc/4.0/ 19 | 20 | Original Author: Prelina Montelli 21 | Project: Edge Monitor - A program to monitor and terminate Microsoft Edge processes when running abnormally in the background. 22 | -------------------------------------------------------------------------------- /EdgeMonitor/Converters/EnumToBooleanConverter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Globalization; 3 | using System.Windows.Data; 4 | 5 | namespace EdgeMonitor.Converters 6 | { 7 | public class EnumToBooleanConverter : IValueConverter 8 | { 9 | public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 10 | { 11 | if (value == null || parameter == null) 12 | return false; 13 | 14 | string enumValue = value.ToString(); 15 | string targetValue = parameter.ToString(); 16 | return enumValue?.Equals(targetValue, StringComparison.InvariantCultureIgnoreCase) == true; 17 | } 18 | 19 | public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) 20 | { 21 | if (value == null || parameter == null) 22 | return Binding.DoNothing; 23 | 24 | bool useValue = (bool)value; 25 | string targetValue = parameter.ToString(); 26 | if (useValue) 27 | { 28 | return Enum.Parse(targetType, targetValue); 29 | } 30 | return Binding.DoNothing; 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /EdgeMonitor/CloseOptionsDialog.xaml.cs: -------------------------------------------------------------------------------- 1 | using System.Windows; 2 | 3 | namespace EdgeMonitor 4 | { 5 | public partial class CloseOptionsDialog : Window 6 | { 7 | public CloseOption SelectedOption { get; private set; } = CloseOption.Cancel; 8 | public bool RememberChoice { get; private set; } = false; 9 | 10 | public CloseOptionsDialog() 11 | { 12 | InitializeComponent(); 13 | } 14 | 15 | private void OkButton_Click(object sender, RoutedEventArgs e) 16 | { 17 | if (MinimizeToTrayRadio.IsChecked == true) 18 | { 19 | SelectedOption = CloseOption.MinimizeToTray; 20 | } 21 | else if (ExitRadio.IsChecked == true) 22 | { 23 | SelectedOption = CloseOption.Exit; 24 | } 25 | 26 | RememberChoice = RememberChoiceCheckBox.IsChecked == true; 27 | 28 | DialogResult = true; 29 | Close(); 30 | } 31 | 32 | private void CancelButton_Click(object sender, RoutedEventArgs e) 33 | { 34 | SelectedOption = CloseOption.Cancel; 35 | DialogResult = false; 36 | Close(); 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /EdgeMonitor/Services/DataService.cs: -------------------------------------------------------------------------------- 1 | namespace EdgeMonitor.Services 2 | { 3 | public interface IDataService 4 | { 5 | Task LoadDataAsync(); 6 | Task SaveDataAsync(string data); 7 | Task> GetLogEntriesAsync(); 8 | Task AddLogEntryAsync(string entry); 9 | } 10 | 11 | public class DataService : IDataService 12 | { 13 | private readonly List _logEntries = new(); 14 | 15 | public async Task LoadDataAsync() 16 | { 17 | // 模拟异步数据加载 18 | await Task.Delay(100); 19 | return "示例数据已加载"; 20 | } 21 | 22 | public async Task SaveDataAsync(string data) 23 | { 24 | // 模拟异步数据保存 25 | await Task.Delay(100); 26 | await AddLogEntryAsync($"数据已保存: {data.Length} 字符"); 27 | } 28 | 29 | public async Task> GetLogEntriesAsync() 30 | { 31 | await Task.Delay(50); 32 | return new List(_logEntries); 33 | } 34 | 35 | public async Task AddLogEntryAsync(string entry) 36 | { 37 | await Task.Delay(10); 38 | _logEntries.Add($"[{DateTime.Now:yyyy-MM-dd HH:mm:ss}] {entry}"); 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /EdgeMonitor/Services/DialogService.cs: -------------------------------------------------------------------------------- 1 | using System.Windows; 2 | 3 | namespace EdgeMonitor.Services 4 | { 5 | public interface IDialogService 6 | { 7 | void ShowMessage(string title, string message); 8 | bool ShowConfirmation(string title, string message); 9 | string? ShowInputDialog(string title, string prompt, string defaultValue = ""); 10 | } 11 | 12 | public class DialogService : IDialogService 13 | { 14 | public void ShowMessage(string title, string message) 15 | { 16 | MessageBox.Show(message, title, MessageBoxButton.OK, MessageBoxImage.Information); 17 | } 18 | 19 | public bool ShowConfirmation(string title, string message) 20 | { 21 | var result = MessageBox.Show(message, title, MessageBoxButton.YesNo, MessageBoxImage.Question); 22 | return result == MessageBoxResult.Yes; 23 | } 24 | 25 | public string? ShowInputDialog(string title, string prompt, string defaultValue = "") 26 | { 27 | // 简单的输入对话框实现 28 | var inputDialog = new InputDialog(title, prompt, defaultValue); 29 | if (inputDialog.ShowDialog() == true) 30 | { 31 | return inputDialog.InputText; 32 | } 33 | return null; 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /EdgeMonitor/Converters/ValueConverters.cs: -------------------------------------------------------------------------------- 1 | using System.Globalization; 2 | using System.Windows.Data; 3 | 4 | namespace EdgeMonitor.Converters 5 | { 6 | public class BooleanToStringConverter : IValueConverter 7 | { 8 | public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 9 | { 10 | if (value is bool boolValue) 11 | { 12 | return boolValue ? "运行中" : "已停止"; 13 | } 14 | return "未知"; 15 | } 16 | 17 | public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) 18 | { 19 | throw new NotImplementedException(); 20 | } 21 | } 22 | 23 | public class InverseBooleanConverter : IValueConverter 24 | { 25 | public object Convert(object value, Type targetType, object parameter, CultureInfo culture) 26 | { 27 | if (value is bool boolValue) 28 | { 29 | return !boolValue; 30 | } 31 | return true; 32 | } 33 | 34 | public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) 35 | { 36 | if (value is bool boolValue) 37 | { 38 | return !boolValue; 39 | } 40 | return false; 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /EdgeMonitor/Services/InputDialog.xaml: -------------------------------------------------------------------------------- 1 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 |