bool LaunchProcesses(List <ProcessStartData> processes, string name) { if (processManager == null) { processManager = new ProcessManager(); processManager.OnProcessExit += (processName, exitCode) => StopWithException(new ProcessExecutionException( $"{processName} exited with exit code {exitCode}", exitCode)); } foreach (var item in processes) { try { LaunchYetiProcess(item); } catch (ProcessException e) { Trace.WriteLine($"Failed to start {item.Name}: {e.Message}"); dialogUtil.ShowError(ErrorStrings.FailedToStartRequiredProcess(e.Message), e.ToString()); return(false); } } Trace.WriteLine($"Manager successfully started all {name} processes"); return(true); }
async Task CustomCommandAsync(IAsyncProject project, Gamelet gamelet, DataRecorder record, string command) { var startInfo = new ProcessStartInfo { FileName = Path.Combine(Environment.SystemDirectory, YetiConstants.Command), Arguments = $"/C \"{command}\"", WorkingDirectory = await project.GetAbsoluteRootPathAsync(), }; startInfo.EnvironmentVariables[GgpInstanceIdName] = gamelet.Id; Stopwatch stopwatch = Stopwatch.StartNew(); using (IProcess process = _managedProcessFactory.CreateVisible(startInfo, int.MaxValue)) { try { await process.RunToExitWithSuccessAsync(); record.CustomDeploy(stopwatch.ElapsedMilliseconds, DataRecorder.NoError); } catch (ProcessException e) { Trace.WriteLine("Error running custom deploy command: " + e); record.CustomDeploy(stopwatch.ElapsedMilliseconds, e); throw new DeployException( ErrorStrings.ErrorRunningCustomDeployCommand(e.Message), e); } } }
void OpenLogs(object sender, RoutedEventArgs e) { var path = "<Invalid>"; try { path = YetiLog.CurrentLogFile; if (!File.Exists(path)) { path = Path.GetDirectoryName(path); } Process.Start(path); } catch (InvalidOperationException ex) { Trace.WriteLine(ex); LogsLink.Text = ErrorStrings.FailedToOpenLogsBecauseLoggingNotInitialized; } catch (Exception ex) when(ex is Win32Exception || ex is FileNotFoundException) { Trace.WriteLine(ex); LogsLink.Text = ErrorStrings.FailedToOpenLogsBecauseLogFileMayNotExist(path); } }
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}"); } }
async Task DeployToTargetAsync(DataRecorder record, ICancelable task, SshTarget target, string localPath, string remotePath, bool force = false) { Stopwatch stopwatch = Stopwatch.StartNew(); try { BinarySignatureCheck.Types.Result signatureCheck = force ? BinarySignatureCheck.Types.Result.AlwaysCopy : BinarySignatureCheck.Types.Result.YesCopy; record.SetCopyAttempted(true); record.BinarySize(FileUtil.GetFileSize(localPath, _fileSystem)); record.SignatureCheckResult(signatureCheck); record.DeploymentMode(); await _remoteFile.SyncAsync(target, localPath, remotePath, task, force); record.CopyBinary(stopwatch.ElapsedMilliseconds, DataRecorder.NoError); } catch (ProcessException exception) { record.CopyBinary(stopwatch.ElapsedMilliseconds, exception); throw new DeployException( ErrorStrings.FailedToDeployExecutable(exception.Message), exception); } }
async Task SetRemoteExecutableBitAsync(SshTarget target, string remoteTargetPath, DataRecorder record) { try { await _remoteCommand.RunWithSuccessAsync(target, "chmod a+x " + remoteTargetPath); record.Chmod(DataRecorder.NoError); } catch (ProcessException e) { Trace.WriteLine("Error setting executable permissions: " + e.ToString()); record.Chmod(e); throw new DeployException(ErrorStrings.FailedToSetExecutablePermissions(e.Message), e); } }
/// <summary> /// Load the application given a string representing the app id or name. /// </summary> /// <exception cref="InvalidStateException">Thrown if the application doesn't exist /// </exception> /// <exception cref="ConfigurationException">Thrown if applicationNameOrId is null /// or empty</exception> async Task <Application> LoadApplicationAsync(ICloudRunner runner, string applicationNameOrId) { if (string.IsNullOrEmpty(applicationNameOrId)) { throw new ConfigurationException(ErrorStrings.NoApplicationConfigured); } var application = await _applicationClientFactory.Create(runner) .LoadByNameOrIdAsync(applicationNameOrId); if (application == null) { throw new InvalidStateException( ErrorStrings.FailedToRetrieveApplication(applicationNameOrId)); } return(application); }
public DetailsDialog(string title, string message, string details, bool dontShowAgainButton, string[] dontShowAgainSettingPath = null) { InitializeComponent(); Title = title; Message.Text = message; if (!string.IsNullOrEmpty(details)) { Details.Text = details; } else { DetailsExpander.Visibility = Visibility.Collapsed; } DontShowAgain.Visibility = dontShowAgainButton ? Visibility.Visible : Visibility.Hidden; if (dontShowAgainSettingPath != null) { DontShowAgain.ToolTip = ErrorStrings.DontShowAgainSettingHint(dontShowAgainSettingPath); } }
/// <summary> /// Load a test account given the organization id, project id and test account /// (Stadia Name). Returns null if the test account is empty or null. /// </summary> /// <exception cref="ConfigurationException">Thrown if the given test account doesn't exist /// or if there is more than one test account with the given name. /// </exception> async Task <TestAccount> LoadTestAccountAsync(ICloudRunner runner, string organizationId, string projectId, string testAccount) { if (string.IsNullOrEmpty(testAccount)) { return(null); } var testAccounts = await _testAccountClientFactory.Create(runner) .LoadByIdOrGamerTagAsync(organizationId, projectId, testAccount); if (testAccounts.Count == 0) { throw new ConfigurationException(ErrorStrings.InvalidTestAccount(testAccount)); } if (testAccounts.Count > 1) { throw new ConfigurationException( ErrorStrings.MoreThanOneTestAccount(testAccounts[0].GamerTagName)); } return(testAccounts[0]); }
public async Task <IReadOnlyList <IDebugLaunchSettings> > QueryDebugTargetsAsync( IAsyncProject project, DebugLaunchOptions launchOptions) { try { // Make sure we can find the target executable. var targetPath = await project.GetTargetPathAsync(); if (!_fileSystem.File.Exists(targetPath)) { Trace.WriteLine($"Unable to find target executable: {targetPath}"); _dialogUtil.ShowError(ErrorStrings.UnableToFindTargetExecutable(targetPath)); return(new IDebugLaunchSettings[] { }); } _metrics.UseNewDebugSessionId(); var actionRecorder = new ActionRecorder(_metrics); var targetFileName = await project.GetTargetFileNameAsync(); var gameletCommand = (targetFileName + " " + await project.GetGameletLaunchArgumentsAsync()).Trim(); var launchParams = new LaunchParams() { Cmd = gameletCommand, RenderDoc = await project.GetLaunchRenderDocAsync(), Rgp = await project.GetLaunchRgpAsync(), SurfaceEnforcementMode = await project.GetSurfaceEnforcementAsync(), VulkanDriverVariant = await project.GetVulkanDriverVariantAsync(), QueryParams = await project.GetQueryParamsAsync(), Endpoint = await project.GetEndpointAsync() }; if (_sdkVersion != null && !string.IsNullOrEmpty(_sdkVersion.ToString())) { launchParams.SdkVersion = _sdkVersion.ToString(); } if (!TrySetupQueries(project, actionRecorder, out SetupQueriesResult setupQueriesResult)) { return(new IDebugLaunchSettings[] { }); } launchParams.ApplicationName = setupQueriesResult.Application.Name; launchParams.ApplicationId = setupQueriesResult.Application.Id; if (setupQueriesResult.TestAccount != null) { launchParams.TestAccount = setupQueriesResult.TestAccount.Name; launchParams.TestAccountGamerName = setupQueriesResult.TestAccount.GamerStadiaName; } DeployOnLaunchSetting deployOnLaunchAsync = await project.GetDeployOnLaunchAsync(); launchParams.Account = _credentialManager.LoadAccount(); // TODO: Enable PlayerEndpoint Launches for non-internal usage in VS. if (launchParams.Endpoint == StadiaEndpoint.PlayerEndpoint && launchParams.Account != null && !launchParams.Account.EndsWith("@sparklingsunset.com") && !launchParams.Account.EndsWith("@subtlesunset.com")) { throw new NotImplementedException( "Player Endpoints are not yet supported, please select " + "Test Client in the Project Properties instead."); } // TODO: Enable launch on any endpoint for external accounts. if (launchParams.Endpoint == StadiaEndpoint.AnyEndpoint && launchParams.Account != null && !launchParams.Account.EndsWith("@sparklingsunset.com") && !launchParams.Account.EndsWith("@subtlesunset.com")) { throw new NotImplementedException( "Launch on any player endpoint is not supported yet, please select " + "another endpoint in the Project Properties instead."); } bool launchGameApiEnabled = _yetiVsiService.Options.LaunchGameApiFlow == LaunchGameApiFlow.ENABLED; IGameletSelector gameletSelector = _gameletSelectorFactory.Create(launchGameApiEnabled, actionRecorder); if (!gameletSelector.TrySelectAndPrepareGamelet( targetPath, deployOnLaunchAsync, setupQueriesResult.Gamelets, setupQueriesResult.TestAccount, launchParams.Account, out Gamelet gamelet)) { return(new IDebugLaunchSettings[] { }); } launchParams.GameletName = gamelet.Name; launchParams.PoolId = gamelet.PoolId; launchParams.GameletSdkVersion = gamelet.GameletVersions.DevToolingVersion; launchParams.GameletEnvironmentVars = await project.GetGameletEnvironmentVariablesAsync(); // Prepare for debug launch using these settings. var debugLaunchSettings = new DebugLaunchSettings(launchOptions); debugLaunchSettings.Environment["PATH"] = await project.GetExecutablePathAsync(); debugLaunchSettings.LaunchOperation = DebugLaunchOperation.CreateProcess; debugLaunchSettings.CurrentDirectory = await project.GetAbsoluteRootPathAsync(); if (!launchOptions.HasFlag(DebugLaunchOptions.NoDebug)) { var parameters = _paramsFactory.Create(); parameters.TargetIp = new SshTarget(gamelet).GetString(); parameters.DebugSessionId = _metrics.DebugSessionId; debugLaunchSettings.Options = _paramsFactory.Serialize(parameters); } IAction action = actionRecorder.CreateToolAction(ActionType.RemoteDeploy); bool isDeployed = _cancelableTaskFactory.Create( TaskMessages.DeployingExecutable, async task => { await _remoteDeploy.DeployGameExecutableAsync( project, new SshTarget(gamelet), task, action); task.Progress.Report(TaskMessages.CustomDeployCommand); await _remoteDeploy.ExecuteCustomCommandAsync(project, gamelet, action); }).RunAndRecord(action); if (!isDeployed) { return(new IDebugLaunchSettings[] { }); } if (launchOptions.HasFlag(DebugLaunchOptions.NoDebug)) { if (_gameLauncher.LaunchGameApiEnabled || launchParams.Endpoint == StadiaEndpoint.PlayerEndpoint || launchParams.Endpoint == StadiaEndpoint.AnyEndpoint) { IVsiGameLaunch launch = _gameLauncher.CreateLaunch(launchParams); if (launch != null) { debugLaunchSettings.Arguments = _launchCommandFormatter.CreateWithLaunchName( launchParams, launch.LaunchName); } else { Trace.WriteLine("Unable to retrieve launch name from the launch api."); return(new IDebugLaunchSettings[] { }); } } else { debugLaunchSettings.Arguments = _launchCommandFormatter.CreateFromParams(launchParams); } debugLaunchSettings.Executable = Path.Combine(Environment.SystemDirectory, YetiConstants.Command); debugLaunchSettings.LaunchOptions = DebugLaunchOptions.NoDebug | DebugLaunchOptions.MergeEnvironment; } else { if (_yetiVsiService.DebuggerOptions[DebuggerOption.SKIP_WAIT_LAUNCH] == DebuggerOptionState.DISABLED) { launchParams.Debug = true; } // TODO: This should really be the game_client executable, since // the args we pass are for game_client as well. We just need to find another // way to pass the game executable. debugLaunchSettings.Executable = targetPath; debugLaunchSettings.LaunchDebugEngineGuid = YetiConstants.DebugEngineGuid; debugLaunchSettings.Arguments = _launchCommandFormatter.EncodeLaunchParams(launchParams); debugLaunchSettings.LaunchOptions = DebugLaunchOptions.MergeEnvironment; } return(new IDebugLaunchSettings[] { debugLaunchSettings }); } catch (Exception e) { Trace.WriteLine(e.ToString()); _dialogUtil.ShowError(e.Message, e.ToString()); return(new IDebugLaunchSettings[] { }); } }