public SystemProxyManager() { AppDomain.CurrentDomain.ProcessExit += (o, args) => RestoreOriginalSettings(); if (Environment.UserInteractive && NativeMethods.GetConsoleWindow() != IntPtr.Zero) { var handler = new NativeMethods.ConsoleEventDelegate(eventType => { if (eventType != 2) { return(false); } RestoreOriginalSettings(); return(false); }); NativeMethods.Handler = handler; // On Console exit make sure we also exit the proxy NativeMethods.SetConsoleCtrlHandler(handler, true); } }
static void Main() { Initialize(); #region Error Mode //Prevent error dialog popups, this prevents the miner sub process from hanging by a windows error popup during a crash NativeMethods.SetErrorMode(NativeMethods.ErrorModes.SemFailcriticalerrors | NativeMethods.ErrorModes.SemNogpfaulterrorbox); #endregion #region Console Hooks //Hook Console to catch Close Event Handler = ConsoleEventCallback; NativeMethods.SetConsoleCtrlHandler(Handler, true); Console.CancelKeyPress += delegate(object sender, ConsoleCancelEventArgs e) { e.Cancel = true; _running = false; PrettyConsole.WriteLine("Gracefully exiting...", ConsoleColor.Magenta); }; #endregion Startup: try { ConnectToMonitoringSocket(); //Every minute the miner is running, it updates this file with how many minutes it has mined % MinutesInRotation var text = ""; try { text = File.ReadAllText(MiningMinuteFile); } catch (Exception ex) { Log.Warning(ex); } if (!int.TryParse(text, out _miningMinute)) { Log.Warning($"Unable to read Mining Minute, defaulting to 0. Text received from {MiningMinuteFile}: {text}"); } int currentMinute = -1; var freshStart = new List <string> { "XzonControlPanel" }; foreach (MinerConfig miner in _miners) { var exeName = Path.GetFileNameWithoutExtension(miner.ExeLocation); if (!freshStart.Contains(exeName)) { freshStart.Add(exeName); } } foreach (var p in freshStart) { ProcessHelper.KillProcess(p); } Thread.Sleep(1000); PrettyConsole.Write("Max Allowed GPU Temperature is "); PrettyConsole.WriteLine($"{MaxTemp}°c", ConsoleColor.Red); PrettyConsole.WriteLine(); Log.Warning("Miner Has Started"); //Main Loop while (_running) { Temperature.Refresh(); #region Scheduling if (DateTime.Now.Hour * 60 + DateTime.Now.Minute != currentMinute && !_paused) { //Minute changed, increment _miningMinute = (_miningMinute + 1) % MinutesInRotation; UpdateMiningMinute(_miningMinute); currentMinute = DateTime.Now.Hour * 60 + DateTime.Now.Minute; PrettyConsole.WriteLine($"Current Minute: {_miningMinute}", ConsoleColor.DarkYellow); //Check if it is time to use the next miner config in the schedule MinerConfig newMinerConfig = _miners[0]; foreach (MinerConfig miner in _miners) { if (miner.StartMinute <= _miningMinute) { newMinerConfig = miner; } else { PrettyConsole.WriteLine($"Will start {miner.Name} at minute {miner.StartMinute}", ConsoleColor.DarkYellow); } } if (!newMinerConfig.Equals(_currentMiningConfig)) { SetActiveMiner(newMinerConfig); } } #endregion VerifyProcesses(); if (!_running) { break; } if (_paused) { Log.Informational("Miner is paused"); //If reboot after paused X minutes is set, reboot after X minutes if (RebootAfterPausedXMinutes > 0 && _pausedTime != null) { if (DateTime.Now > _pausedTime.Value.AddMinutes(RebootAfterPausedXMinutes)) { Log.Warning("Rebooting Machine"); Process.Start("shutdown.exe", "-r -t 30"); _running = false; } else { Log.Informational($"Rebooting machine in {_pausedTime.Value.AddMinutes(RebootAfterPausedXMinutes).Subtract(DateTime.Now).TotalSeconds} seconds", true); PrettyConsole.Write("Rebooting machine in "); PrettyConsole.Write($"{_pausedTime.Value.AddMinutes(RebootAfterPausedXMinutes).Subtract(DateTime.Now).TotalSeconds}", ConsoleColor.Yellow); PrettyConsole.WriteLine(" seconds"); } } } List <Gpu> gpus = new List <Gpu>(); List <Cpu> cpus = new List <Cpu>(); if (Temperature.GpuTemperatures == null) { Log.Warning("Unable to read GPU Temperatures, killing miner"); Pause(); KillMiner(); continue; } foreach (var temp in Temperature.CpuTemperatures) { PrettyConsole.Write($"{temp.InstanceName} ({temp.InstanceId}): "); PrettyConsole.WriteLine($"{temp.CurrentValue}°c", ConsoleColor.Cyan); cpus.Add(new Cpu { Color = "Cyan", Id = temp.InstanceId, Name = temp.InstanceName, Temp = (int)temp.CurrentValue }); } foreach (var temp in Temperature.GpuTemperatures) { PrettyConsole.Write($"{temp.InstanceName} ({temp.InstanceId}): "); var outputColor = ConsoleColor.Cyan; if (temp.CurrentValue >= MaxTemp) { outputColor = ConsoleColor.Red; PrettyConsole.Write($"{temp.CurrentValue}", outputColor); PrettyConsole.Write(@"°c"); } else if (temp.CurrentValue >= WarningTemp) { outputColor = ConsoleColor.Yellow; PrettyConsole.Write($"{temp.CurrentValue}", outputColor); PrettyConsole.Write(@"°c"); } else if (Math.Abs(temp.CurrentValue) < 1) { //Check if GPU went offline, if it did its reported temperature is 0, check for <1 because floating point numbers doing their thing outputColor = ConsoleColor.Red; PrettyConsole.Write($"{temp.CurrentValue}", outputColor); PrettyConsole.Write(@"°c"); Log.Error($"GPU {temp.InstanceName} ({temp.InstanceId}) Went Offline."); KillMiner(); Pause(); } else { PrettyConsole.Write($"{temp.CurrentValue}", outputColor); PrettyConsole.Write(@"°c"); } decimal gpuHr = -1; try { int gpuId; if (int.TryParse(temp.InstanceId.Substring(temp.InstanceId.LastIndexOf("/", StringComparison.Ordinal) + 1), out gpuId)) { lock (RecentGpuHashrates) { if (RecentGpuHashrates.ContainsKey(gpuId) && RecentGpuHashrates[gpuId].Count > 0) { gpuHr = decimal.Round(RecentGpuHashrates[gpuId].Average(), 2); PrettyConsole.Write($" ({gpuHr} {_units}/s)", ConsoleColor.Gray); } } } } catch (Exception) { //Do nothing } finally { PrettyConsole.WriteLine(); } gpus.Add(new Gpu { Color = outputColor.ToString(), Name = temp.InstanceName, Id = temp.InstanceId, Temp = (int)temp.CurrentValue, Rate = gpuHr }); if (temp.CurrentValue > MaxTemp) { Log.Error($"Killing miner, GPU Temperature is {temp.CurrentValue}°c but the max is set for {MaxTemp}°c"); //Hard shut down //Exit(1); //Soft shut down KillMiner(); Pause(); } } //Check average hash rate decimal averageHashrate = 0; ConsoleColor hashrateColor = ConsoleColor.Red; if (RecentHashrates.Count > 0) { Queue <decimal> localQueue = new Queue <decimal>(RecentHashrates); averageHashrate = decimal.Round(localQueue.Average(), 3); hashrateColor = ConsoleColor.Green; if (averageHashrate < _currentMiningConfig.HashrateError) { hashrateColor = ConsoleColor.Red; if (localQueue.Count == TotalReadingsToAverage) { var error = $"Average Hashrate {averageHashrate} dropped below configured error rate ({_currentMiningConfig.HashrateError}). Killing miner."; Log.Error(error); KillMiner(); } } else if (averageHashrate < _currentMiningConfig.HashrateWarning) { hashrateColor = ConsoleColor.Yellow; if (localQueue.Count == TotalReadingsToAverage) { Log.Warning($"Average Hashrate {averageHashrate} dropped below configured warning rate {_currentMiningConfig.HashrateWarning}."); } } if (localQueue.Count > 0) { PrettyConsole.Write(@"Current Average Hashrate: "); PrettyConsole.Write($"{averageHashrate} {_units}/s", hashrateColor); PrettyConsole.WriteLine(); } PrettyConsole.Write(@"Solutions Found: "); PrettyConsole.Write($"{_solutionsFound}", _solutionsFound > 0 ? ConsoleColor.Green : ConsoleColor.Yellow); if (_rejectedSolutions > 0) { PrettyConsole.Write(@". Rejected: "); PrettyConsole.Write($"{_rejectedSolutions}", ConsoleColor.Red); } PrettyConsole.WriteLine(@"."); } UpdateMonitoringSockets(gpus, cpus, averageHashrate, hashrateColor); //foreach (var config in _miners) //{ // PrettyConsole.WriteLine($"({config.Wallet}){WalletHelper.GetWalletBalance(config.CurrencyCode, config.Wallet)}", ConsoleColor.DarkGreen); //} Thread.Sleep(10000); if (File.Exists("stop.txt")) { File.Delete("stop.txt"); _running = false; } } } catch (Exception ex) { Log.Error(ex); if (_running) { Log.Warning(ex); Log.Informational("Attempting to restart from the beginning..."); goto Startup; } } KillMiner(); Exit(); }