private async Task <int> UpdateWtmSettings(Computer pc, CancellationToken token, int errorCount, int iteration, int jobCount, DateTime wtmSettingsDate) { pc.SwitchStatus = Computer.OperationStatus.OperationInProgress; var address = ViewModel.BuildServerAddress(pc.Name, Constants.StreamServer); var channel = Service.NewStreamChannel(address, TimeSpan.FromSeconds(60)); MemoryStream stream = NetHelper.SerializeToStream <WtmSettingsObject>(ViewModel.Instance.WtmSettings); var uploadRequest = new StreamUploadRequest { Stream = stream }; try { if (ViewModel.Instance.WtmSettings.ProxyPassword != null && ViewModel.Instance.WtmSettings.ProxyPassword.Length != 0) { uploadRequest.ProxyPassword = ViewModel.Instance.WtmSettings.ProxyPassword.ToCharArray(); } var response = await channel.UpdateWtmSettings(uploadRequest).WithCancellation(token).ConfigureAwait(false); if (response.ResponseFlag) { pc.SwitchStatus = Computer.OperationStatus.Success; pc.WtmSettingsDate = response.Date; if (pc.WtmSettingsDate >= wtmSettingsDate) { pc.UpdateStatus = Computer.OperationStatus.NotNecessary; } } } catch (Exception ex) { errorCount++; pc.SwitchStatus = Computer.OperationStatus.Failure; Application.Current.Dispatcher.Invoke(() => { var p = new Paragraph(); p.Inlines.Add(new Run($"{pc.Name}: ").FontWeight(FontWeights.Bold).Color(Colors.Salmon)); p.Inlines.Add(new Run($"Failed to update.\r\n")); p.Inlines.Add(new Run(ex.Message + "\r\n")); NewParagraph = p; }); } finally { if (uploadRequest.ProxyPassword.Length != 0) { Array.Clear(uploadRequest.ProxyPassword, 0, uploadRequest.ProxyPassword.Length); } NetHelper.CloseChannel(channel); stream.Dispose(); ReportTitle = $"Progress: {iteration + 1} of {jobCount}."; } return(errorCount); }
private async void ScanLanCommand(object obj) { ScanLanIsInProgress = true; ScanLanCancelSource = new CancellationTokenSource(); var token = ScanLanCancelSource.Token; var taskList = new List <Task>(); foreach (var table in ProfitTables.Tables) { foreach (var pc in table.Computers) { pc.OnlineStatus = Computer.OperationStatus.OperationInProgress; Task task = Task.Run(async() => //Func<Task> function = (async () => { var serverAddress = "net.tcp://" + pc.Name + ":" + NetHelper.Port + Constants.AccessPoint; var channel = Service.NewChannel(serverAddress, TimeSpan.FromSeconds(15)); try { var info = await channel.GetInfoAsync().WithCancellation(token).ConfigureAwait(false); Debug.WriteLine($"{pc.Name} coin: {info?.CurrentCoin?.GetSymbol()}."); if (info != null) { pc.OnlineStatus = Computer.OperationStatus.Success; pc.CurrentCoinName = info?.CurrentCoin?.GetCoinInfo("Name"); pc.CurrentCoinSymbol = info?.CurrentCoin?.GetCoinInfo("SYMBOL"); pc.ApplicationMode = info.ApplicationMode; } else { pc.OnlineStatus = Computer.OperationStatus.Failure; } } catch (Exception ex) { Debug.WriteLine($"{pc.Name} is not responding. " + ex.Message); pc.OnlineStatus = Computer.OperationStatus.Failure; } finally { NetHelper.CloseChannel(channel); } }); taskList.Add(task); } } await Task.WhenAll(taskList); ScanLanIsInProgress = false; }
private async void TestConnectionCommand(object obj) { var serverAddress = BuildServerAddress(WtmSettings.ServerName, Constants.AccessPoint); var channel = Service.NewChannel(serverAddress); TestConnection.SetCanExecute(false); Helpers.MouseCursorWait(); var cancelSource = new CancellationTokenSource(); var token = cancelSource.Token; ProgressManager pm = new ProgressManager($"Accessing {WtmSettings.ServerName}...", cancelSource, 1000, true); try { var testResult = await channel.GetInfoAsync().WithCancellation(token).ConfigureAwait(false); if (testResult != null) { pm.IsAlive = false; pm.Close(); await Task.Delay(100); Helpers.MouseCursorNormal(); if (testResult.ApplicationMode == "Server") { MessageBox.Show($"{Constants.AppName} server is alive and responsive on {WtmSettings.ServerName}.", "Success", MessageBoxButton.OK); } else { MessageBox.Show($"{Constants.AppName} is up on {WtmSettings.ServerName} but it is not in server mode.", "Error", MessageBoxButton.OK, MessageBoxImage.Error); } } } catch (Exception ex) { pm.Close(); await Task.Delay(100); Helpers.MouseCursorNormal(); MessageBox.Show("No response from the server.\n\n" + ex.Message, "Failure", MessageBoxButton.OK, MessageBoxImage.Error); } finally { var error = NetHelper.CloseChannel(channel); Application.Current.Dispatcher.Invoke(() => TestConnection.SetCanExecute(true)); if (pm.IsAlive) { pm.Close(); } } }
private async Task QueryRemoteWtmSettingsDate(Computer pc, CancellationToken token, DateTime wtmSettingsDate) { var address = ViewModel.BuildServerAddress(pc.Name, Constants.AccessPoint); var channel = Service.NewChannel(address); try { var info = await channel.GetInfoAsync().WithCancellation(token).ConfigureAwait(false); var remoteSettingsDate = await channel.GetWtmSettingsDateAsync().WithCancellation(token).ConfigureAwait(false); if (info != null) { pc.OnlineStatus = Computer.OperationStatus.Success; pc.ApplicationMode = info.ApplicationMode; pc.WtmSettingsDate = remoteSettingsDate; if (wtmSettingsDate > remoteSettingsDate) { pc.Switch = true; pc.SwitchStatus = Computer.OperationStatus.Possible; pc.UpdateStatus = Computer.OperationStatus.Necessary; } else { pc.SwitchStatus = Computer.OperationStatus.NotPossible; pc.UpdateStatus = Computer.OperationStatus.NotNecessary; } } } catch (Exception) { pc.OnlineStatus = Computer.OperationStatus.Failure; pc.SwitchStatus = Computer.OperationStatus.NotPossible; } finally { NetHelper.CloseChannel(channel); } return; }
private async Task UpdateWorkersFromServer(StreamWriter logFile) { bool addressOk = ValidateServerAddress(logFile); if (!addressOk) { return; } var serverAddress = BuildServerAddress(WtmSettings.ServerName, Constants.AccessPoint); var channel = Service.NewChannel(serverAddress); DateTime remoteWorkersDate = default(DateTime); string errorMessage = "Failed to update Workers from local server."; try { remoteWorkersDate = await channel.GetWorkersDateAsync(); } catch (Exception ex) { logFile?.WriteLine(errorMessage + " " + ex.Message); NetHelper.CloseChannel(channel); return; } if (remoteWorkersDate == default(DateTime)) { NetHelper.CloseChannel(channel); logFile?.WriteLine(errorMessage); return; } var localWorkersDate = Workers.GetWorkersLastUpdateTime(); if (localWorkersDate >= remoteWorkersDate) { logFile?.WriteLine($"{Constants.WorkersFile} is up to date."); NetHelper.CloseChannel(channel); return; } NetHelper.CloseChannel(channel); // Open stream channel for workers download serverAddress = BuildServerAddress(WtmSettings.ServerName, Constants.StreamServer); var streamChannel = Service.NewStreamChannel(serverAddress); Workers workers = null; try { var response = await streamChannel.GetWorkersAsync().ConfigureAwait(false); if (response != null) { var memoryStream = new MemoryStream(); await response.Stream.CopyToAsync(memoryStream); workers = NetHelper.DeserializeFromStream <Workers>(memoryStream); } if (workers == null) { throw new NullReferenceException("The received data are null."); } } catch (Exception ex) { logFile?.WriteLine(errorMessage + " " + ex.Message); NetHelper.CloseChannel(streamChannel); return; } bool wResult = Workers.SaveWorkers(workers); if (!wResult) { logFile?.WriteLine("Workers have been received from local server but could not be saved."); NetHelper.CloseChannel(streamChannel); return; } IsInitializingWtm = true; Workers.PropertyChanging -= Workers_PropertyChanging; Workers.PropertyChanged -= Workers_PropertyChanged; Workers = new Workers(workers.WorkerList, workers.PowerCost, workers.CoinType, workers.DisplayCoinAs, workers.NetworkScanMethod); Workers.PropertyChanging += Workers_PropertyChanging; Workers.PropertyChanged += Workers_PropertyChanged; IsInitializingWtm = false; logFile?.WriteLine("Workers have been received from local server and successfully updated."); NetHelper.CloseChannel(streamChannel); }
public async Task <SwitchResult> SwitchStandalone() { var streamServerAddress = BuildServerAddress(WtmSettings.ServerName, Constants.StreamServer); using (var logFile = new StreamWriter(Constants.SwitchLog, true)) { if (new FileInfo(Constants.SwitchLog).Length > 0) { logFile.WriteLine(string.Empty); } logFile.WriteLine(DateTime.Now); // Respect the DelayNextSwitchTime setting if (WtmSettings.DelayNextSwitchTime != 0) { var lastTime = new DateTime(); var lastTimeObj = GetRegistryKeyValue(Constants.SwitchRegistryKey, "LastSuccess"); string lastTimeStr = lastTimeObj as string; if (lastTimeStr != null && lastTimeStr != string.Empty) { lastTime = Convert.ToDateTime(lastTimeStr, DateTimeFormatInfo.InvariantInfo).ToUniversalTime(); var now = DateTime.UtcNow; var lastTimePlusDelay = lastTime.AddHours(WtmSettings.DelayNextSwitchTime); if (now < lastTimePlusDelay) { logFile.WriteLine($"Because of the Delay option checked Auto Switch can proceed only after {lastTimePlusDelay.ToLocalTime()}."); return(SwitchResult.DelayIsNotOver); } } } // Update Workers from server if (WtmSettings.ApplicationMode == "Client" && WtmSettings.UpdateWorkersFromServer) { await UpdateWorkersFromServer(logFile); } //Find localhost name in Workers list (used in Standalone and Client modes ) var thisPcName = Environment.MachineName; Worker thisWorker = GetWorkerByPCName(thisPcName); if (thisWorker == null && WtmSettings.ApplicationMode != "Server") { string msg = $"{thisPcName} was not found in any worker."; logFile.WriteLine(msg); return(SwitchResult.ThisPcIsNotListed); } // Get coin names from worker description var coinList = new List <string>(); var allCoinList = new List <string>(); var workersList = new List <Worker>(); string noCoinChecked = string.Empty; if (thisWorker != null) { noCoinChecked = $"No coin is checked as switchable in {thisWorker.Name}."; } else { noCoinChecked = "No coin is checked as switchable."; } if (WtmSettings.ApplicationMode != "Server") // Standalone or Client mode - just the worker that contains localhost name { workersList = new List <Worker> { thisWorker }; } else // Server mode - all workers, all coins { foreach (var w in Workers.WorkerList) { workersList.Add(w.Clone()); } allCoinList = Workers.GetCoins(workersList, false, false); if (allCoinList == null || allCoinList.Count == 0) { logFile.WriteLine(noCoinChecked); return(SwitchResult.NothingToDo); } if (!allCoinList.Contains("Bitcoin")) { allCoinList.Add("Bitcoin"); } } coinList = Workers.GetCoins(workersList, false, true); // Only coins with Switch checked if (coinList == null || coinList.Count == 0) { logFile.WriteLine(noCoinChecked); return(SwitchResult.NothingToDo); } if (!coinList.Contains("Bitcoin")) { coinList.Add("Bitcoin"); } // Get WTM coins JSON data Dictionary <string, WtmData> wtmDataDict = new Dictionary <string, WtmData>(); // Attempt to download data from local server HistoricalData localDataCopy = null; if (WtmSettings.ApplicationMode == "Client") { var channel = Service.NewStreamChannel(streamServerAddress, TimeSpan.FromSeconds(60)); try { var response = await channel.GetWtmLocalDataAsync(); if (response != null) { var memoryStream = new MemoryStream(); await response.Stream.CopyToAsync(memoryStream); localDataCopy = NetHelper.DeserializeFromStream <HistoricalData>(memoryStream); } if (localDataCopy == null) { throw new NullReferenceException("Local data from server are null."); } } catch (Exception ex) { logFile.WriteLine($"Failed to download proxy data from local server {WtmSettings.ServerName}. " + ex.Message); if (!WtmSettings.QueryWtmOnLocalServerFail) { return(SwitchResult.NoWtmData); } } finally { NetHelper.CloseChannel(channel); } // Check if the received data are up to date if (localDataCopy != null) { bool dataTimestampGood = EvaluateWtmDataTimeRange(localDataCopy.Date); if (!dataTimestampGood && !WtmSettings.QueryWtmOnLocalServerFail) { logFile.WriteLine("The server cache data is expired." + " Make sure that AutoSwitch on the client launches later than on the server." + " For example, if AutoSwitch runs on a daily basis schedule AutoSwitch on the server to run at 9:00 and on the client machines at anyting between 10:00-23:59." + " This way the cache data obtained in the morning is valid for the rest of the day."); return(SwitchResult.Terminate); } if (dataTimestampGood) { // Filter out coins downloded from server that are not checked for AutoSwitch locally wtmDataDict = localDataCopy.PriceData.Where(x => coinList.Contains(x.Key)).ToDictionary(x => x.Key, x => x.Value); } } } // Download data from WhatToMine (Standalone or Server) if (wtmDataDict.Count == 0) { StatusBarText = "Downloading coin definitions from whattomine.com..."; (Dictionary <string, WtmData> data, WhatToMine.GetWtmCoinDataResult result)wtmDataResult = (null, WhatToMine.GetWtmCoinDataResult.OK); if (WtmSettings.ApplicationMode == "Server") { var allCoinHashList = GetHashrates(allCoinList); wtmDataResult = await WhatToMine.GetWtmCoinData(allCoinHashList, false, logFile).ConfigureAwait(false); } else { var coinHashList = GetHashrates(coinList); wtmDataResult = await WhatToMine.GetWtmCoinData(coinHashList, false, logFile).ConfigureAwait(false); } if (wtmDataResult.result == WhatToMine.GetWtmCoinDataResult.CoinNotFound) { return(SwitchResult.CoinNotFound); } wtmDataDict = wtmDataResult.data; if (wtmDataDict == null) { return(SwitchResult.CoinNotFound); } } // Update WTM coin data with historical averages from local database if opted to var historicalDataList = new List <HistoricalData>(); bool historicalDataUpToDate = false; if (WtmSettings.UseHistoricalAverage) { if (WtmSettings.ApplicationMode == "Client") { //Needs longer timeout for the server might be downloading all coins from whattomine.com var channel = Service.NewStreamChannel(streamServerAddress, TimeSpan.FromSeconds(180)); try { var response = await channel.GetPriceHistoryAsync(new StreamDownloadRequest { Period = WtmSettings.HistoricalAveragePeriod }).ConfigureAwait(false); if (response != null) { var memoryStream = new MemoryStream(); await response.Stream.CopyToAsync(memoryStream); historicalDataList = NetHelper.DeserializeFromStream <List <HistoricalData> >(memoryStream); historicalDataUpToDate = true; } } catch (Exception ex) { logFile.WriteLine($"Failed to obtain historical prices from local server {WtmSettings.ServerName}. " + ex.Message); return(SwitchResult.Error); } finally { NetHelper.CloseChannel(channel); } } else { var result = await UpdatePriceHistory(); if (result == UpdatePriceHistoryResult.Success || result == UpdatePriceHistoryResult.AlreadyUpToDate) { historicalDataList = ReadHistoricalData(WtmSettings.HistoricalAveragePeriod); historicalDataUpToDate = true; } } // Calculate historical prices for wtmDataList if (historicalDataUpToDate) { GetHistoricalAverages(wtmDataDict, historicalDataList); } } // Update WtmLocalData if in server mode if (WtmSettings.ApplicationMode == "Server") { if (wtmDataDict != null && wtmDataDict.Count != 0) { using (var db = new LiteDatabase(Constants.DataBase)) { var collection = db.GetCollection <HistoricalData>(Constants.LightDB_WtmCacheCollection); collection.Delete(LiteDB.Query.All()); collection.Insert(new HistoricalData(DateTime.Now, wtmDataDict)); } } } // Abandon if in server mode and DontSwitchServer is checked if (WtmSettings.ApplicationMode == "Server" && WtmSettings.DontSwitchServer) { return(SwitchResult.NoNeedToSwitch); } if (WtmSettings.ApplicationMode == "Server" && !WtmSettings.DontSwitchServer && thisWorker == null) { logFile.WriteLine("The server cannot switch because it is not listed in any worker table."); return(SwitchResult.ThisPcIsNotListed); } // Calculate profit table for this PC and analize it var profitTables = WhatToMine.CreateProfitTables(wtmDataDict, workersList, (decimal)Workers.PowerCost, WtmSettings, true); var profitTable = profitTables.First(); var currentCoinShortcut = Shortcut.GetCurrentCoin(); // Get current coin from Startup folder .lnk ProfitTableRow maxCoinRow = null; decimal maxProfit = 0; decimal currentProfit = 0; bool nothingChecked = false; WhatToMine.GetProfit(profitTable, currentCoinShortcut, out maxCoinRow, out maxProfit, out currentProfit, out nothingChecked); if (nothingChecked) { string msg = "Nothing to do. Make sure there are actual switchable coins defined in worker."; logFile.WriteLine(msg); return(SwitchResult.NothingToDo); } if (maxProfit == 0) { string msg = $"There is no coin with profit above 0 for {thisPcName}."; logFile.WriteLine(msg); return(SwitchResult.NothingToDo); } //Check profitability and price margin bool currentCoinMatch = currentCoinShortcut?.GetName() == maxCoinRow.Name; bool currentCoinPathMatch = currentCoinShortcut?.Path == maxCoinRow.Path; bool currentPforitIsHigherOrEqual = maxProfit <= currentProfit; bool currentProfitIsWithinMargin = false; if (WtmSettings.PriceMargin > 0) { currentProfitIsWithinMargin = maxProfit <= (currentProfit + (currentProfit * WtmSettings.PriceMargin / 100)); } if (currentPforitIsHigherOrEqual) { string msg; msg = $"No need to switch. {thisPcName} is already set to mine the most profitable coin {currentCoinShortcut?.GetNameAndSymbol()}."; logFile.WriteLine(msg); return(SwitchResult.NoNeedToSwitch); } if (currentProfitIsWithinMargin) { string msg; if (currentCoinMatch && !currentCoinPathMatch) { msg = $"No need to switch. {thisPcName} is set to mine {currentCoinShortcut?.GetNameAndSymbol()} started by \"{currentCoinShortcut?.Path}\". It is less profitable than {maxCoinRow.NameAndSymbol} started by \"{maxCoinRow.Path}\" but the difference is within price margin."; } else { msg = $"No need to switch. {thisPcName} is set to mine {currentCoinShortcut?.GetNameAndSymbol()}. It is less profitable than {maxCoinRow.NameAndSymbol} but the difference is within price margin."; } logFile.WriteLine(msg); return(SwitchResult.NoNeedToSwitch); } // Check if executable path exists if (!File.Exists(maxCoinRow.Path)) { logFile.WriteLine($"{maxCoinRow.Path} - file does not exist on {thisPcName}."); return(SwitchResult.CoinNotFound); } bool startOk = false; // Start miner process flag try { Shortcut.CreateCoinShortcut(maxCoinRow.Name, maxCoinRow.Symbol, maxCoinRow.Algorithm, maxCoinRow.Path, maxCoinRow.Arguments); if (WtmSettings.RestartComputer) { RestartComputerPending = true; } if (WtmSettings.RestartMiner) { // Kill processes from KillList var killResponse = KillProcesses(WtmSettings.KillList); if (!killResponse.success && killResponse.failList != null) { string errorMessage = $"Startup shortcut to mine {maxCoinRow.NameAndSymbol} has been created but some processes could not be killed:"; logFile.WriteLine(errorMessage); foreach (var entry in killResponse.failList) { if (entry != string.Empty) { logFile.WriteLine(entry); } } logFile.WriteLine($"{Environment.MachineName} will restart."); RestartComputerPending = true; SetRegistryKeyValue(Constants.SwitchRegistryKey, "LastSuccess", DateTime.UtcNow.ToString("o")); return(SwitchResult.SwitchedSuccessfully); } if (!System.IO.File.Exists(maxCoinRow.Path)) { logFile.WriteLine($"ERROR: File not found. {maxCoinRow.Path}"); return(SwitchResult.Error); } // Start miner process var startInfo = new ProcessStartInfo(maxCoinRow.Path, maxCoinRow.Arguments); Process process = new Process(); process.StartInfo = startInfo; startOk = process.Start(); if (!startOk) { throw new Exception($"\"{Path.GetFileName(maxCoinRow.Path)}\" failed to start."); } } SetRegistryKeyValue(Constants.SwitchRegistryKey, "LastSuccess", DateTime.UtcNow.ToString("o")); logFile.WriteLine($"Switched to {maxCoinRow.NameAndSymbol} successfully."); return(SwitchResult.SwitchedSuccessfully); } catch (Exception ex) { logFile.WriteLine($"Failed to switch to {maxCoinRow.NameAndSymbol}: {ex.Message}"); if (WtmSettings.RestartMiner && !startOk) { RestartComputerPending = true; logFile.WriteLine($"{Environment.MachineName} will restart."); } return(SwitchResult.Error); } } }
private async Task <int> UpdateVersion(Computer pc, CancellationToken token, int errorCount, int iteration, int jobCount, string appVersion) { pc.SwitchStatus = Computer.OperationStatus.OperationInProgress; pc.UpdateSuccessfull = new TaskCompletionSource <bool>(); var address = ViewModel.BuildServerAddress(pc.Name, Constants.StreamServer); var channel = Service.NewStreamChannel(address, TimeSpan.FromSeconds(60 * 10)); FileStream outputStream = null; try { string appFileName = Helpers.ApplicationPath(); System.IO.FileInfo info = new System.IO.FileInfo(appFileName); outputStream = new FileStream(appFileName, FileMode.Open, FileAccess.Read, FileShare.Read, Service.StreamBuffer, true); FileRequest request = new FileRequest(); request.CallerHostName = Environment.MachineName; request.FileName = info.Name; request.Length = info.Length; request.FileStream = outputStream; var reply = await channel.UpdateApplication(request).WithCancellation(token).ConfigureAwait(false); var awaitCallbackTask = pc.UpdateSuccessfull.Task; await Task.WhenAny(awaitCallbackTask, Task.Delay(1000 * 30)).WithCancellation(token).ConfigureAwait(false); bool callbackResult = false; if (awaitCallbackTask.Status == TaskStatus.RanToCompletion) { callbackResult = awaitCallbackTask.Result; } if (!callbackResult) { throw new Exception($"{pc.Name} has downloaded the new version but failed to report success."); } // Update row colors, green (NotNecessary) - the version is up to date, red (Necessary) - the version is older. if (new Version(appVersion).CompareTo(new Version(pc.Version)) == 1) { pc.UpdateStatus = Computer.OperationStatus.Necessary; } else { pc.UpdateStatus = Computer.OperationStatus.NotNecessary; } } catch (Exception ex) { errorCount++; pc.SwitchStatus = Computer.OperationStatus.Failure; Application.Current.Dispatcher.Invoke(() => { var p = new Paragraph(); p.Inlines.Add(new Run($"{pc.Name}: ").FontWeight(FontWeights.Bold).Color(Colors.Salmon)); p.Inlines.Add(new Run($"Failed to update.\r\n")); p.Inlines.Add(new Run(ex.Message + "\r\n")); NewParagraph = p; }); } finally { NetHelper.CloseChannel(channel); if (outputStream != null) { outputStream.Close(); } ReportTitle = $"Progress: {iteration + 1} of {jobCount}."; } return(errorCount); }
public async Task InitializeInterface() { // Delete registry key left-over var startWithWindows = GetRegistryKeyValue(Constants.RunRegistryKey, Constants.AppName); if (startWithWindows != null && !WtmSettings.StartWithWindows) { DeleteRegistryKeyValue(Constants.RunRegistryKey, Constants.AppName); } ApplyServerSettingsCommand(null); // Start server if app's role is 'Server' NetHelper.Port = WtmSettings.TcpPort; AccessPoinServiceHost = new ServiceHost(typeof(Service)); AccessPoinServiceHost.Open(); string failedToDecrypt = "The encryption is based on machine configuration. " + "If you have copied settings to a different machine, logged on as a different user or changed your Windows password you need to re-enter "; ScanLanCancelSource = new System.Threading.CancellationTokenSource(); var token = ScanLanCancelSource.Token; Func <Task> taskLoadWtmCoins = (async() => { //Load Whattomine available coins if (WtmSettings.ProxyPasswordEncrypted != null && WtmSettings.ProxyPasswordEncrypted != string.Empty) { try { BypassUndo(() => WtmSettings.ProxyPassword = WtmSettings.ProxyPasswordEncrypted.DecryptSecure()); } catch (Exception) { WtmSettings.ProxyPasswordEncrypted = null; string msg = "Failed to decrypt WhatToMine proxy password. " + failedToDecrypt + "the proxy password."; var t = Task.Run(() => MessageBox.Show(msg, "Error", MessageBoxButton.OK, MessageBoxImage.Error)); } } await LoadWtmCoins(token); // Update coins statuses if (WtmCoins != null) { UpdateCoinStatus(); } IsInitializingWtm = false; }); Func <Task> taskLoadYahooCurrencies = (async() => { //Load Yahoo currencies SaveUndoIsEnabled = false; await WtmSettings.GetYahooRates(); SaveUndoIsEnabled = true; }); var tasks = new List <Task>() { taskLoadWtmCoins() }; if (WtmSettings.UseYahooRates) { tasks.Add(taskLoadYahooCurrencies()); } try { await Task.WhenAll(tasks).WithCancellation(token); } catch (Exception ex) { Task <MessageBoxResult> t = null; if (ex.Message != "The operation was canceled.") { t = Task.Run(() => MessageBox.Show("Error while waiting for taskLoadWtmCoins or taskLoadYahooCurrencies.\n" + ex.Message, "", MessageBoxButton.OK, MessageBoxImage.Error)); } } finally { IsInitializingWtm = false; } // Update callback using (RegistryKey key = Microsoft.Win32.Registry.CurrentUser.OpenSubKey(Constants.BaseRegistryKey, true)) { if (key != null) { var callerHostName = key.GetValue("CallerHostName") as string; if (callerHostName != null && callerHostName != string.Empty) { var address = BuildServerAddress(callerHostName, Constants.AccessPoint); var channel = Service.NewChannel(address, TimeSpan.FromSeconds(60)); try { await channel.UpdateApplicationCallback(Environment.MachineName, Helpers.ApplicationVersion()); } catch { } finally { NetHelper.CloseChannel(channel); } key.DeleteValue("CallerHostName"); } } } bool workersExist = File.Exists(Constants.WorkersFile); bool settingsExist = File.Exists(Constants.WtmSettingsFile); if (!workersExist && !settingsExist) { var t = Task.Run(() => MessageBox.Show($"If you're running a fresh copy of {Constants.AppName} please define your workers inside 'Workers' tab and click 'Save' icon.", "Default configuration used", MessageBoxButton.OK, MessageBoxImage.Information)); } else { if (DefaultWorkers) { var t = Task.Run(() => MessageBox.Show($"{Constants.WorkersFile} is missing or corrupt.", "", MessageBoxButton.OK, MessageBoxImage.Warning)); } if (DefaultWtmSettings) { var t = Task.Run(() => MessageBox.Show($"{Constants.WtmSettingsFile} is missing or corrupt. Default settings are used.", "", MessageBoxButton.OK, MessageBoxImage.Warning)); } } // Check if there are any pending jobs in registry bool switchJobIsInProgress = false; bool updatePriceJobIsInProgress = false; string switchTime = string.Empty; string switchLastTime = string.Empty; string updatePriceTime = string.Empty; string updatePriceLastUpdate = string.Empty; using (RegistryKey switchKey = Microsoft.Win32.Registry.CurrentUser.OpenSubKey(Constants.SwitchRegistryKey, true)) using (RegistryKey updatePriceKey = Microsoft.Win32.Registry.CurrentUser.OpenSubKey(Constants.UpdatePriceHistoryRegistryKey, true)) { if ((string)switchKey.GetValue("IsInProgress") == "True") { switchJobIsInProgress = true; } switchTime = (string)switchKey.GetValue("Schedule"); if (switchTime != null && switchTime != string.Empty) { SwitchSchedule = Convert.ToDateTime(switchTime, DateTimeFormatInfo.InvariantInfo).ToLocalTime(); } switchLastTime = (string)switchKey.GetValue("LastUpdate"); if (switchLastTime != null && switchLastTime != string.Empty) { SwitchLastTime = Convert.ToDateTime(switchLastTime, DateTimeFormatInfo.InvariantInfo).ToLocalTime(); } if ((string)updatePriceKey.GetValue("IsInProgress") == "True") { updatePriceJobIsInProgress = true; } updatePriceTime = (string)updatePriceKey.GetValue("Schedule"); if (updatePriceTime != null && updatePriceTime != string.Empty) { HistoricalPricesSchedule = Convert.ToDateTime(updatePriceTime, DateTimeFormatInfo.InvariantInfo).ToLocalTime(); } updatePriceLastUpdate = (string)updatePriceKey.GetValue("LastUpdate"); if (updatePriceLastUpdate != null && updatePriceLastUpdate != string.Empty) { HistoricalPricesLastTime = Convert.ToDateTime(updatePriceLastUpdate, DateTimeFormatInfo.InvariantInfo).ToLocalTime(); } } // Start job if one is still pending after system restart if (switchJobIsInProgress && workersExist) { await SwitchTaskWrapper(); switchTime = string.Empty; } if (updatePriceJobIsInProgress && workersExist) { await UpdatePriceHistoryTaskWrapper(); updatePriceTime = string.Empty; } // Delete Mass Update left-overs if they exist Helpers.DeleteUpdateLeftOvers(); // Check if Switch job has been missed today/this hour if (WtmSettings.AutoSwitch) { if (switchTime != string.Empty) { DateTime schedule = Convert.ToDateTime(switchTime, DateTimeFormatInfo.InvariantInfo); DateTime now = DateTime.Now; DateTime expiryTime = GetSwitchExpiry(schedule); if (schedule < now && now < expiryTime) { await SwitchTaskWrapper(); switchTime = string.Empty; } } } // Check if UpdateHistoricalPrices job has been missed today DateTime updatePriceLastUpdateTime; if (WtmSettings.BackupHistoricalPrices) { if (updatePriceLastUpdate != string.Empty) { updatePriceLastUpdateTime = Convert.ToDateTime(updatePriceLastUpdate, DateTimeFormatInfo.InvariantInfo); DateTime now = DateTime.Now; DateTime historyBackupTime = new DateTime(now.Year, now.Month, now.Day, WtmSettings.HistoryTimeTo.Hour, WtmSettings.HistoryTimeTo.Minute, 0, DateTimeKind.Local); if (now > historyBackupTime && updatePriceLastUpdateTime.Day < now.Day) // Now is past daily schedule and last update had been done before today { await UpdatePriceHistoryTaskWrapper(); updatePriceTime = string.Empty; } } } // Schedule jobs JobManager.UseUtcTime(); if (WtmSettings.AutoSwitch == true && workersExist) { Debug.WriteLine(DateTime.Now + " Scheduling a Switch task at startup."); if (switchTime != string.Empty) { ResetScheduledJob(JobType.Switch, switchTime); } else { ResetScheduledJob(JobType.Switch); } } if (WtmSettings.BackupHistoricalPrices == true && workersExist) { if (updatePriceTime != string.Empty) { ResetScheduledJob(JobType.UpdatePriceHistory, updatePriceTime); } else { ResetScheduledJob(JobType.UpdatePriceHistory); } } UpdateNextJobStatus(); }
private async void StartCommand(object obj) { SwitchIsInProgress = true; ManualSwitchCancelSource = new CancellationTokenSource(); var token = ManualSwitchCancelSource.Token; var taskList = new List <Task>(); var jobCount = ProfitTables.Sum(x => x.Computers.Count); var failList = new List <ProfitTable>(); FlowDocument report = new FlowDocument(); int errorCount = 0; await Task.Run(() => { ReportTitle = $"Progress: 0 of {jobCount}."; int i = 1; foreach (var table in ProfitTables) { var currentCoinRow = table.ProfitList[0]; foreach (var pc in table.Computers) { pc.RestartStatus = pc.Restart ? Computer.OperationStatus.OperationInProgress : Computer.OperationStatus.Indeterminate; pc.SwitchStatus = pc.Switch ? Computer.OperationStatus.OperationInProgress : Computer.OperationStatus.Indeterminate; Func <Task> function = (async() => { var serverAddress = "net.tcp://" + pc.Name + ":" + NetHelper.Port + Constants.AccessPoint; var channel = Service.NewChannel(serverAddress, TimeSpan.FromSeconds(10)); try { try { if (pc.Switch) { bool switchResult = await channel.SetCurrentCoinAsync( currentCoinRow.Name, currentCoinRow.Symbol, currentCoinRow.Algorithm, currentCoinRow.Path, currentCoinRow.Arguments).WithCancellation(token); if (switchResult) { pc.SwitchStatus = Computer.OperationStatus.Success; } else { pc.SwitchStatus = Computer.OperationStatus.Failure; } } } catch (Exception ex) { errorCount++; pc.SwitchStatus = Computer.OperationStatus.Failure; Application.Current.Dispatcher.Invoke(() => { var p = new Paragraph(); p.Inlines.Add(new Run($"{table.Name}:").FontWeight(FontWeights.Bold).Color(Colors.Salmon)); p.Inlines.Add(new Run($"{pc.Name} Failed to switch to {currentCoinRow.NameAndSymbol}.\r\n")); p.Inlines.Add(new Run(ex.Message + "\r\n")); NewParagraph = p; }); if (pc.Restart) { pc.RestartStatus = Computer.OperationStatus.Failure; } else { pc.RestartStatus = Computer.OperationStatus.NotPossible; } return; } try { if (pc.Restart) { // Schedule delayed restart if pc is localhost if (string.Equals(pc.Name, Environment.MachineName, StringComparison.CurrentCultureIgnoreCase)) { RestartPending = true; pc.RestartStatus = Computer.OperationStatus.Pending; } else { bool restartResult = await channel.RestartComputerAsync(5).WithCancellation(token); if (restartResult) { pc.RestartStatus = Computer.OperationStatus.Success; } else { pc.RestartStatus = Computer.OperationStatus.Failure; } } } } catch (Exception ex) { errorCount++; pc.RestartStatus = Computer.OperationStatus.Failure; Application.Current.Dispatcher.Invoke(() => { var p = new Paragraph(); p.Inlines.Add(new Run($"{table.Name}:").FontWeight(FontWeights.Bold).Color(Colors.Salmon)); p.Inlines.Add(new Run($"{pc.Name} Failed to restart.\r\n")); p.Inlines.Add(new Run(ex.Message + "\r\n")); NewParagraph = p; }); } } finally { NetHelper.CloseChannel(channel); ReportTitle = $"Progress: {i} of {jobCount}."; i++; } }); // This line blocks UI upon DNS lookup of a non-existing or disconnected machine. // That is why the entire block is wrapped into Task.Run(). Task task = function(); taskList.Add(task); } } }); await Task.WhenAll(taskList); if (errorCount == 0) { ReportTitle = "Report:"; NewParagraph = new Paragraph(new Run("Operation has finished successfully.")); } else { ReportTitle = "Error report:"; } SwitchIsInProgress = false; SwitchIsFinished = true; }