using Newtonsoft.Json; using Renci.SshNet; using Spectre.Console; using System; using System.Collections.Generic; using System.Diagnostics; using System.DirectoryServices; using System.IO; using System.Linq; using System.Management; using System.Net; using System.Net.NetworkInformation; using System.Net.Sockets; using System.Reflection; using System.Security.Principal; using System.Text.RegularExpressions; using System.Threading; namespace domain_utility { internal class Program { static readonly string regularDateTime = @"(\d+[.]\d+[.]\d+[ ]\d+[:]\d+[:]\d+)"; static readonly string[,] stringsToFind = new string[,] { { "Учетная запись активна", @"(Yes|No)", "Учетная запись работает: " }, { "Последний пароль задан", regularDateTime, "Когда был сменен пароль: " }, { "Действие пароля завершается", regularDateTime, "Когда нужно менять пароль (крайний срок): "}, { "Членство в глобальных группах", @"([*].+)", "Член групп:\t" } }; static readonly string[,] computerNameRegex = new string[,] { { "^[a-zA-Z]+\\d+$", "R54-630300" }, // THE01 { "^\\d{6,}[a-zA-Z]+\\d+$", "R54-" }, // 630300THE01 { "^[rR]\\d{2,}[-]\\d{6,}[a-zA-Z]+\\d+$", "" } // R54-630300THE01 }; static string domain_user = string.Empty; static string domain_password = string.Empty; static bool _click_cancel = false; static bool IsStringContainIp(string ip) { return Regex.IsMatch(ip, @"^(\d+[.]\d+[.]\d+[.]\d+)$"); } static string CheckComputerName(string pcName) { for (int i = 0; i < computerNameRegex.GetLength(0); i++) if (Regex.IsMatch(pcName, computerNameRegex[i, 0])) return $"{computerNameRegex[i, 1]}{pcName}".ToUpper(); return string.Empty; } static string InputData(string message, Action callback, bool withClear = true, bool withChecks = true) { if (withClear) AnsiConsole.Clear(); string data = AnsiConsole.Prompt( new TextPrompt(message + "\n> ") ); if (string.IsNullOrWhiteSpace(data)) return InputData(message, callback, withClear, withChecks); data = data.Trim(); AnsiConsole.WriteLine(); if (withChecks) if (!IsStringContainIp(data)) { data = CheckComputerName(data); if (data == string.Empty) { AnsiConsole.WriteLine("Имя компьютера или IP-адрес не распознаны! Попробуйте еще раз."); BackToMenu(callback); } } return data; } static void BackToMenu(Action callback, bool withMessage = true) { if (withMessage) AnsiConsole.WriteLine("\nНажмите Enter чтобы продолжить, ESC чтобы вернуться на главную."); ConsoleKey key = Console.ReadKey(true).Key; if (key == ConsoleKey.Enter) callback.Invoke(); else if (key == ConsoleKey.Escape) Menu(); else { AnsiConsole.WriteLine("Нажмите Enter или ESC!"); BackToMenu(callback, false); } } static void InputDomainCredentials() { if (domain_user == string.Empty) { string machineNameAndUser = WindowsIdentity.GetCurrent().Name.ToString(); int indexOfUserName = machineNameAndUser.IndexOf('\\') + 1; domain_user = machineNameAndUser.Substring(indexOfUserName, machineNameAndUser.Length - indexOfUserName).ToLower(); } if (domain_password != string.Empty) return; domain_password = AnsiConsole.Prompt( new TextPrompt("\nВведите пароль от ТЕКУЩЕЙ учетной записи:\n> ") .Secret() ); } static void ExecuteCommandViaSSH(string remote, string commandToExecute) { InputDomainCredentials(); try { using (SshClient client = new SshClient(remote, domain_user, domain_password)) { client.Connect(); SshCommand command = client.RunCommand(commandToExecute); AnsiConsole.WriteLine(command.Result); client.Disconnect(); } } catch (Exception ex) { AnsiConsole.WriteLine("Произошла ошибка: " + ex.Message); } } static void ResetAdminPassword() { string machineNameAndUser = WindowsIdentity.GetCurrent().Name.ToString(); string machineName = machineNameAndUser.Substring(0, machineNameAndUser.IndexOf('\\')); using (DirectoryEntry directoryEntry = new DirectoryEntry(string.Format("WinNT://{0}/{1}", machineName, "Администратор"))) { //directoryEntry.Properties["LockOutTime"].Value = 0; directoryEntry.Invoke("SetPassword", "Qwe12345"); directoryEntry.CommitChanges(); directoryEntry.Close(); } AnsiConsole.WriteLine("Пароль сброшен."); BackToMenu(Menu); } static string PingHost(string host) { string returnMessage = string.Empty; PingOptions pingOptions = new PingOptions() { DontFragment = true }; // TTL = 128 using (Ping ping = new Ping()) { byte[] buffer = new byte[32]; for (int i = 0; i < 4; i++) { try { PingReply pingReply = ping.Send(host, 1000, buffer, pingOptions); if (pingReply == null) { returnMessage = "Ошибка подключения по неизвестной причине."; throw new Exception(message: string.Empty); } switch (pingReply.Status) { case IPStatus.Success: { if (pingReply.RoundtripTime < 1) returnMessage = string.Format("Ответ от {0}: число байт={1} время<1мс TTL={2}", pingReply.Address, pingReply.Buffer.Length, pingReply.Options.Ttl); else returnMessage = string.Format("Ответ от {0}: число байт={1} время={2}мс TTL={3}", pingReply.Address, pingReply.Buffer.Length, pingReply.RoundtripTime, pingReply.Options.Ttl); break; } case IPStatus.TimedOut: returnMessage = "Время подключения истекло."; break; case IPStatus.DestinationHostUnreachable: returnMessage = "Заданный узел недоступен."; break; default: returnMessage = string.Format("Ошибка пинга: {0}", pingReply.Status.ToString()); break; } } catch (Exception ex) { if (ex.Message != string.Empty) returnMessage = string.Format("Ошибка подключения: {0}", ex.Message); } } } return returnMessage; } static void PingClickCancel(object sender, ConsoleCancelEventArgs e) { e.Cancel = true; _click_cancel = true; } static void StartPing() { string remote = InputData("ping компьютера\n\nВведите IP адрес или имя компьютера (пр. 10.234.16.129, 'IT04', '630300IT04', 'R54-630300IT04'):", StartPing); AnsiConsole.WriteLine("Нажмите Ctrl + C чтобы остановить\n"); string correctName = CheckComputerName(remote); if (correctName != string.Empty) { try { IPAddress ip = Dns.GetHostEntry(correctName).AddressList.First(addr => addr.AddressFamily == AddressFamily.InterNetwork); remote = ip.ToString(); AnsiConsole.WriteLine("Обмен пакетами с {0}.main.russianpost.ru [{1}] с 32 байтами данных:", correctName, remote); } catch (Exception) { AnsiConsole.WriteLine("Компьютер не найден."); BackToMenu(StartPing); return; } } else AnsiConsole.WriteLine("Обмен пакетами с {0} по с 32 байтами данных:", remote); Console.CancelKeyPress += PingClickCancel; for (int i = 0; i < 4; i++) { if (_click_cancel) break; AnsiConsole.WriteLine(PingHost(remote)); Thread.Sleep(1000); } Console.CancelKeyPress -= PingClickCancel; _click_cancel = false; BackToMenu(StartPing); } static void StartRDPConnection() { string remote = InputData("удаленный доступ к компьютеру\n\nВведите IP адрес или имя компьютера (пр. 10.234.16.129, 'IT04', '630300IT04', 'R54-630300IT04'):", StartRDPConnection); remote = $"/v:{remote} /f"; Process proc = new Process(); proc.StartInfo = new ProcessStartInfo("mstsc", remote); proc.Start(); AnsiConsole.WriteLine("Подключение открыто."); BackToMenu(StartRDPConnection); } static void ShowDomainUserInfo() { string username = InputData("посмотреть информацию о пользователе\n\nВведите имя пользователя (пр. 'lev.rusanov'): ", ShowDomainUserInfo, withChecks: false); username = $"user {username} /domain"; ProcessStartInfo procStartInfo = new ProcessStartInfo("net", username) { CreateNoWindow = true, UseShellExecute = false, RedirectStandardOutput = true, }; List strArr = new List { }; Process proc = new Process(); proc.StartInfo = procStartInfo; proc.Start(); while (!proc.StandardOutput.EndOfStream) strArr.Add(proc.StandardOutput.ReadLine()); Match regex; bool groupsFlag = false; for (int i = 0; i < strArr.Count; i++) { for (int j = 0; j < stringsToFind.GetLength(0); j++) { if (strArr[i].Contains(stringsToFind[j, 0])) { regex = Regex.Match(strArr[i], stringsToFind[j, 1]); if (regex.Success) { AnsiConsole.WriteLine(stringsToFind[j, 2] + regex.Value); if (j == 3) { groupsFlag = true; continue; } } } if (j == 3 && groupsFlag) { regex = Regex.Match(strArr[i], stringsToFind[j, 1]); if (regex.Success) AnsiConsole.WriteLine("\t\t" + regex.Value); } } } strArr.Clear(); BackToMenu(ShowDomainUserInfo); } static void ShowComputerBootupTime() { string remote = InputData("посмотреть дату последней загрузки компьютера\n\nВведите IP адрес или имя компьютера (пр. 10.234.16.129, 'IT04', '630300IT04', 'R54-630300IT04'):", ShowComputerBootupTime); ManagementScope scope = new ManagementScope(string.Format(@"\\{0}\root\cimv2", remote)); try { scope.Connect(); ObjectQuery query = new ObjectQuery("SELECT LastBootUpTime FROM Win32_OperatingSystem"); ManagementObjectSearcher searcher = new ManagementObjectSearcher(scope, query); var firstResult = searcher.Get().OfType().First()["LastBootUpTime"]; DateTime lastBootUp = ManagementDateTimeConverter.ToDateTime(firstResult.ToString()); AnsiConsole.WriteLine("Дата последней загрузки: " + lastBootUp); AnsiConsole.WriteLine("Время работы (д:ч:м:с): " + (DateTime.Now.ToUniversalTime() - lastBootUp.ToUniversalTime()).ToString(@"d\:hh\:mm\:ss")); } catch (Exception) { AnsiConsole.WriteLine("Произошла ошибка. Попробуйте еще раз."); } BackToMenu(ShowComputerBootupTime); } static void RemoteRebootWindows() { string remote = InputData("удаленная перезагрузка компьютера\n\nВведите IP адрес или имя компьютера (пр. 10.234.16.129, 'IT04', '630300IT04', 'R54-630300IT04'):", RemoteRebootWindows); remote = $"/m \\\\{remote} /r /f /t 180 /c \"Через 3 минуты будет произведена перезагрузка ПК!\""; Process proc = new Process(); proc.StartInfo = new ProcessStartInfo("shutdown", remote); proc.Start(); AnsiConsole.WriteLine("Команда перезагрузки отправлена."); BackToMenu(RemoteRebootWindows); } static void OpenComputerCups() { string remote = InputData("открыть CUPS выбранного компьютера (Linux)\n\nВведите IP адрес или имя компьютера (пр. 10.234.16.129, 'IT04', '630300IT04', 'R54-630300IT04'):", OpenComputerCups); Process.Start($"https://{remote}:631/printers"); AnsiConsole.WriteLine($"CUPS {remote} открыт."); BackToMenu(OpenComputerCups); } static void ExecuteCustomCommandViaSSH() { string remote = InputData("выполнить команду через SSH (Linux)\n\nВведите IP адрес или имя компьютера (пр. 10.234.16.129, 'IT04', '630300IT04', 'R54-630300IT04'):", ExecuteCustomCommandViaSSH); string commandToExecute = InputData("Введите команду для выполнения:", ExecuteCustomCommandViaSSH, withClear: false, withChecks: false); ExecuteCommandViaSSH(remote, commandToExecute); AnsiConsole.WriteLine("Команда выполнена."); BackToMenu(ExecuteCustomCommandViaSSH); } static void FixConky() { string remote = InputData("изменить время обновления conky с 0.5 на 300 (Linux)\n\nВведите IP адрес или имя компьютера (пр. 10.234.16.129, 'IT04', '630300IT04', 'R54-630300IT04'):", FixConky); ExecuteCommandViaSSH(remote, "sudo sed -i 's/update_interval = 0.5,/update_interval = 300,/' /etc/conky/conky.conf"); AnsiConsole.WriteLine("Команда исправления Conky отправлена."); BackToMenu(FixConky); } static void RemoteRebootLinux() { string remote = InputData("удаленная перезагрузка компьютера (Linux)\n\nВведите IP адрес или имя компьютера (пр. 10.234.16.129, 'IT04', '630300IT04', 'R54-630300IT04'):", RemoteRebootLinux); ExecuteCommandViaSSH(remote, "sudo shutdown -r +3 \"Через 3 минуты будет произведена перезагрузка ПК!\""); AnsiConsole.WriteLine("Команда перезагрузки отправлена."); BackToMenu(RemoteRebootLinux); } static void ShowLinuxComputerBootupTime() { string remote = InputData("посмотреть время работы компьютера (Linux)\n\nВведите IP адрес или имя компьютера (пр. 10.234.16.129, 'IT04', '630300IT04', 'R54-630300IT04'):", ShowLinuxComputerBootupTime); ExecuteCommandViaSSH(remote, "uptime"); BackToMenu(ShowLinuxComputerBootupTime); } static void ChangeRemote802Password() { string remote = InputData("сменить пароль для 802.1x (Linux)\n\nВведите IP адрес или имя компьютера (пр. 10.234.16.129, 'IT04', '630300IT04', 'R54-630300IT04')\nall - для массового изменения", ChangeRemote802Password, withChecks: false); remote = remote.Trim().ToLower(); if (remote != "all") { if (!IsStringContainIp(remote)) { remote = CheckComputerName(remote); if (remote == string.Empty) ChangeRemote802Password(); } } string new802password = AnsiConsole.Prompt( new TextPrompt("\nВведите новый пароль от УЗ:\n> ") .Secret() ); if (remote == "all") { string armListKey = AnsiConsole.Prompt( new TextPrompt("Введите УЗ на которой нужно сменить пароль") .AddChoices(new string[] { "OBR", "PIS", "OBM", "MMP" }) ); InputDomainCredentials(); string path = Path.Combine(Environment.CurrentDirectory, "settings.json"); if (!File.Exists(path)) { AnsiConsole.WriteLine("Файл с настройками не найден!"); BackToMenu(ChangeRemote802Password); } JsonFile data = JsonConvert.DeserializeObject(File.ReadAllText(path)); string unitKey; int sleep_time = data.sleep_time; foreach (KeyValuePair> unit in data.arm_list) { unitKey = unit.Key; if (unitKey != armListKey) continue; foreach (int position in unit.Value) { remote = CheckComputerName($"{unitKey}{(position < 10 ? $"0{position}" : position.ToString())}"); if (remote == string.Empty) { AnsiConsole.WriteLine($"{unitKey}{(position < 10 ? $"0{position}" : position.ToString())}: имя ПК не распознано."); continue; } try { using (SshClient client = new SshClient(remote, domain_user, domain_password)) { client.Connect(); SshCommand command = client.RunCommand($"sudo sed -i 's/password=.\\+/password={new802password}/' /etc/NetworkManager/system-connections/Проводное\\ подключение\\ 1.nmconnection"); //AnsiConsole.WriteLine(command.Result); command = client.RunCommand("sudo nmcli connection reload"); //AnsiConsole.WriteLine(command.Result); command.Dispose(); client.Disconnect(); } AnsiConsole.WriteLine(remote + ": "); } catch (Exception ex) { AnsiConsole.WriteLine(remote + ": " + ex.Message); } } } } else { ExecuteCommandViaSSH(remote, $"sudo sed -i 's/^password=.\\+/password={new802password}/' /etc/NetworkManager/system-connections/Проводное\\ подключение\\ 1.nmconnection && sudo nmcli connection reload"); AnsiConsole.WriteLine("Команда отправлена."); } BackToMenu(ChangeRemote802Password); } static void DisableKdeWallet() { string remote = InputData("отключить KDE кошелек (Linux)\n\nВведите IP адрес или имя компьютера (пр. 10.234.16.129, 'IT04', '630300IT04', 'R54-630300IT04'):", DisableKdeWallet); ExecuteCommandViaSSH(remote, "sudo sed -i 's/^Exec=/#Exec=/' /usr/share/dbus-1/services/org.kde.kwalletd5.service"); AnsiConsole.WriteLine("Команда отключения кошелька отправлена."); BackToMenu(DisableKdeWallet); } private class MenuItem { public string Name { get; } public Action Executor { get; } public MenuItem(string _name, Action _executor) { Name = _name; Executor = _executor; } } static readonly MenuItem[] availableOptions = new[] { new MenuItem("ping компьютера", () => StartPing()), new MenuItem("удаленный доступ к компьютеру", () => StartRDPConnection()), new MenuItem("посмотреть информацию о пользователе", () => ShowDomainUserInfo()), new MenuItem("посмотреть дату последней загрузки компьютера", () => ShowComputerBootupTime()), new MenuItem("удаленная перезагрузка компьютера", () => RemoteRebootWindows()), new MenuItem("открыть CUPS выбранного компьютера (Linux)", () => OpenComputerCups()), new MenuItem("выполнить команду через SSH (Linux)", () => ExecuteCustomCommandViaSSH()), new MenuItem("изменить время обновления conky с 0.5 на 300 (Linux)", () => FixConky()), new MenuItem("удаленная перезагрузка компьютера (Linux)", () => RemoteRebootLinux()), new MenuItem("посмотреть время работы компьютера (Linux)", () => ShowLinuxComputerBootupTime()), new MenuItem("сменить пароль для 802.1x (Linux)", () => ChangeRemote802Password()), new MenuItem("отключить KDE кошелек (Linux)", () => DisableKdeWallet()), }; static void Menu() { AnsiConsole.Clear(); MenuItem choice = AnsiConsole.Prompt( new SelectionPrompt() .Title("Выберите действие:") .PageSize(15) //.MoreChoicesText("[grey](Move up and down to reveal more fruits)[/]") .UseConverter(i => i.Name) .AddChoices(availableOptions) ); choice.Executor(); } class JsonFile { public int sleep_time = 0; public int restart_time = 0; public string message = ""; public Dictionary> arm_list = null; } static void StartRestartComputers() { string path = Path.Combine(Environment.CurrentDirectory, "settings.json"); if (!File.Exists(path)) { AnsiConsole.WriteLine("Файл с настройками не найден!"); Console.ReadKey(); return; } JsonFile data = JsonConvert.DeserializeObject(File.ReadAllText(path)); string remote, unitKey; int sleep_time = data.sleep_time; foreach (KeyValuePair> unit in data.arm_list) { unitKey = unit.Key; foreach (int position in unit.Value) { remote = CheckComputerName($"{unitKey}{(position < 10 ? $"0{position}" : position.ToString())}"); if (remote == string.Empty) { AnsiConsole.WriteLine($"{unitKey}{(position < 10 ? $"0{position}" : position.ToString())}: имя ПК не распознано."); continue; } //AnsiConsole.WriteLine($"{remote}: shutdown -r +{data.restart_time} \"{data.message}\""); ExecuteCommandViaSSH(remote, $"sudo shutdown -r +{data.restart_time} \"{data.message}\""); Thread.Sleep(sleep_time); } } Console.ReadKey(); } static void Main(string[] args) { Console.Title = Assembly.GetExecutingAssembly().GetCustomAttribute().Title; if (args.Length > 0 && args[0] == "reboot") { StartRestartComputers(); return; } Menu(); } } }