This commit is contained in:
ded_ikar
2026-05-04 01:50:35 +05:00
parent ac895d964a
commit e7ea83daa0
10 changed files with 309 additions and 103 deletions
+60 -7
View File
@@ -108,7 +108,7 @@ namespace QoSManager.Services
private string GetPolicyStore()
{
return $"GPO:{Environment.MachineName}";
return "localhost";
}
private static string EscapePowerShellString(string value)
@@ -251,7 +251,7 @@ namespace QoSManager.Services
var escapedName = EscapePowerShellString(policy.Name);
var escapedProcess = EscapePowerShellString(policy.Process);
var escapedStore = EscapePowerShellString(GetPolicyStore());
var command = $"New-NetQosPolicy -Name '{escapedName}' -AppPathNameMatchCondition '{escapedProcess}' -DSCPAction {policy.DSCP} -PolicyStore '{escapedStore}'";
var command = $"New-NetQosPolicy -Name '{escapedName}' -AppPathNameMatchCondition '{escapedProcess}' -DSCPAction {policy.DSCP} -PolicyStore '{escapedStore}' -NetworkProfile All";
var encodedCommand = Convert.ToBase64String(Encoding.Unicode.GetBytes(command));
var startInfo = new ProcessStartInfo
@@ -291,7 +291,7 @@ namespace QoSManager.Services
{
try
{
_logger.LogInformation("Refreshing Group Policy to synchronize with gpedit.msc");
LogInformation("Refreshing Group Policy to synchronize with gpedit.msc");
var startInfo = new ProcessStartInfo
{
FileName = "cmd.exe",
@@ -310,19 +310,19 @@ namespace QoSManager.Services
var output = process.StandardOutput.ReadToEnd();
var error = process.StandardError.ReadToEnd();
_logger.LogInformation($"Gpupdate output: {output}");
LogInformation($"Gpupdate output: {output}");
if (!string.IsNullOrEmpty(error))
{
_logger.LogInformation($"Gpupdate error: {error}");
LogInformation($"Gpupdate error: {error}");
}
if (process.ExitCode == 0)
{
_logger.LogInformation("Group Policy updated successfully");
LogInformation("Group Policy updated successfully");
}
else
{
_logger.LogInformation($"Group Policy update returned exit code: {process.ExitCode}");
LogInformation($"Group Policy update returned exit code: {process.ExitCode}");
}
}
}
@@ -332,6 +332,59 @@ namespace QoSManager.Services
}
}
public void RefreshQoSPolicies()
{
try
{
if (_loggingEnabled)
{
LogInformation("Force refreshing QoS policies to ensure they apply after reboot");
}
// Force update Group Policy
RefreshGroupPolicy();
// Restart QoS service to ensure policies apply
var startInfo = new ProcessStartInfo
{
FileName = "cmd.exe",
Arguments = "/c sc query QWAVE | find \"STATE\" && net stop QWAVE && net start QWAVE || net start QWAVE",
UseShellExecute = false,
RedirectStandardOutput = true,
RedirectStandardError = true,
CreateNoWindow = true,
StandardOutputEncoding = System.Text.Encoding.UTF8,
StandardErrorEncoding = System.Text.Encoding.UTF8
};
using (var process = Process.Start(startInfo))
{
process.WaitForExit();
var output = process.StandardOutput.ReadToEnd();
var error = process.StandardError.ReadToEnd();
LogInformation($"QoS service restart output: {output}");
if (!string.IsNullOrEmpty(error))
{
LogInformation($"QoS service restart error: {error}");
}
if (process.ExitCode == 0)
{
LogInformation("QoS service restarted successfully");
}
else
{
LogInformation($"QoS service restart returned exit code: {process.ExitCode}");
}
}
}
catch (Exception ex)
{
_logger.LogError(ex, "Error refreshing QoS policies");
}
}
public void DeletePolicy(string policyName, bool autoRefreshGPO = true)
{
try
-1
View File
@@ -6,7 +6,6 @@
ResizeMode="NoResize"
SizeToContent="WidthAndHeight"
Background="#2D2D2D"
WindowStyle="SingleBorderWindow"
BorderBrush="#444444"
BorderThickness="1"
FontFamily="Segoe UI"
+15
View File
@@ -1,4 +1,5 @@
using System.Windows;
using System.Windows.Input;
namespace QoSManager.Views
{
@@ -83,5 +84,19 @@ namespace QoSManager.Views
Result = MessageBoxResult.No;
Close();
}
private void TitleBar_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
if (e.ChangedButton == MouseButton.Left)
{
DragMove();
}
}
private void CloseButton_Click(object sender, RoutedEventArgs e)
{
Result = MessageBoxResult.Cancel;
Close();
}
}
}
+87 -70
View File
@@ -8,74 +8,75 @@
Background="#1E1E1E">
<Grid Margin="20">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<!-- Заголовок -->
<StackPanel Grid.Row="0" Margin="0,0,0,20">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<StackPanel Grid.Column="0">
<TextBlock Text="Управление QoS-политиками Windows"
FontSize="18"
FontWeight="SemiBold"
Foreground="White"/>
<TextBlock Text="Добавляйте, удаляйте и просматривайте политики для отдельных процессов."
FontSize="12"
Foreground="#A0A0A0"
Margin="0,5,0,10"/>
</StackPanel>
<StackPanel Grid.Column="1"
Orientation="Horizontal"
VerticalAlignment="Top"
Margin="20,0,0,0">
<CheckBox x:Name="LoggingCheckBox"
Content="Вести логи"
Width="120"
Height="30"
Foreground="White"
VerticalContentAlignment="Center"/>
</StackPanel>
</Grid>
</StackPanel>
<!-- Таблица политик -->
<DataGrid x:Name="PoliciesDataGrid"
Grid.Row="1"
AutoGenerateColumns="False"
CanUserAddRows="False"
CanUserDeleteRows="False"
CanUserReorderColumns="False"
CanUserResizeRows="False"
IsReadOnly="True"
BeginningEdit="PoliciesDataGrid_BeginningEdit"
CellEditEnding="PoliciesDataGrid_CellEditEnding"
GridLinesVisibility="All"
HorizontalGridLinesBrush="#333333"
VerticalGridLinesBrush="#555555"
Background="#2D2D2D"
Foreground="White"
BorderBrush="#444444"
BorderThickness="1"
HeadersVisibility="Column"
SelectionMode="Single"
AlternatingRowBackground="#252525"
RowHeight="30"
MinRowHeight="25"
VirtualizingPanel.IsVirtualizing="True"
VirtualizingPanel.VirtualizationMode="Recycling"
ScrollViewer.CanContentScroll="True"
ScrollViewer.HorizontalScrollBarVisibility="Disabled"
ScrollViewer.VerticalScrollBarVisibility="Auto">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<!-- Заголовок -->
<StackPanel Grid.Row="0" Margin="0,0,0,20">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<StackPanel Grid.Column="0">
<TextBlock Text="Управление QoS-политиками Windows"
FontSize="18"
FontWeight="SemiBold"
Foreground="White"/>
<TextBlock Text="Создавайте и управляйте QoS-политиками для приоритизации сетевого трафика"
FontSize="12"
Foreground="#CCCCCC"
Margin="0,5,0,0"/>
</StackPanel>
<StackPanel Grid.Column="1"
Orientation="Horizontal"
VerticalAlignment="Top">
<TextBlock Text="Статус: "
FontSize="12"
Foreground="#CCCCCC"
VerticalAlignment="Center"/>
<TextBlock Text="Активно"
FontSize="12"
FontWeight="SemiBold"
Foreground="#4CAF50"
VerticalAlignment="Center"/>
</StackPanel>
</Grid>
</StackPanel>
<!-- DataGrid -->
<DataGrid x:Name="PoliciesDataGrid"
Grid.Row="1"
AutoGenerateColumns="False"
CanUserAddRows="False"
CanUserDeleteRows="False"
CanUserReorderColumns="False"
CanUserResizeColumns="True"
CanUserResizeRows="False"
CanUserSortColumns="True"
GridLinesVisibility="Horizontal"
HorizontalGridLinesBrush="#3C3C3C"
VerticalGridLinesBrush="Transparent"
Background="#1E1E1E"
Foreground="White"
BorderBrush="#3C3C3C"
BorderThickness="1"
HeadersVisibility="Column"
SelectionMode="Single"
AlternatingRowBackground="#252525"
RowHeight="30"
MinRowHeight="25"
VirtualizingPanel.IsVirtualizing="True"
VirtualizingPanel.VirtualizationMode="Recycling"
ScrollViewer.CanContentScroll="True"
ScrollViewer.HorizontalScrollBarVisibility="Disabled"
ScrollViewer.VerticalScrollBarVisibility="Auto">
<DataGrid.ColumnHeaderStyle>
<Style TargetType="DataGridColumnHeader">
@@ -129,7 +130,7 @@
Binding="{Binding Name}"
Width="180"
IsReadOnly="True"/>
<DataGridTextColumn Header="Процесс / путь"
<DataGridTextColumn Header="Процесс"
Binding="{Binding Process}"
Width="*"
IsReadOnly="True"/>
@@ -145,8 +146,23 @@
</DataGrid>
<!-- Настройки -->
<StackPanel x:Name="SettingsPanel"
Grid.Row="2"
Orientation="Horizontal"
HorizontalAlignment="Left"
Margin="0,20,0,10">
<CheckBox x:Name="LoggingCheckBox"
Content="Вести логи"
Width="120"
Height="30"
Foreground="White"
VerticalContentAlignment="Center"/>
</StackPanel>
<!-- Кнопки -->
<StackPanel Grid.Row="2"
<StackPanel Grid.Row="3"
Orientation="Horizontal"
HorizontalAlignment="Right"
Margin="0,20,0,0">
@@ -172,6 +188,7 @@
Margin="0,0,10,0"
Style="{StaticResource DarkButtonStyle}"/>
<Button x:Name="LogButton"
Content="Открыть лог"
Width="100"
+89 -5
View File
@@ -1,9 +1,15 @@
using System;
using System.Collections;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.ComponentModel;
using System.Diagnostics;
using System.Linq;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Data;
using QoSManager.Models;
using QoSManager.Services;
@@ -14,7 +20,8 @@ namespace QoSManager.Views
private readonly QoSService _qosService;
private readonly LoggingService _loggingService;
private readonly ObservableCollection<QoSPolicy> _policies;
private bool _loggingEnabled = true;
private bool _loggingEnabled = false;
private bool _isInitialized = false;
public MainWindow()
{
@@ -41,9 +48,22 @@ namespace QoSManager.Views
// Initialize checkbox state
LoggingCheckBox.IsChecked = _loggingEnabled;
// Hide settings panel initially and show it after UI is fully loaded
SettingsPanel.Visibility = Visibility.Collapsed;
// Don't log startup - let user enable logging manually if needed
LoadPolicies();
// Show settings panel and mark initialization as complete after UI loads
Dispatcher.BeginInvoke(() => {
// Always show checkboxes panel with current settings state
SettingsPanel.Visibility = Visibility.Visible;
_isInitialized = true;
// Auto-refresh QoS policies disabled on startup to prevent unwanted behavior
// User must manually enable auto-refresh if needed
});
}
public ObservableCollection<QoSPolicy> Policies => _policies;
@@ -65,7 +85,7 @@ namespace QoSManager.Views
{
try
{
// Load logging preference from Properties.Settings
// Load preferences from Properties.Settings
_loggingEnabled = Properties.Settings.Default.EnableLogging;
}
catch
@@ -78,7 +98,7 @@ namespace QoSManager.Views
{
try
{
// Save logging preference to Properties.Settings
// Save preferences to Properties.Settings
Properties.Settings.Default.EnableLogging = _loggingEnabled;
Properties.Settings.Default.Save();
}
@@ -215,6 +235,40 @@ namespace QoSManager.Views
LoadPolicies();
}
private void RefreshPoliciesButton_Click(object sender, RoutedEventArgs e)
{
try
{
_loggingService.LogInformation("Force refreshing QoS policies by user request", _loggingEnabled);
// Show progress message
CustomMessageBox.Show(
"Выполняется принудительное перечитывание QoS политик...\n\n" +
"Это может занять несколько секунд.\n" +
"После обновления может потребоваться перезапуск приложений.",
"Перечитывание политик", MessageBoxButton.OK, MessageBoxImage.Information);
// Force refresh QoS policies
_qosService.RefreshQoSPolicies();
// Reload policies list
LoadPolicies();
_loggingService.LogInformation("QoS policies refreshed successfully", _loggingEnabled);
// Show success message
CustomMessageBox.Show(
"QoS политики перечитаны",
"Успешно", MessageBoxButton.OK, MessageBoxImage.Information);
}
catch (Exception ex)
{
_loggingService.LogError($"Error refreshing QoS policies: {ex.Message}", _loggingEnabled);
CustomMessageBox.Show($"Ошибка при перечитывании QoS политик:\n\n{ex.Message}",
"Ошибка", MessageBoxButton.OK, MessageBoxImage.Error);
}
}
private void LogButton_Click(object sender, RoutedEventArgs e)
{
try
@@ -235,23 +289,53 @@ namespace QoSManager.Views
_loggingEnabled = true;
_qosService.SetLoggingEnabled(_loggingEnabled);
((App)Application.Current).SetLoggingEnabled(_loggingEnabled);
_loggingService.LogInformation("Логирование включено", _loggingEnabled);
if (_isInitialized)
{
_loggingService.LogInformation("Логирование включено", true);
}
}
private void LoggingCheckBox_Unchecked(object sender, RoutedEventArgs e)
{
// Log the disable action before actually disabling
_loggingService.LogInformation("Логирование отключено пользователем", _loggingEnabled);
if (_isInitialized && _loggingEnabled)
{
_loggingService.LogInformation("Логирование отключено пользователем", true);
}
_loggingEnabled = false;
_qosService.SetLoggingEnabled(_loggingEnabled);
((App)Application.Current).SetLoggingEnabled(_loggingEnabled);
}
private void ExitButton_Click(object sender, RoutedEventArgs e)
{
Close();
}
private void TitleBar_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
if (e.ChangedButton == MouseButton.Left)
{
DragMove();
}
}
private void MinimizeButton_Click(object sender, RoutedEventArgs e)
{
WindowState = WindowState.Minimized;
}
private void MaximizeButton_Click(object sender, RoutedEventArgs e)
{
WindowState = WindowState == WindowState.Maximized ? WindowState.Normal : WindowState.Maximized;
}
private void CloseButton_Click(object sender, RoutedEventArgs e)
{
Close();
}
protected override void OnClosed(EventArgs e)
{
SaveSettings();
+11 -11
View File
@@ -1,23 +1,23 @@
<Window x:Class="QoSManager.Views.PolicyEditWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Создание QoS-политики"
Title="Создание QoS-политики"
Height="320" Width="500"
WindowStartupLocation="CenterScreen"
Background="#1E1E1E"
ResizeMode="NoResize">
<Grid Margin="20">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="120"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
+15 -1
View File
@@ -1,6 +1,7 @@
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using Microsoft.Win32;
using QoSManager.Models;
using QoSManager.Services;
@@ -134,7 +135,7 @@ namespace QoSManager.Views
if (string.IsNullOrWhiteSpace(ProcessTextBox.Text))
{
CustomMessageBox.Show("Укажите процесс или путь к исполняемому файлу.", "Ошибка", MessageBoxButton.OK, MessageBoxImage.Error);
CustomMessageBox.Show("Укажите имя процесса.", "Ошибка", MessageBoxButton.OK, MessageBoxImage.Error);
ProcessTextBox.Focus();
return false;
}
@@ -184,5 +185,18 @@ namespace QoSManager.Views
DSCP = dscpValue
};
}
private void TitleBar_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
if (e.ChangedButton == MouseButton.Left)
{
DragMove();
}
}
private void CloseButton_Click(object sender, RoutedEventArgs e)
{
Close();
}
}
}
-6
View File
@@ -8,12 +8,6 @@
Background="#2b2b2b"
TextElement.Foreground="White">
<Window.Resources>
<Style TargetType="Window">
<Setter Property="Foreground" Value="White"/>
</Style>
</Window.Resources>
<Grid Margin="10">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
+17 -2
View File
@@ -4,6 +4,7 @@ using System.Diagnostics;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using QoSManager.Models;
namespace QoSManager.Views
@@ -30,7 +31,7 @@ namespace QoSManager.Views
var processInfo = new ProcessInfo
{
Id = process.Id,
Name = process.ProcessName,
Name = (process.ProcessName + ".exe").ToLower(),
Path = process.MainModule?.FileName ?? "Unknown"
};
@@ -57,7 +58,7 @@ namespace QoSManager.Views
{
if (ProcessesDataGrid.SelectedItem is ProcessInfo selectedProcess)
{
SelectedProcess = selectedProcess.Path;
SelectedProcess = selectedProcess.Name;
DialogResult = true;
Close();
}
@@ -68,5 +69,19 @@ namespace QoSManager.Views
DialogResult = false;
Close();
}
private void TitleBar_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
if (e.ChangedButton == MouseButton.Left)
{
DragMove();
}
}
private void CloseButton_Click(object sender, RoutedEventArgs e)
{
DialogResult = false;
Close();
}
}
}
+15
View File
@@ -1,5 +1,6 @@
using System;
using System.Windows;
using System.Windows.Input;
using QoSManager.Services;
namespace QoSManager.Views
@@ -22,5 +23,19 @@ namespace QoSManager.Views
DialogResult = false;
Close();
}
private void TitleBar_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
if (e.ChangedButton == MouseButton.Left)
{
DragMove();
}
}
private void CloseButton_Click(object sender, RoutedEventArgs e)
{
DialogResult = false;
Close();
}
}
}