From a9fa99cf53ff47aa446ca04ce93594f488edd4ec Mon Sep 17 00:00:00 2001 From: "kirill.labutin" Date: Sat, 7 Feb 2026 23:23:15 +0300 Subject: [PATCH] initial commit --- .gitignore | 3 + EthernetSwitcher.sln | 16 ++ EthernetSwitcher.sln.DotSettings.user | 3 + EthernetSwitcher/App.config | 6 + EthernetSwitcher/CurrentSettings.cs | 107 +++++++ EthernetSwitcher/EthernetSwitcher.csproj | 94 +++++++ EthernetSwitcher/EthernetSwitcherService.cs | 264 ++++++++++++++++++ EthernetSwitcher/Form1.Designer.cs | 193 +++++++++++++ EthernetSwitcher/Form1.cs | 249 +++++++++++++++++ EthernetSwitcher/NetworkManager.cs | 196 +++++++++++++ EthernetSwitcher/Program.cs | 24 ++ EthernetSwitcher/Properties/AssemblyInfo.cs | 36 +++ .../Properties/Resources.Designer.cs | 64 +++++ EthernetSwitcher/Properties/Resources.resx | 117 ++++++++ .../Properties/Settings.Designer.cs | 24 ++ EthernetSwitcher/Properties/Settings.settings | 7 + EthernetSwitcher/Settings.cs | 94 +++++++ EthernetSwitcher/app.manifest | 35 +++ EthernetSwitcher/icon.ico | Bin 0 -> 21646 bytes EthernetSwitcher/icon_green.ico | Bin 0 -> 1150 bytes EthernetSwitcher/icon_red.ico | Bin 0 -> 1150 bytes EthernetSwitcher/icon_yellow.ico | Bin 0 -> 1150 bytes EthernetSwitcher/log.txt | 10 + 23 files changed, 1542 insertions(+) create mode 100644 .gitignore create mode 100644 EthernetSwitcher.sln create mode 100644 EthernetSwitcher.sln.DotSettings.user create mode 100644 EthernetSwitcher/App.config create mode 100644 EthernetSwitcher/CurrentSettings.cs create mode 100644 EthernetSwitcher/EthernetSwitcher.csproj create mode 100644 EthernetSwitcher/EthernetSwitcherService.cs create mode 100644 EthernetSwitcher/Form1.Designer.cs create mode 100644 EthernetSwitcher/Form1.cs create mode 100644 EthernetSwitcher/NetworkManager.cs create mode 100644 EthernetSwitcher/Program.cs create mode 100644 EthernetSwitcher/Properties/AssemblyInfo.cs create mode 100644 EthernetSwitcher/Properties/Resources.Designer.cs create mode 100644 EthernetSwitcher/Properties/Resources.resx create mode 100644 EthernetSwitcher/Properties/Settings.Designer.cs create mode 100644 EthernetSwitcher/Properties/Settings.settings create mode 100644 EthernetSwitcher/Settings.cs create mode 100644 EthernetSwitcher/app.manifest create mode 100644 EthernetSwitcher/icon.ico create mode 100644 EthernetSwitcher/icon_green.ico create mode 100644 EthernetSwitcher/icon_red.ico create mode 100644 EthernetSwitcher/icon_yellow.ico create mode 100644 EthernetSwitcher/log.txt diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..5eaf580 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +.idea +EthernetSwitcher/bin +EthernetSwitcher/obj diff --git a/EthernetSwitcher.sln b/EthernetSwitcher.sln new file mode 100644 index 0000000..e0f1534 --- /dev/null +++ b/EthernetSwitcher.sln @@ -0,0 +1,16 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EthernetSwitcher", "EthernetSwitcher\EthernetSwitcher.csproj", "{0463CEC3-E6DB-4698-BA12-6166940A143A}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {0463CEC3-E6DB-4698-BA12-6166940A143A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {0463CEC3-E6DB-4698-BA12-6166940A143A}.Debug|Any CPU.Build.0 = Debug|Any CPU + {0463CEC3-E6DB-4698-BA12-6166940A143A}.Release|Any CPU.ActiveCfg = Release|Any CPU + {0463CEC3-E6DB-4698-BA12-6166940A143A}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection +EndGlobal diff --git a/EthernetSwitcher.sln.DotSettings.user b/EthernetSwitcher.sln.DotSettings.user new file mode 100644 index 0000000..83a3131 --- /dev/null +++ b/EthernetSwitcher.sln.DotSettings.user @@ -0,0 +1,3 @@ + + True + True \ No newline at end of file diff --git a/EthernetSwitcher/App.config b/EthernetSwitcher/App.config new file mode 100644 index 0000000..2d7731d --- /dev/null +++ b/EthernetSwitcher/App.config @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/EthernetSwitcher/CurrentSettings.cs b/EthernetSwitcher/CurrentSettings.cs new file mode 100644 index 0000000..3c4ff3c --- /dev/null +++ b/EthernetSwitcher/CurrentSettings.cs @@ -0,0 +1,107 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Net.NetworkInformation; +using System.Diagnostics; + +namespace EthernetSwitcher +{ + public static class CurrentSettings + { + private static Settings _settings; + + public static Settings Instance + { + get { return _settings ?? (_settings = Settings.Load()); } + } + + public static void Save() + { + Instance.Save(); + } + + public static void Reload() + { + _settings = Settings.Load(); + } + + public static List GetNetworkInterfaces() + { + try + { + // Use PowerShell to get consistent interface names + var output = ExecutePowerShell("Get-NetAdapter | Select-Object Name, Status | ForEach-Object { $_.Name + ' (' + $_.Status + ')' }"); + + if (string.IsNullOrEmpty(output)) + { + // Fallback to NetworkInterface + return NetworkInterface.GetAllNetworkInterfaces() + .Select(ni => $"{ni.Name} ({ni.OperationalStatus})") + .OrderBy(name => name) + .ToList(); + } + + var interfaces = output.Split(new[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries) + .Where(line => !string.IsNullOrWhiteSpace(line.Trim())) + .Select(line => line.Trim()) + .OrderBy(name => name) + .ToList(); + + return interfaces; + } + catch (Exception) + { + return new List(); + } + } + + private static string ExecutePowerShell(string command) + { + try + { + var process = new Process + { + StartInfo = new ProcessStartInfo + { + FileName = "powershell.exe", + Arguments = $"-NoProfile -ExecutionPolicy Bypass -Command \"& {{{command}}}\"", + UseShellExecute = false, + RedirectStandardOutput = true, + RedirectStandardError = true, + CreateNoWindow = true + } + }; + + process.Start(); + var output = process.StandardOutput.ReadToEnd(); + var error = process.StandardError.ReadToEnd(); + process.WaitForExit(); + + if (process.ExitCode != 0 && !string.IsNullOrEmpty(error)) + { + Console.WriteLine($"PowerShell error in GetNetworkInterfaces: {error}"); + } + + return output; + } + catch (Exception ex) + { + Console.WriteLine($"Error executing PowerShell in GetNetworkInterfaces: {ex.Message}"); + return ""; + } + } + + public static string GetCleanInterfaceName(string displayName) + { + if (string.IsNullOrEmpty(displayName)) + return ""; + + var lastSpaceIndex = displayName.LastIndexOf(" ("); + if (lastSpaceIndex > 0) + { + return displayName.Substring(0, lastSpaceIndex); + } + return displayName; + } + } +} \ No newline at end of file diff --git a/EthernetSwitcher/EthernetSwitcher.csproj b/EthernetSwitcher/EthernetSwitcher.csproj new file mode 100644 index 0000000..d16872c --- /dev/null +++ b/EthernetSwitcher/EthernetSwitcher.csproj @@ -0,0 +1,94 @@ + + + + + Debug + AnyCPU + {0463CEC3-E6DB-4698-BA12-6166940A143A} + WinExe + EthernetSwitcher + EthernetSwitcher + v4.0 + 512 + true + true + + + AnyCPU + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + AnyCPU + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + + + + + + + + + + + + + + + Form + + + Form1.cs + + + + + + + + + ResXFileCodeGenerator + Resources.Designer.cs + Designer + + + True + Resources.resx + + + SettingsSingleFileGenerator + Settings.Designer.cs + + + True + Settings.settings + True + + + + + + + + + + + + + app.manifest + + + \ No newline at end of file diff --git a/EthernetSwitcher/EthernetSwitcherService.cs b/EthernetSwitcher/EthernetSwitcherService.cs new file mode 100644 index 0000000..689005d --- /dev/null +++ b/EthernetSwitcher/EthernetSwitcherService.cs @@ -0,0 +1,264 @@ +using System; +using System.Threading; +using System.Drawing; +using System.Windows.Forms; + +namespace EthernetSwitcher +{ + public class EthernetSwitcherService + { + private Thread _workerThread; + private bool _isRunning; + private NotifyIcon _trayIcon; + private string _lastSelectedInterface = ""; + + public void Start(NotifyIcon trayIcon) + { + _trayIcon = trayIcon; + _isRunning = true; + _workerThread = new Thread(WorkerLoop); + _workerThread.IsBackground = true; + _workerThread.Start(); + } + + public void Stop() + { + _isRunning = false; + if (_workerThread != null && _workerThread.IsAlive) + { + _workerThread.Join(1000); // Wait up to 1 second for thread to finish + } + } + + public void UpdateMode(EthernetMode newMode) + { + // Force immediate execution of the new mode + var settings = CurrentSettings.Instance; + + switch (newMode) + { + case EthernetMode.Primary: + SelectInterface(settings.PrimaryName); + UpdateIconFromResource("icon_yellow.ico"); + break; + + case EthernetMode.Secondary: + SelectInterface(settings.SecondaryName); + UpdateIconFromResource("icon_yellow.ico"); + break; + + case EthernetMode.Auto: + HandleAutoMode(settings); + break; + + case EthernetMode.Disabled: + UpdateIconFromResource("icon_yellow.ico"); + _lastSelectedInterface = "Нет активного интерфейса"; + break; + } + + UpdateTrayTooltip(newMode, _lastSelectedInterface); + } + + private void WorkerLoop() + { + while (_isRunning) + { + try + { + var settings = CurrentSettings.Instance; + + switch (settings.Mode) + { + case EthernetMode.Primary: + SelectInterface(settings.PrimaryName); + UpdateIconFromResource("icon_yellow.ico"); + break; + + case EthernetMode.Secondary: + SelectInterface(settings.SecondaryName); + UpdateIconFromResource("icon_yellow.ico"); + break; + + case EthernetMode.Auto: + HandleAutoMode(settings); + break; + + case EthernetMode.Disabled: + // Do nothing + UpdateIconFromResource("icon_yellow.ico"); + _lastSelectedInterface = "Нет активного интерфейса"; + break; + } + + // Update tray tooltip after all operations + UpdateTrayTooltip(settings.Mode, _lastSelectedInterface); + + // Wait for the specified interval + Thread.Sleep(settings.CheckInterval * 1000); + } + catch (Exception ex) + { + Thread.Sleep(5000); // Wait 5 seconds on error before retrying + } + } + } + + private void UpdateIconFromResource(string resourceName) + { + try + { + var icon = new Icon(System.Reflection.Assembly.GetExecutingAssembly().GetManifestResourceStream($"EthernetSwitcher.{resourceName}")); + if (_trayIcon.Icon?.Handle != icon.Handle) + { + _trayIcon.Icon = icon; + } + } + catch (Exception ex) + { + // Fallback to default icon + var defaultIcon = Icon.FromHandle(System.Drawing.SystemIcons.WinLogo.Handle); + if (_trayIcon.Icon?.Handle != defaultIcon.Handle) + { + _trayIcon.Icon = defaultIcon; + } + } + } + + private void HandleAutoMode(Settings settings) + { + bool primaryLinkExists = CheckInterfaceLink(settings.PrimaryName); + + // Update tray icon based on link status + if (primaryLinkExists) + { + UpdateIconFromResource("icon_green.ico"); + } + else + { + UpdateIconFromResource("icon_red.ico"); + } + + if (primaryLinkExists) + { + SelectInterface(settings.PrimaryName); + DeselectInterface(settings.SecondaryName); + } + else + { + SelectInterface(settings.SecondaryName); + DeselectInterface(settings.PrimaryName); + } + } + + private bool CheckInterfaceLink(string interfaceName) + { + try + { + return NetworkManager.GetInterfaceStatus(interfaceName); + } + catch (Exception ex) + { + return false; + } + } + + private void DeselectInterface(string interfaceName) + { + if (string.IsNullOrEmpty(interfaceName)) + return; + + try + { + var settings = CurrentSettings.Instance; + + if (!NetworkManager.InterfaceExists(interfaceName)) + { + _lastSelectedInterface = $"Интерфейс не найден: {interfaceName}"; + UpdateIconFromResource("icon_red.ico"); + return; + } + + switch (settings.Protocol) + { + case IpProtocol.IPv4: + NetworkManager.SetIPv4Status(interfaceName, false); + break; + case IpProtocol.IPv6: + NetworkManager.SetIPv6Status(interfaceName, false); + break; + case IpProtocol.IPv4_IPv6: + NetworkManager.SetIPv4Status(interfaceName, false); + NetworkManager.SetIPv6Status(interfaceName, false); + break; + } + } + catch (Exception ex) + { + // Error handling without logging + } + } + + private void SelectInterface(string interfaceName) + { + if (string.IsNullOrEmpty(interfaceName)) + return; + + try + { + var settings = CurrentSettings.Instance; + + if (!NetworkManager.InterfaceExists(interfaceName)) + { + _lastSelectedInterface = $"Интерфейс не найден: {interfaceName}"; + UpdateIconFromResource("icon_red.ico"); + return; + } + + switch (settings.Protocol) + { + case IpProtocol.IPv4: + NetworkManager.SetIPv4Status(interfaceName, true); + break; + case IpProtocol.IPv6: + NetworkManager.SetIPv6Status(interfaceName, true); + break; + case IpProtocol.IPv4_IPv6: + NetworkManager.SetIPv4Status(interfaceName, true); + NetworkManager.SetIPv6Status(interfaceName, true); + break; + } + + _lastSelectedInterface = interfaceName; + } + catch (Exception ex) + { + // Error handling without logging + } + } + + private void UpdateTrayTooltip(EthernetMode mode, string interfaceName) + { + try + { + var tooltip = $"Режим: {mode}"; + + if (!string.IsNullOrEmpty(interfaceName)) + { + // Shorten interface name to fit in tooltip (Windows 64 char limit) + var shortInterfaceName = interfaceName.Length > 25 ? interfaceName.Substring(0, 22) + "..." : interfaceName; + tooltip += $"\nИнтерфейс: {shortInterfaceName}"; + } + + if (_trayIcon.Text != tooltip) + { + _trayIcon.Text = tooltip; + } + } + catch (Exception ex) + { + // Error handling without logging + } + } + } +} \ No newline at end of file diff --git a/EthernetSwitcher/Form1.Designer.cs b/EthernetSwitcher/Form1.Designer.cs new file mode 100644 index 0000000..3641a72 --- /dev/null +++ b/EthernetSwitcher/Form1.Designer.cs @@ -0,0 +1,193 @@ +using System.Drawing; +using System.Windows.Forms; +using System.Reflection; + +namespace EthernetSwitcher +{ + partial class Form1 + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.label1 = new System.Windows.Forms.Label(); + this.label2 = new System.Windows.Forms.Label(); + this.label3 = new System.Windows.Forms.Label(); + this.label4 = new System.Windows.Forms.Label(); + this.label5 = new System.Windows.Forms.Label(); + this.comboBoxMode = new System.Windows.Forms.ComboBox(); + this.comboBoxProtocol = new System.Windows.Forms.ComboBox(); + this.comboBoxPrimary = new System.Windows.Forms.ComboBox(); + this.comboBoxSecondary = new System.Windows.Forms.ComboBox(); + this.trackBarInterval = new System.Windows.Forms.TrackBar(); + this.SuspendLayout(); + // + // label1 + // + this.label1.AutoSize = true; + this.label1.Location = new System.Drawing.Point(20, 20); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(99, 13); + this.label1.TabIndex = 0; + this.label1.Text = "Режим работы:"; + // + // label2 + // + this.label2.AutoSize = true; + this.label2.Location = new System.Drawing.Point(20, 60); + this.label2.Name = "label2"; + this.label2.Size = new System.Drawing.Size(82, 13); + this.label2.TabIndex = 1; + this.label2.Text = "Основной интерфейс:"; + // + // label3 + // + this.label3.AutoSize = true; + this.label3.Location = new System.Drawing.Point(20, 100); + this.label3.Name = "label3"; + this.label3.Size = new System.Drawing.Size(103, 13); + this.label3.TabIndex = 2; + this.label3.Text = "Резервный интерфейс:"; + // + // label5 + // + this.label5.AutoSize = true; + this.label5.Location = new System.Drawing.Point(20, 145); + this.label5.Name = "label5"; + this.label5.Size = new System.Drawing.Size(78, 13); + this.label5.TabIndex = 4; + this.label5.Text = "IP протокол:"; + // + // label4 + // + this.label4.AutoSize = true; + this.label4.Location = new System.Drawing.Point(20, 185); + this.label4.Name = "label4"; + this.label4.Size = new System.Drawing.Size(126, 13); + this.label4.TabIndex = 3; + this.label4.Text = "Интервал проверки: 5 сек"; + // + // comboBoxMode + // + this.comboBoxMode.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + this.comboBoxMode.FormattingEnabled = true; + this.comboBoxMode.Items.AddRange(new object[] { + "Auto", + "Primary", + "Secondary", + "Disabled"}); + this.comboBoxMode.Location = new System.Drawing.Point(150, 17); + this.comboBoxMode.Name = "comboBoxMode"; + this.comboBoxMode.Size = new System.Drawing.Size(200, 21); + this.comboBoxMode.TabIndex = 4; + // + // comboBoxPrimary + // + this.comboBoxPrimary.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + this.comboBoxPrimary.FormattingEnabled = true; + this.comboBoxPrimary.Location = new System.Drawing.Point(150, 57); + this.comboBoxPrimary.Name = "comboBoxPrimary"; + this.comboBoxPrimary.Size = new System.Drawing.Size(200, 21); + this.comboBoxPrimary.TabIndex = 5; + // + // comboBoxSecondary + // + this.comboBoxSecondary.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + this.comboBoxSecondary.FormattingEnabled = true; + this.comboBoxSecondary.Location = new System.Drawing.Point(150, 97); + this.comboBoxSecondary.Name = "comboBoxSecondary"; + this.comboBoxSecondary.Size = new System.Drawing.Size(200, 21); + this.comboBoxSecondary.TabIndex = 6; + // + // comboBoxProtocol + // + this.comboBoxProtocol.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + this.comboBoxProtocol.FormattingEnabled = true; + this.comboBoxProtocol.Items.AddRange(new object[] { + "IPv4", + "IPv6", + "IPv4 + IPv6"}); + this.comboBoxProtocol.Location = new System.Drawing.Point(150, 142); + this.comboBoxProtocol.Name = "comboBoxProtocol"; + this.comboBoxProtocol.Size = new System.Drawing.Size(200, 21); + this.comboBoxProtocol.TabIndex = 8; + // + // trackBarInterval + // + this.trackBarInterval.AutoSize = false; + this.trackBarInterval.LargeChange = 5; + this.trackBarInterval.Location = new System.Drawing.Point(150, 180); + this.trackBarInterval.Maximum = 30; + this.trackBarInterval.Minimum = 1; + this.trackBarInterval.Name = "trackBarInterval"; + this.trackBarInterval.Size = new System.Drawing.Size(200, 45); + this.trackBarInterval.SmallChange = 1; + this.trackBarInterval.TabIndex = 7; + this.trackBarInterval.TickFrequency = 1; + this.trackBarInterval.Value = 5; + this.trackBarInterval.ValueChanged += new System.EventHandler(this.TrackBarInterval_ValueChanged); + // + // Form1 + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(400, 270); + this.Controls.Add(this.comboBoxProtocol); + this.Controls.Add(this.trackBarInterval); + this.Controls.Add(this.comboBoxSecondary); + this.Controls.Add(this.comboBoxPrimary); + this.Controls.Add(this.comboBoxMode); + this.Controls.Add(this.label4); + this.Controls.Add(this.label3); + this.Controls.Add(this.label2); + this.Controls.Add(this.label5); + this.Controls.Add(this.label1); + this.Text = "Ethernet Switcher Settings"; + this.WindowState = System.Windows.Forms.FormWindowState.Minimized; + this.ShowInTaskbar = false; + this.Icon = new Icon(Assembly.GetExecutingAssembly().GetManifestResourceStream("EthernetSwitcher.icon.ico")); + this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle; + this.MaximizeBox = false; + this.MinimizeBox = false; + this.ResumeLayout(false); + this.PerformLayout(); + } + + #endregion + + private System.Windows.Forms.Label label1; + private System.Windows.Forms.Label label2; + private System.Windows.Forms.Label label3; + private System.Windows.Forms.Label label4; + private System.Windows.Forms.ComboBox comboBoxMode; + private System.Windows.Forms.ComboBox comboBoxPrimary; + private System.Windows.Forms.ComboBox comboBoxSecondary; + private System.Windows.Forms.TrackBar trackBarInterval; + private System.Windows.Forms.Label label5; + private System.Windows.Forms.ComboBox comboBoxProtocol; + private NotifyIcon trayIcon; + } +} \ No newline at end of file diff --git a/EthernetSwitcher/Form1.cs b/EthernetSwitcher/Form1.cs new file mode 100644 index 0000000..43eb6dd --- /dev/null +++ b/EthernetSwitcher/Form1.cs @@ -0,0 +1,249 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Forms; +using System.Reflection; + +namespace EthernetSwitcher +{ + public partial class Form1 : Form + { + private static EthernetSwitcherService _service; + + public Form1() + { + InitializeComponent(); + InitializeTrayIcon(); + LoadNetworkInterfaces(); + LoadSettings(); + + // Start the background service + _service = new EthernetSwitcherService(); + _service.Start(trayIcon); + } + + private void InitializeTrayIcon() + { + var contextMenu = new ContextMenuStrip(); + + // Add Mode submenu + var modeMenuItem = new ToolStripMenuItem("Режим"); + foreach (EthernetMode mode in Enum.GetValues(typeof(EthernetMode))) + { + var modeItem = new ToolStripMenuItem(GetModeDisplayName(mode)); + modeItem.Tag = mode; + modeItem.Click += (sender, e) => SetModeFromTray((EthernetMode)((ToolStripMenuItem)sender).Tag); + modeMenuItem.DropDownItems.Add(modeItem); + } + contextMenu.Items.Add(modeMenuItem); + + contextMenu.Items.Add("Настройки", null, ShowSettings); + contextMenu.Items.Add("Выход", null, ExitApplication); + + var networkIcon = new Icon(Assembly.GetExecutingAssembly().GetManifestResourceStream("EthernetSwitcher.icon.ico")); + + trayIcon = new NotifyIcon() + { + Icon = networkIcon, + Text = "Ethernet Switcher", + Visible = true, + ContextMenuStrip = contextMenu + }; + + trayIcon.Click += TrayIcon_Click; + + UpdateModeMenuCheck(); + } + + private void ShowSettings(object sender, EventArgs e) + { + this.Show(); + this.WindowState = FormWindowState.Normal; + this.BringToFront(); + } + + private void ExitApplication(object sender, EventArgs e) + { + trayIcon.Visible = false; + Application.Exit(); + } + + private void SetModeFromTray(EthernetMode mode) + { + var settings = CurrentSettings.Instance; + settings.Mode = mode; + CurrentSettings.Save(); + + // Update the service if needed + _service?.UpdateMode(mode); + + // Update menu check marks + UpdateModeMenuCheck(); + } + + private string GetModeDisplayName(EthernetMode mode) + { + switch (mode) + { + case EthernetMode.Auto: + return "Авто"; + case EthernetMode.Primary: + return "Основной"; + case EthernetMode.Secondary: + return "Резервный"; + case EthernetMode.Disabled: + return "Отключен"; + default: + return mode.ToString(); + } + } + + private void UpdateModeMenuCheck() + { + if (trayIcon?.ContextMenuStrip == null) return; + + var currentMode = CurrentSettings.Instance.Mode; + var modeMenuItem = trayIcon.ContextMenuStrip.Items[0] as ToolStripMenuItem; + if (modeMenuItem?.DropDownItems != null) + { + foreach (ToolStripMenuItem item in modeMenuItem.DropDownItems) + { + item.Checked = ((EthernetMode)item.Tag) == currentMode; + } + } + } + + private void LoadNetworkInterfaces() + { + var interfaces = CurrentSettings.GetNetworkInterfaces(); + + comboBoxPrimary.Items.Clear(); + comboBoxSecondary.Items.Clear(); + + comboBoxPrimary.Items.AddRange(interfaces.ToArray()); + comboBoxSecondary.Items.AddRange(interfaces.ToArray()); + + if (interfaces.Count > 0) + { + comboBoxPrimary.SelectedIndex = 0; + comboBoxSecondary.SelectedIndex = Math.Min(1, interfaces.Count - 1); + } + } + + private void LoadSettings() + { + var settings = CurrentSettings.Instance; + + comboBoxMode.SelectedItem = settings.Mode.ToString(); + + // Find the display names that match the saved clean names + var primaryDisplay = FindInterfaceDisplay(settings.PrimaryName); + var secondaryDisplay = FindInterfaceDisplay(settings.SecondaryName); + + comboBoxPrimary.SelectedItem = primaryDisplay; + comboBoxSecondary.SelectedItem = secondaryDisplay; + comboBoxProtocol.SelectedItem = settings.Protocol.ToString().Replace("_", " + "); + trackBarInterval.Value = settings.CheckInterval; + + // Update tray menu check marks + UpdateModeMenuCheck(); + } + + private string FindInterfaceDisplay(string cleanName) + { + foreach (var item in comboBoxPrimary.Items) + { + if (item.ToString().StartsWith(cleanName + " (")) + { + return item.ToString(); + } + } + return cleanName; // Fallback if not found + } + + private void SaveSettings() + { + var settings = CurrentSettings.Instance; + + EthernetMode parsedMode; + if (Enum.TryParse(comboBoxMode.SelectedItem?.ToString(), out parsedMode)) + { + settings.Mode = parsedMode; + } + + settings.PrimaryName = CurrentSettings.GetCleanInterfaceName(comboBoxPrimary.SelectedItem?.ToString() ?? ""); + settings.SecondaryName = CurrentSettings.GetCleanInterfaceName(comboBoxSecondary.SelectedItem?.ToString() ?? ""); + + var protocolString = comboBoxProtocol.SelectedItem?.ToString().Replace(" + ", "_") ?? "IPv4_IPv6"; + IpProtocol parsedProtocol; + if (Enum.TryParse(protocolString, out parsedProtocol)) + { + settings.Protocol = parsedProtocol; + } + + settings.CheckInterval = trackBarInterval.Value; + + CurrentSettings.Save(); + } + + private void TrackBarInterval_ValueChanged(object sender, EventArgs e) + { + label4.Text = $"Интервал проверки: {trackBarInterval.Value} сек"; + } + + protected override void OnVisibleChanged(EventArgs e) + { + base.OnVisibleChanged(e); + + if (this.Visible) + { + LoadNetworkInterfaces(); + LoadSettings(); + } + } + + private void TrayIcon_Click(object sender, EventArgs e) + { + var mouseEvent = e as MouseEventArgs; + if (mouseEvent != null && mouseEvent.Button == MouseButtons.Left) + { + this.Show(); + this.WindowState = FormWindowState.Normal; + this.BringToFront(); + } + } + + protected override void OnResize(EventArgs e) + { + base.OnResize(e); + + if (WindowState == FormWindowState.Minimized) + { + this.Hide(); + } + } + + protected override void OnFormClosing(FormClosingEventArgs e) + { + if (e.CloseReason == CloseReason.UserClosing) + { + SaveSettings(); + e.Cancel = true; + this.Hide(); + } + base.OnFormClosing(e); + } + + protected override void OnFormClosed(FormClosedEventArgs e) + { + _service?.Stop(); + trayIcon?.Dispose(); + base.OnFormClosed(e); + } + } +} \ No newline at end of file diff --git a/EthernetSwitcher/NetworkManager.cs b/EthernetSwitcher/NetworkManager.cs new file mode 100644 index 0000000..5b13e28 --- /dev/null +++ b/EthernetSwitcher/NetworkManager.cs @@ -0,0 +1,196 @@ +using System; +using System.Diagnostics; +using System.Linq; + +namespace EthernetSwitcher +{ + public static class NetworkManager + { + public static bool InterfaceExists(string interfaceName) + { + try + { + var escapedName = EscapePowerShellString(interfaceName); + var output = ExecutePowerShell($"Get-NetAdapter -Name '{escapedName}' -ErrorAction SilentlyContinue"); + return !string.IsNullOrEmpty(output) && !output.Contains("Get-NetAdapter") && output.Contains("Name"); + } + catch (Exception ex) + { + return false; + } + } + + public static void EnableInterface(string interfaceName) + { + try + { + var status = GetInterfaceStatus(interfaceName); + if (!status) + { + var escapedName = EscapePowerShellString(interfaceName); + ExecutePowerShell($"Enable-NetAdapter -Name '{escapedName}' -Confirm:$false"); + Console.WriteLine($"Interface enabled: {interfaceName}"); + } + else + { + Console.WriteLine($"Interface already enabled: {interfaceName}"); + } + } + catch (Exception ex) + { + Console.WriteLine($"Error enabling interface {interfaceName}: {ex.Message}"); + } + } + + public static void SetIPv4Status(string interfaceName, bool status) + { + try + { + var isCurrentlyEnabled = IsIPv4Enabled(interfaceName); + if (isCurrentlyEnabled == status) + { + return; + } + + var escapedName = EscapePowerShellString(interfaceName); + var command = status + ? $"Enable-NetAdapterBinding -Name '{escapedName}' -ComponentID ms_tcpip -Confirm:$false" + : $"Disable-NetAdapterBinding -Name '{escapedName}' -ComponentID ms_tcpip -Confirm:$false"; + + ExecutePowerShell(command); + Console.WriteLine($"IPv4 {(status ? "enabled" : "disabled")} for interface: {interfaceName}"); + } + catch (Exception ex) + { + // Error handling without logging + } + } + + public static void SetIPv6Status(string interfaceName, bool status) + { + try + { + var isCurrentlyEnabled = IsIPv6Enabled(interfaceName); + if (isCurrentlyEnabled == status) + { + return; + } + + var escapedName = EscapePowerShellString(interfaceName); + var command = status + ? $"Enable-NetAdapterBinding -Name '{escapedName}' -ComponentID ms_tcpip6 -Confirm:$false" + : $"Disable-NetAdapterBinding -Name '{escapedName}' -ComponentID ms_tcpip6 -Confirm:$false"; + + ExecutePowerShell(command); + Console.WriteLine($"IPv6 {(status ? "enabled" : "disabled")} for interface: {interfaceName}"); + } + catch (Exception ex) + { + // Error handling without logging + } + } + + public static bool IsIPv4Enabled(string interfaceName) + { + try + { + var escapedName = EscapePowerShellString(interfaceName); + var command = $"Get-NetAdapterBinding -Name '{escapedName}' -ComponentID ms_tcpip -ErrorAction SilentlyContinue"; + var output = ExecutePowerShell(command); + + var lines = output.Split(new[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries); + foreach (var line in lines) + { + if (line.Contains("ms_tcpip")) + { + return line.Contains("True"); + } + } + return false; + } + catch (Exception ex) + { + return false; + } + } + + public static bool IsIPv6Enabled(string interfaceName) + { + try + { + var escapedName = EscapePowerShellString(interfaceName); + var command = $"Get-NetAdapterBinding -Name '{escapedName}' -ComponentID ms_tcpip6 -ErrorAction SilentlyContinue"; + var output = ExecutePowerShell(command); + + var lines = output.Split(new[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries); + foreach (var line in lines) + { + if (line.Contains("ms_tcpip6")) + { + return line.Contains("True"); + } + } + return false; + } + catch (Exception ex) + { + return false; + } + } + + public static bool GetInterfaceStatus(string interfaceName) + { + try + { + var escapedName = EscapePowerShellString(interfaceName); + var output = ExecutePowerShell($"Get-NetAdapter -Name '{escapedName}' | Select-Object -ExpandProperty Status -ErrorAction SilentlyContinue"); + return output.Trim() == "Up"; + } + catch (Exception ex) + { + return false; + } + } + + public static string EscapePowerShellString(string input) + { + return input.Replace("'", "''"); + } + + private static string ExecutePowerShell(string command) + { + try + { + var process = new Process + { + StartInfo = new ProcessStartInfo + { + FileName = "powershell.exe", + Arguments = $"-NoProfile -ExecutionPolicy Bypass -Command \"& {{{command}}}\"", + UseShellExecute = false, + RedirectStandardOutput = true, + RedirectStandardError = true, + CreateNoWindow = true, + Verb = "runas" + } + }; + + process.Start(); + var output = process.StandardOutput.ReadToEnd(); + var error = process.StandardError.ReadToEnd(); + process.WaitForExit(); + + if (process.ExitCode != 0 && !string.IsNullOrEmpty(error)) + { + throw new Exception($"PowerShell command failed: {error}"); + } + + return output; + } + catch (Exception ex) + { + throw new Exception($"Error executing PowerShell command '{command}': {ex.Message}"); + } + } + } +} \ No newline at end of file diff --git a/EthernetSwitcher/Program.cs b/EthernetSwitcher/Program.cs new file mode 100644 index 0000000..050a05a --- /dev/null +++ b/EthernetSwitcher/Program.cs @@ -0,0 +1,24 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using System.Windows.Forms; + +namespace EthernetSwitcher +{ + static class Program + { + /// + /// The main entry point for the application. + /// + [STAThread] + static void Main() + { + Application.EnableVisualStyles(); + Application.SetCompatibleTextRenderingDefault(false); + // Load settings on startup + var settings = CurrentSettings.Instance; + Application.Run(new Form1()); + } + } +} \ No newline at end of file diff --git a/EthernetSwitcher/Properties/AssemblyInfo.cs b/EthernetSwitcher/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..b3b8613 --- /dev/null +++ b/EthernetSwitcher/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("EthernetSwitcher")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("EthernetSwitcher")] +[assembly: AssemblyCopyright("Copyright © 2026")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("0463CEC3-E6DB-4698-BA12-6166940A143A")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] \ No newline at end of file diff --git a/EthernetSwitcher/Properties/Resources.Designer.cs b/EthernetSwitcher/Properties/Resources.Designer.cs new file mode 100644 index 0000000..438b5a5 --- /dev/null +++ b/EthernetSwitcher/Properties/Resources.Designer.cs @@ -0,0 +1,64 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace EthernetSwitcher.Properties +{ + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resources + { + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() + { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager + { + get + { + if ((resourceMan == null)) + { + global::System.Resources.ResourceManager temp = + new global::System.Resources.ResourceManager("EthernetSwitcher.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture + { + get { return resourceCulture; } + set { resourceCulture = value; } + } + } +} \ No newline at end of file diff --git a/EthernetSwitcher/Properties/Resources.resx b/EthernetSwitcher/Properties/Resources.resx new file mode 100644 index 0000000..af7dbeb --- /dev/null +++ b/EthernetSwitcher/Properties/Resources.resx @@ -0,0 +1,117 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/EthernetSwitcher/Properties/Settings.Designer.cs b/EthernetSwitcher/Properties/Settings.Designer.cs new file mode 100644 index 0000000..81a63da --- /dev/null +++ b/EthernetSwitcher/Properties/Settings.Designer.cs @@ -0,0 +1,24 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace EthernetSwitcher.Properties +{ + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "11.0.0.0")] + internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase + { + private static Settings defaultInstance = ((Settings) (global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); + + public static Settings Default + { + get { return defaultInstance; } + } + } +} \ No newline at end of file diff --git a/EthernetSwitcher/Properties/Settings.settings b/EthernetSwitcher/Properties/Settings.settings new file mode 100644 index 0000000..3964565 --- /dev/null +++ b/EthernetSwitcher/Properties/Settings.settings @@ -0,0 +1,7 @@ + + + + + + + diff --git a/EthernetSwitcher/Settings.cs b/EthernetSwitcher/Settings.cs new file mode 100644 index 0000000..9a6f2c1 --- /dev/null +++ b/EthernetSwitcher/Settings.cs @@ -0,0 +1,94 @@ +using System; +using System.IO; +using System.Runtime.InteropServices; +using System.Windows.Forms; + +namespace EthernetSwitcher +{ + public enum EthernetMode + { + Auto, + Primary, + Secondary, + Disabled + } + + public enum IpProtocol + { + IPv4, + IPv6, + IPv4_IPv6 + } + + public class Settings + { + private static readonly string SettingsFilePath = Path.Combine(Application.StartupPath, "settings.ini"); + + public EthernetMode Mode { get; set; } = EthernetMode.Auto; + public string PrimaryName { get; set; } = ""; + public string SecondaryName { get; set; } = ""; + public int CheckInterval { get; set; } = 5; + public IpProtocol Protocol { get; set; } = IpProtocol.IPv4_IPv6; + + public static Settings Load() + { + var settings = new Settings(); + + if (File.Exists(SettingsFilePath)) + { + var mode = ReadIniValue("Settings", "Mode", "Auto"); + EthernetMode parsedMode; + if (Enum.TryParse(mode, out parsedMode)) + { + settings.Mode = parsedMode; + } + + settings.PrimaryName = ReadIniValue("Settings", "PrimaryName", ""); + settings.SecondaryName = ReadIniValue("Settings", "SecondaryName", ""); + + var interval = ReadIniValue("Settings", "CheckInterval", "5"); + int parsedInterval; + if (int.TryParse(interval, out parsedInterval)) + { + settings.CheckInterval = parsedInterval; + } + + var protocol = ReadIniValue("Settings", "Protocol", "IPv4_IPv6"); + IpProtocol parsedProtocol; + if (Enum.TryParse(protocol, out parsedProtocol)) + { + settings.Protocol = parsedProtocol; + } + } + + return settings; + } + + public void Save() + { + WriteIniValue("Settings", "Mode", Mode.ToString()); + WriteIniValue("Settings", "PrimaryName", PrimaryName); + WriteIniValue("Settings", "SecondaryName", SecondaryName); + WriteIniValue("Settings", "CheckInterval", CheckInterval.ToString()); + WriteIniValue("Settings", "Protocol", Protocol.ToString()); + } + + [DllImport("kernel32", CharSet = CharSet.Unicode)] + private static extern long WritePrivateProfileString(string section, string key, string value, string filePath); + + [DllImport("kernel32", CharSet = CharSet.Unicode)] + private static extern int GetPrivateProfileString(string section, string key, string defaultValue, string returnedString, int size, string filePath); + + private static void WriteIniValue(string section, string key, string value) + { + WritePrivateProfileString(section, key, value, SettingsFilePath); + } + + private static string ReadIniValue(string section, string key, string defaultValue) + { + var buffer = new string('\0', 256); + var length = GetPrivateProfileString(section, key, defaultValue, buffer, buffer.Length, SettingsFilePath); + return buffer.Substring(0, length); + } + } +} \ No newline at end of file diff --git a/EthernetSwitcher/app.manifest b/EthernetSwitcher/app.manifest new file mode 100644 index 0000000..4807a5b --- /dev/null +++ b/EthernetSwitcher/app.manifest @@ -0,0 +1,35 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + true + PerMonitorV2 + + + \ No newline at end of file diff --git a/EthernetSwitcher/icon.ico b/EthernetSwitcher/icon.ico new file mode 100644 index 0000000000000000000000000000000000000000..e4ca05ff2ab7d24dc0f7763013f200e9a5ebff49 GIT binary patch literal 21646 zcmeI4Nlau#7{{w=VGb^k%s82Y8Rn#H4alg6aS}WTdUK3R0wEBVgU1PQ0+Mc)#EVD> zA#BPvCj-cG&=C@779$?!;CPvgqK$Ky#8H+Tgr>{yE8aJ$yy>?9-PLxdDkImTXPjFp$4Y_nU8eF=3rPzNsHVbnwU4%DABrJb`q zHIGFcF9nmzQLyKwZL^8{(1(&t~coY~|M%Xb%gYlnW@cstzqGWpPl4U7jEsyAktH&<;CB*%v0sXcigkR7)~0TsX&wnScm)2hy1a`c?PB)_61~|k1##>Kot6qCZGvu0-As(pb2OKnt&#t z31|YEfF_^`XabsmCXfmQ@G(0+2E+VP0uLxt(t&m&Q*K>d-Pa2X3ys4bGcNHkM3K z(#FQdJ}@a#$fa;?ZEfGo1-BKlv1Ni<0)fC1Fu9_T%N4)hzleQDOA6Q&<9rhB+95sT z7Hd&+wd_|3BfkJ2U?n2_vu6|qSsCaTyZBa?WuNoFSTVv`C?V$CL%n8b=r zaZ^*%`Z+&~FM$}JkuQ=k7iGNLx&53nuWuaJvBsLsZhew-`}XbGm6eqp%wW#|kJnr< zQPr-@Y3&F1nm>bHy4Q5Oj;XeNCO9N~I7ZC<828qAU0Eg7?NCQqPfyP?_ur%)*TucPz29|rcYkYl&*PR$ zFc{pW*i<4b&|%9(aXaKv4qTp)MstZ=`uh652S2xS%X=8qB3){1Y>ajt&4NG9sa8pK zJGa--8;0Omu*n5Bb1+7BG2?s#v2(0|NcF1Pxt(`QByDIqvN7(N?Z(Z^5a%qP)A4SH zpVPmYuNm6LYX{!xz6aWAoFET5#e$6-@Bd&sGBKV%yyYM^mDt3J2_Z`bHg4CrPUD1_ zP?^kZ;>9GH*~FVkGO|&{B$?Q_eeQkQ`Ggo)m5%d`anF6jDnK0TZ#dm68{a)ztxwJ? z&5;e^nb)zW=)#q&Et}QV)m?~E=qgfdoP5#lJ&}(> zCUhj0Y~VZeC*YJ%jta{B#l^+H6F5%HhbZ3jkl(L3JUryJwYB5msPsLLnwpw1?3)s5 zf@^CNbj17GF*Bj<9C#mR2>!=2G&eW5U0GQ<2s^IQPKD*wii(Os)PP!06ZGxoUOt`@ zGa)!W$Hn|&JUeoTjqk9LjzqrC<{(q=)&w*GO+XXS1T+CnKoigeGyzRO6VL=S0Zl*? z&;+ar&@)l-qjbhbYS@`@H0xX(OXLFB?I(5^?ZAnBAZ)+z*%NlDutV53m@VvJHrSy| zVFyaV-n$@d<_G)0i*`i(#9-KicGv^eJR*MN@4$;TXKhd~!b8V5!4~16gIB-~W^eP) zBiW%Bzz&oKxi_4-Cw@fFFYE)TW=yhWAGxg@Q|?RFAZwE~bLm*Pe2nt3%S>ceGDDfI Q%$!T-LLlKM{8PyO4-CR%g#Z8m literal 0 HcmV?d00001 diff --git a/EthernetSwitcher/icon_green.ico b/EthernetSwitcher/icon_green.ico new file mode 100644 index 0000000000000000000000000000000000000000..35a3a7d49076bff071a7cdc7b7b09d029c2adadf GIT binary patch literal 1150 zcmb_ayGjF55IxCe6{1BdYfB+jNRd|X2Yg2jh^3$5cZm24k}ip*_yNX70s(_XenJ_~ z%-w-u(LhM$lIKeS_+9eHDd}0Gb|G#_E2+}EmacD0JJwI_ zd&q?IfAd@~^jYDGl`EhBot&--CuBW)(o6HJaVm8jVjD*`OV0G4`K1oP8?GT4jl{^w z5TA3&MK$E&{pCUPK>Sqfw*v22bN7LF82=;Z*71*fuVrFofjBGYgwt@J&v|LQsk=Wq LD5p8qxL)Hg63DK1 literal 0 HcmV?d00001 diff --git a/EthernetSwitcher/icon_red.ico b/EthernetSwitcher/icon_red.ico new file mode 100644 index 0000000000000000000000000000000000000000..eef12ecd2637241a279c35e5775db6171c07e731 GIT binary patch literal 1150 zcmb_byN$w75F9>700cxA6H*2x9O6?0Ww;J>q6Ksr2jPhVfCM2Sfe2^<1T)WGSOYqV z&$Grmp50kJ@3VmnuSx~HSJBM_p8#qEB`UGbfI4$8uI!6`v%jNH&YHQ{C;xHJ*Hk&x z*zyyZ0nrgS68N{tKLW07=NrMxVnejp~q zHi5V_=Hx&3&_0~@41dOBdyp6R_P?k8NAR5k#HG2tM)J-Ht=swK(c%2QP(~xnQZr4z zyUi~&;B9)DBSt2=IKG;jr9O->eiMV_x#V=?%JrOX)PF~&z2h6VUXR4gKgBoyjGd(7 SZpTC8Nkw-$NK;NV-g5%H+o|^e literal 0 HcmV?d00001 diff --git a/EthernetSwitcher/icon_yellow.ico b/EthernetSwitcher/icon_yellow.ico new file mode 100644 index 0000000000000000000000000000000000000000..efe40940303b5175d4d1886e7c4dcd9dc6c64c8c GIT binary patch literal 1150 zcmb_bOHKk&5Ug>AK;nj#TU~ksAdoOe(D*rn$M77+cm?B5aA`b%xG^Lo5*J)T^Q?Mr zI@6=ZU|>koHC5G3({BdI_~~}R?*m*Ez#f1@1}QR$XF^GB!)s^5dMn>XpWK?cd_#Qa z?!QB6^4R4!GDBGggb*lB%;55U)Z_tXju)Jx*Gsjk&$2fZ#TnXd#R>5#xn-=EJ{+pY zYt>_c!Jw`MqrO3k(kt6H_hJz7V-ah9r)m^kBns%!s0^9 zd};m{a=PZ|_v^meU!I?HcSq=Sj^i%L?OSbgf2jlTjPclJoEqu!L!4ip=J~ap=bHGo yy5DuYVQE*6H|U=u<{ygcZR3RwWL_BcxXJS%U?Q(lO~V(mA?Qa=+UVF literal 0 HcmV?d00001 diff --git a/EthernetSwitcher/log.txt b/EthernetSwitcher/log.txt new file mode 100644 index 0000000..5eef771 --- /dev/null +++ b/EthernetSwitcher/log.txt @@ -0,0 +1,10 @@ +ExecutePowerShell: Running command: Get-NetAdapterBinding -Name 'vEthernet (ethernet1)' -ComponentID ms_tcpip6 -ErrorAction SilentlyContinue +ExecutePowerShell: Exit code = 0 +ExecutePowerShell: Output = 'Name DisplayName ComponentID Enabled +---- ----------- ----------- ------- +vEthernet (ethernet1) Internet Protocol Version 6 (TCP/IPv6) ms_tcpip6 False' +IsIPv6Enabled: Output: 'Name DisplayName ComponentID Enabled +---- ----------- ----------- ------- +vEthernet (ethernet1) Internet Protocol Version 6 (TCP/IPv6) ms_tcpip6 False' +IsIPv6Enabled: Result = True +EnableIPv6: IPv6Enabled check returned True