From 3fc0bc4ec2fb1a4f6a8ceff3349896b5929a6cd2 Mon Sep 17 00:00:00 2001 From: Dencher12 Date: Sun, 23 Nov 2025 15:11:21 +0300 Subject: [PATCH] release --- MicrosocksGUI/App.axaml | 2 + MicrosocksGUI/MicrosocksGUI.csproj | 1 + MicrosocksGUI/Services/IServiceManager.cs | 24 +++ .../Services/WindowsServiceManager.cs | 130 ++++++++++++++ .../ViewModels/MainWindowViewModel.cs | 162 +++--------------- MicrosocksGUI/Views/MainWindow.axaml | 7 +- MicrosocksGUI/Views/MainWindow.axaml.cs | 1 + 7 files changed, 188 insertions(+), 139 deletions(-) create mode 100644 MicrosocksGUI/Services/IServiceManager.cs create mode 100644 MicrosocksGUI/Services/WindowsServiceManager.cs diff --git a/MicrosocksGUI/App.axaml b/MicrosocksGUI/App.axaml index de57a6d..0d3368d 100644 --- a/MicrosocksGUI/App.axaml +++ b/MicrosocksGUI/App.axaml @@ -1,5 +1,6 @@ @@ -11,5 +12,6 @@ + \ No newline at end of file diff --git a/MicrosocksGUI/MicrosocksGUI.csproj b/MicrosocksGUI/MicrosocksGUI.csproj index d49259d..baaea60 100644 --- a/MicrosocksGUI/MicrosocksGUI.csproj +++ b/MicrosocksGUI/MicrosocksGUI.csproj @@ -22,6 +22,7 @@ None All + all diff --git a/MicrosocksGUI/Services/IServiceManager.cs b/MicrosocksGUI/Services/IServiceManager.cs new file mode 100644 index 0000000..75004d5 --- /dev/null +++ b/MicrosocksGUI/Services/IServiceManager.cs @@ -0,0 +1,24 @@ +namespace MicrosocksGUI.Services; + +public interface IServiceManager +{ + public record Arguments(string Ip, string Port); + + public void CreateIfNotExists(); + + public void Start(); + + public void Stop(); + + public void Restart(); + + public bool IsRunning(); + + public bool GetAutostart(); + + public void SetAutostart(bool autostart); + + public Arguments GetArguments(); + + public void SetArguments(Arguments arguments); +} \ No newline at end of file diff --git a/MicrosocksGUI/Services/WindowsServiceManager.cs b/MicrosocksGUI/Services/WindowsServiceManager.cs new file mode 100644 index 0000000..18a6590 --- /dev/null +++ b/MicrosocksGUI/Services/WindowsServiceManager.cs @@ -0,0 +1,130 @@ +using System; +using System.Diagnostics; +using System.IO; +using System.Runtime.InteropServices; +using System.ServiceProcess; + +namespace MicrosocksGUI.Services; + +public class WindowsServiceManager : IServiceManager +{ + private record NssmResult(string Output, string Errors); + private readonly ServiceController _serviceController = new("MicroSocks"); + + public void CreateIfNotExists() + { + if (!RunNssmProcess("status MicroSocks").Errors.Contains("Can't open service!")) + return; + + var result = RunNssmProcess("install MicroSocks microsocks.exe -i 127.0.0.1 -p 1080"); + + if (!string.IsNullOrEmpty(result.Errors)) + { + throw new ExternalException(result.Errors); + } + } + + public void Start() + { + _serviceController.Refresh(); + + if (_serviceController.Status != ServiceControllerStatus.Stopped) + return; + + _serviceController.Start(); + _serviceController.WaitForStatus(ServiceControllerStatus.Running); + } + + public void Stop() + { + _serviceController.Refresh(); + + if (_serviceController.Status != ServiceControllerStatus.Running) + return; + + _serviceController.Stop(); + _serviceController.WaitForStatus(ServiceControllerStatus.Stopped); + } + + public void Restart() + { + Stop(); + Start(); + } + + public bool IsRunning() + { + _serviceController.Refresh(); + return _serviceController.Status == ServiceControllerStatus.Running; + } + + public bool GetAutostart() + { + _serviceController.Refresh(); + return _serviceController.StartType == ServiceStartMode.Automatic; + } + + public void SetAutostart(bool autostart) + { + var param = autostart ? "SERVICE_AUTO_START" : "SERVICE_DEMAND_START"; + var result = RunNssmProcess($"set MicroSocks Start {param}"); + + if (!string.IsNullOrEmpty(result.Errors)) + { + throw new ExternalException(result.Errors); + } + } + + public IServiceManager.Arguments GetArguments() + { + var result = RunNssmProcess("get MicroSocks AppParameters"); + + if (!string.IsNullOrEmpty(result.Errors)) + { + throw new ExternalException(result.Errors); + } + + return ParseArguments(result.Output); + } + + public void SetArguments(IServiceManager.Arguments arguments) + { + var result = RunNssmProcess($"set MicroSocks AppParameters -i {arguments.Ip} -p {arguments.Port}"); + + if (!string.IsNullOrEmpty(result.Errors)) + { + throw new ExternalException(result.Errors); + } + } + + private IServiceManager.Arguments ParseArguments(string arguments) + { + var argumentsList = arguments.Split(); + return new IServiceManager.Arguments(argumentsList[1], argumentsList[3]); + } + + private NssmResult RunNssmProcess(string arguments) + { + using var process = new Process(); + + process.StartInfo = new ProcessStartInfo + { + FileName = ".\\nssm.exe", + Arguments = arguments, + UseShellExecute = false, + RedirectStandardOutput = true, + RedirectStandardError = true, + CreateNoWindow = true, + WorkingDirectory = Path.GetDirectoryName(".") + }; + + process.Start(); + + var output = process.StandardOutput.ReadToEnd().Replace("\0", "").Trim(); + var errors = process.StandardError.ReadToEnd().Replace("\0", "").Trim(); + + process.WaitForExit(); + + return new NssmResult(output, errors); + } +} \ No newline at end of file diff --git a/MicrosocksGUI/ViewModels/MainWindowViewModel.cs b/MicrosocksGUI/ViewModels/MainWindowViewModel.cs index d9e8642..cd11a0e 100644 --- a/MicrosocksGUI/ViewModels/MainWindowViewModel.cs +++ b/MicrosocksGUI/ViewModels/MainWindowViewModel.cs @@ -1,155 +1,60 @@ using System; -using System.Diagnostics; -using System.IO; -using System.Management; -using System.Runtime.Versioning; using System.Threading; -using System.Threading.Tasks; -using ReactiveUI; using ReactiveUI.SourceGenerators; -using System.ServiceProcess; +using MicrosocksGUI.Services; namespace MicrosocksGUI.ViewModels; public partial class MainWindowViewModel : ViewModelBase { - private record Arguments(string Ip, string Port); - - [Reactive] private bool _isWorking; - [Reactive] private bool _isAutoloading; - [Reactive] private string? _ip; - [Reactive] private string? _port; + [Reactive] private bool _isRunning; + [Reactive] private bool _isAutostart; + [Reactive] private string _ip = string.Empty; + [Reactive] private string _port = string.Empty; + + private bool _isUpdateLocked; private Timer _timer; - //private readonly ManagementObject _serviceManager = new("Win32_Service.Name='Microsocks'"); - private readonly ServiceController _sc = new("MicroSocks"); + private readonly IServiceManager _serviceManager = new WindowsServiceManager(); public MainWindowViewModel() { - // TODO Костыль, таймер запускается через секунду, а должен после инициализации ReactiveUI + _serviceManager.CreateIfNotExists(); _timer = new Timer(GetServiceStatus, null, TimeSpan.FromSeconds(1), TimeSpan.FromMilliseconds(100)); - GetMicroSocksArguments(); } + private void GetServiceStatus(object? state) + { + if (_isUpdateLocked) return; + + IsRunning = _serviceManager.IsRunning(); + IsAutostart = _serviceManager.GetAutostart(); + } + [ReactiveCommand] private void SetServiceStatus() { - /*var serviceProps = _serviceManager.GetMethodParameters("Change"); - serviceProps["StartMode"] = IsAutoloading ? "Automatic" : "Manual"; - _serviceManager.InvokeMethod("Change", serviceProps, null);*/ - - SetServiceAutoloading(IsAutoloading); - + _isUpdateLocked = true; - if (IsWorking) + _serviceManager.SetAutostart(IsAutostart); + + if (IsRunning) { - StartService(); + _serviceManager.Start(); } else { - StopService(); + _serviceManager.Stop(); } - - - - //_serviceManager.InvokeMethod(IsWorking ? "StartService" : "StopService", null, null); - } - private void StartService() - { - _sc.Refresh(); - if (_sc.Status != ServiceControllerStatus.Stopped) return; - - _sc.Start(); - _sc.WaitForStatus(ServiceControllerStatus.Running); - //_serviceManager.InvokeMethod("StartService", null, null); - } - - private void StopService() - { - _sc.Refresh(); - if (_sc.Status != ServiceControllerStatus.Running) return; - - _sc.Stop(); - _sc.WaitForStatus(ServiceControllerStatus.Stopped); - //_serviceManager.InvokeMethod("StopService", null, null); + _isUpdateLocked = false; } - private void RestartService() - { - StopService(); - StartService(); - } - - private bool ServiceIsRunning() - { - _sc.Refresh(); - return _sc.Status == ServiceControllerStatus.Running; - } - - private bool ServiceIsAutoloading() - { - _sc.Refresh(); - return _sc.StartType == ServiceStartMode.Automatic; - } - - private void SetServiceAutoloading(bool isAutoloading) - { - using var process = new Process(); - - var param = isAutoloading ? "SERVICE_AUTO_START" : "SERVICE_DEMAND_START"; - process.StartInfo = new ProcessStartInfo - { - FileName = ".\\nssm.exe", - Arguments = $"set MicroSocks Start {param}", - UseShellExecute = false, - RedirectStandardOutput = true, - RedirectStandardError = true, - CreateNoWindow = true, - WorkingDirectory = Path.GetDirectoryName(".") - }; - process.Start(); - process.WaitForExit(); - } - - private void GetServiceStatus(object? state) - { - //_sc.Refresh(); - //_serviceManager.Get(); - IsWorking = ServiceIsRunning(); - IsAutoloading = ServiceIsAutoloading(); - - //IsWorking = _serviceManager["State"]?.ToString() == "Running"; - //IsAutoloading = _serviceManager["StartMode"]?.ToString() == "Auto"; - } - - Arguments ParseArguments(string arguments) - { - var argumentsList = arguments.Replace("\0", "").Trim().Split(); - return new Arguments(argumentsList[1], argumentsList[3]); - } - [ReactiveCommand] private void GetMicroSocksArguments() { - using var process = new Process(); - process.StartInfo = new ProcessStartInfo - { - FileName = ".\\nssm.exe", - Arguments = "get MicroSocks AppParameters", - UseShellExecute = false, - RedirectStandardOutput = true, - RedirectStandardError = true, - CreateNoWindow = true, - WorkingDirectory = Path.GetDirectoryName(".") - }; - - process.Start(); - var output = process.StandardOutput.ReadToEnd(); - process.WaitForExit(); - - var arguments = ParseArguments(output); + var arguments = _serviceManager.GetArguments(); Ip = arguments.Ip; Port = arguments.Port; } @@ -157,20 +62,7 @@ public partial class MainWindowViewModel : ViewModelBase [ReactiveCommand] private void SetMicroSocksArguments() { - using var process = new Process(); - process.StartInfo = new ProcessStartInfo - { - FileName = ".\\nssm.exe", - Arguments = $"set MicroSocks AppParameters -i {_ip} -p {_port}", - UseShellExecute = false, - RedirectStandardOutput = true, - RedirectStandardError = true, - CreateNoWindow = true, - WorkingDirectory = Path.GetDirectoryName(".") - }; - process.Start(); - process.WaitForExit(); - - RestartService(); + _serviceManager.SetArguments(new IServiceManager.Arguments(Ip, Port)); + _serviceManager.Restart(); } } \ No newline at end of file diff --git a/MicrosocksGUI/Views/MainWindow.axaml b/MicrosocksGUI/Views/MainWindow.axaml index 1deef4a..81f5816 100644 --- a/MicrosocksGUI/Views/MainWindow.axaml +++ b/MicrosocksGUI/Views/MainWindow.axaml @@ -11,8 +11,7 @@ CanMaximize="False" CanResize="False" Width="250" - Height="330" - > + Height="330">