List <ProcessListEntry> GetProcessList(IProcessListRequest request) { // TODO: Use single cancelable task for both actions try { var enableSshAction = _actionRecorder.CreateToolAction(ActionType.GameletEnableSsh); if (!_cancelableTaskFactory .Create(TaskMessages.EnablingSSH, async _ => await _sshManager.EnableSshAsync(Gamelet, enableSshAction)) .RunAndRecord(enableSshAction)) { return(new List <ProcessListEntry>()); } } catch (Exception e) when(e is SshKeyException || e is CloudException) { Trace.WriteLine(e.ToString()); _dialogUtil.ShowError(ErrorStrings.FailedToEnableSsh(e.Message), e.ToString()); return(new List <ProcessListEntry>()); } // TODO: Handle ProcessException var processListAction = _actionRecorder.CreateToolAction(ActionType.ProcessList); var queryProcessesTask = _cancelableTaskFactory.Create( "Querying instance processes...", async() => await request.GetBySshAsync(new SshTarget(Gamelet))); queryProcessesTask.RunAndRecord(processListAction); return(queryProcessesTask.Result); }
public IVsiGameLaunch CreateLaunch(LaunchParams launchParams) { IAction action = _actionRecorder.CreateToolAction(ActionType.GameLaunchCreate); CreateLaunchResult launchRes = null; ICancelableTask launchTask = _cancelableTaskFactory.Create( TaskMessages.LaunchingGame, async task => { launchRes = await CreateLaunchAsync(launchParams, task, action); }); try { if (!launchTask.RunAndRecord(action)) { Trace.WriteLine("Launching a game has been canceled by user."); return(null); } } catch (ConfigurationException e) { _dialogUtil.ShowError(e.Message); return(null); } catch (CloudException e) { string message = $"{ErrorStrings.CouldNotStartTheGame}{Environment.NewLine}" + $"{e.Message}{Environment.NewLine}{Environment.NewLine}{ErrorStrings.SeeLogs}"; _dialogUtil.ShowError(message); return(null); } if (!string.IsNullOrWhiteSpace(launchRes.WarningMessage)) { _dialogUtil.ShowWarning(launchRes.WarningMessage); } if (!string.IsNullOrWhiteSpace(launchRes.SdkCompatibilityMessage)) { bool showAgain = _dialogUtil.ShowOkNoMoreDisplayWarning( launchRes.SdkCompatibilityMessage, new[] { "Tools", "Options", "Stadia SDK", "Game launch", "SDK incompatibility warning" }); if (!showAgain) { _vsiService.Options.AddSdkVersionsToHide(launchParams.GameletSdkVersion, launchParams.SdkVersion, launchParams.GameletName); } } return(launchRes.GameLaunch); }
public async Task <bool> ShouldAttachToIncosistentCoreFileAsync(DumpReadWarning warning) { await _taskContext.Factory.SwitchToMainThreadAsync(); string dialogMessage = null; string dialogTitle = null; switch (warning) { case DumpReadWarning.FileDoesNotExist: _dialogUtil.ShowError(ErrorStrings.CoreFileDoesNotExist); return(false); case DumpReadWarning.ElfHeaderIsCorrupted: dialogTitle = ErrorStrings.DialogTitleWarning; dialogMessage = ErrorStrings.CoreFileCorruptedWarningMessage; break; case DumpReadWarning.FileIsTruncated: dialogTitle = ErrorStrings.DialogTitleWarning; dialogMessage = ErrorStrings.CoreFileTruncatedWarningMessage; break; case DumpReadWarning.ExecutableBuildIdMissing: dialogTitle = ErrorStrings.CoreAttachBuildIdMissingWarningTitle; dialogMessage = ErrorStrings.CoreAttachBuildIdMissingWarningMessage; break; case DumpReadWarning.None: break; } return(_dialogUtil.ShowYesNoWarning(dialogMessage, dialogTitle)); }
List <string> ReadMountsContentOrDefault(Gamelet gamelet, ActionRecorder actionRecorder) { List <string> content = new List <string>(); ICancelableTask getMountsTask = _cancelableTaskFactory.Create(TaskMessages.CheckingMountInfo, async _ => { content = await _remoteCommand.RunWithSuccessCapturingOutputAsync( new SshTarget(gamelet), ReadMountsCmd) ?? new List <string>(); }); try { getMountsTask.RunAndRecord(actionRecorder, ActionType.GameletReadMounts); return(content); } catch (ProcessException e) { Trace.WriteLine($"Error reading /proc/mounts file: {e.Message}"); _dialogUtil.ShowError(ErrorStrings.FailedToStartRequiredProcess(e.Message), e.ToString()); return(content); } finally { string joinedContent = string.Join("\n\t", content); Trace.WriteLine($"Gamelet /proc/mounts:{Environment.NewLine}{joinedContent}"); } }
/// <summary> /// Enable SSH for communication with the gamelet. /// </summary> bool EnableSsh(Gamelet gamelet) { try { IAction action = _actionRecorder.CreateToolAction(ActionType.GameletEnableSsh); ICancelableTask enableSshTask = _cancelableTaskFactory.Create(TaskMessages.EnablingSSH, async _ => { await _sshManager.EnableSshAsync(gamelet, action); }); return(enableSshTask.RunAndRecord(action)); } catch (Exception e) when(e is CloudException || e is SshKeyException) { Trace.Write($"Received exception while enabling ssh.\n{e}"); _dialogUtil.ShowError(ErrorStrings.FailedToEnableSsh(e.Message), e.ToString()); return(false); } }
public int AddPort(IDebugPortRequest2 request, out IDebugPort2 port) { var debugSessionMetrics = new DebugSessionMetrics(_metrics); debugSessionMetrics.UseNewDebugSessionId(); var actionRecorder = new ActionRecorder(debugSessionMetrics); port = null; if (request.GetPortName(out string gameletIdOrName) != VSConstants.S_OK) { return(VSConstants.E_FAIL); } var action = actionRecorder.CreateToolAction(ActionType.GameletGet); var gameletClient = _gameletClientFactory.Create(_cloudRunner.Intercept(action)); var gameletTask = _cancelableTaskFactory.Create( "Querying instance...", async() => await gameletClient.LoadByNameOrIdAsync(gameletIdOrName)); try { gameletTask.RunAndRecord(action); } catch (CloudException e) { Trace.WriteLine(e.ToString()); _dialogUtil.ShowError(e.Message); return(VSConstants.S_OK); } var debugPort = _debugPortFactory.Create(gameletTask.Result, this, debugSessionMetrics.DebugSessionId); _ports.Add(debugPort); port = debugPort; return(VSConstants.S_OK); }
public void TestClearLogsFailsReturnsFalse() { _remoteCommand .When(m => m.RunWithSuccessAsync(new SshTarget(_gamelet1), GameletSelectorLegacyFlow.ClearLogsCmd)) .Do(c => { throw new ProcessException("Oops!"); }); Gamelet gamelet; var result = _gameletSelector.TrySelectAndPrepareGamelet(_targetPath, _deploy, new List <Gamelet> { _gamelet1 }, null, _devAccount, out gamelet); Assert.That(result, Is.False); _dialogUtil.ShowError(Arg.Any <string>(), Arg.Any <string>()); AssertMetricRecorded(DeveloperEventType.Types.Type.VsiGameletsClearLogs, DeveloperEventStatus.Types.Code.ExternalToolUnavailable); }
public bool WaitUntilGameLaunched() { IAction action = _actionRecorder.CreateToolAction(ActionType.GameLaunchWaitForStart); ICancelableTask pollForLaunchStatusTask = _cancelableTaskFactory.Create( TaskMessages.LaunchingGame, async task => await PollForLaunchStatusAsync(task, action)); try { if (!pollForLaunchStatusTask.RunAndRecord(action)) { Trace.WriteLine("Polling for the launch status has been canceled by user."); return(false); } } catch (Exception e) when(e is TimeoutException || e is GameLaunchFailError) { Trace.WriteLine(e.Message); _dialogUtil.ShowError(e.Message); return(false); } return(true); }
public ExitDialogUtil(IDialogUtil dialogUtil, DialogExecutionContext executionContext) { showErrorDialogWithDetails = (message, details) => executionContext(() => dialogUtil.ShowError(message, details)); showErrorDialog = message => executionContext(() => dialogUtil.ShowError(message)); }
void AttachClick(object sender, RoutedEventArgs e) { _taskContext.ThrowIfNotOnMainThread(); // Figure out core file path CoreListEntry?coreListEntry = null; if (TabControl.SelectedContent == GameletGroupBox) { coreListEntry = (CoreListEntry?)CoreList.SelectedItem; if (coreListEntry == null) { _dialogUtil.ShowError(ErrorStrings.NoCoreFileSelected); return; } } string coreFilePath = null; bool deleteAfter = false; if (TabControl.SelectedContent == LocalGroupBox) { coreFilePath = LocalCorePathBox.Text; } else if (TabControl.SelectedContent == GameletGroupBox) { var tempPath = Path.GetTempPath(); try { _cancelableTaskFactory .Create(TaskMessages.DownloadingCoreFile, async task => await _remoteFile.GetAsync(new SshTarget(_instance), "/usr/local/cloudcast/core/" + coreListEntry?.Name, tempPath, task)) .RunAndRecord(_actionRecorder, ActionType.CrashDumpDownload); } catch (ProcessException ex) { Trace.WriteLine($"Failed to download core file.{Environment.NewLine}" + $"{ex}"); _dialogUtil.ShowError(ErrorStrings.FailedToDownloadCore(ex.Message), ex.ToString()); return; } coreFilePath = Path.Combine(tempPath, coreListEntry?.Name); deleteAfter = true; } if (string.IsNullOrEmpty(coreFilePath)) { ShowMessage(ErrorStrings.FailedToRetrieveCoreFilePath); return; } // Check if we have a debugger (should always be the case). var vsDebugger = (IVsDebugger4)ServiceProvider.GlobalProvider.GetService(typeof(IVsDebugger)); if (vsDebugger == null) { ShowMessage(ErrorStrings.FailedToStartDebugger); return; } try { _actionRecorder.RecordToolAction(ActionType.CrashDumpAttach, delegate { _taskContext.ThrowIfNotOnMainThread(); VsDebugTargetInfo4[] debugTargets = new VsDebugTargetInfo4[1]; debugTargets[0].dlo = (uint)DEBUG_LAUNCH_OPERATION.DLO_CreateProcess; // LaunchDebugTargets4() throws an exception if |bstrExe| and |bstrCurDir| // are empty. Use core path and temp directory as placeholders. debugTargets[0].bstrExe = coreFilePath; debugTargets[0].bstrCurDir = Path.GetTempPath(); var parameters = _paramsFactory.Create(); parameters.CoreFilePath = coreFilePath; parameters.DebugSessionId = _debugSessionMetrics.DebugSessionId; parameters.DeleteCoreFile = deleteAfter; debugTargets[0].bstrOptions = _paramsFactory.Serialize(parameters); debugTargets[0].guidLaunchDebugEngine = YetiConstants.DebugEngineGuid; VsDebugTargetProcessInfo[] processInfo = new VsDebugTargetProcessInfo[debugTargets.Length]; vsDebugger.LaunchDebugTargets4(1, debugTargets, processInfo); }); } catch (COMException except) { Trace.WriteLine($"Failed to start debugger: {except}"); // Both DebugEngine and Visual Studio already show error dialogs if DebugEngine // has to abort while it's attaching, no need to show another dialog in that case. if (except.ErrorCode != VSConstants.E_ABORT) { _dialogUtil.ShowError(ErrorStrings.FailedToStartDebugger, except.ToString()); } } finally { Close(); } }