/// <summary> /// This function can be called twice. /// /// First time, it simply check connectivity with a short timeout. /// If it does not connect, there are two possibilities. /// 1) Firewall was just enabled, let's check for longer time. /// 2) Remote powershell is disabled on target machine etc. /// /// Since we are not clear which is the case, we return null. It will then show /// the dialog UI to ask user to choose if he wants to retry testing connectivity. /// /// If the user choose yes for retry, this method is called the second time. /// The second time, we keep testing connectivity with a longer period of time. /// /// Both times, /// if remote powershell can be connected, go to install, start remote debugger step. /// /// If it is determined it won't connect successfully, /// go to a help page with a link to our documentation. /// </summary> protected override async Task <IAttachDebuggerStep> GetNextStepAsync() { SetStage(Stage.CheckingConnectivity); var port = Context.RemotePowerShellPort; int waitTime = port.WaitForFirewallRuleTimeInSeconds(); bool connected = waitTime > 0 && _askedToCheckConnectivityLater ? // This is the second time, check connectivity with a longer wait time. await ConnectivityTestUntillTimeoutAsync(waitTime) : // This is the first time, we don't check "waitTime", test connectivity anyhow. await port.ConnectivityTestAsync(CancelToken); if (connected) { return(InstallStartRemoteToolStepViewModel.CreateStep(Context)); } // else: not connected // If this is first time call, then check if firewall was just enabled. if (!_askedToCheckConnectivityLater && port.WaitForFirewallRuleTimeInSeconds() > 0) { SetStage(Stage.AskToCheckConnectivityLater); _askedToCheckConnectivityLater = true; return(null); } else { return(HelpStepViewModel.CreateStep(Context)); } }
public override Task <IAttachDebuggerStep> OnStartAsync() { ProgressMessage = Resources.AttachDebuggerConnectingProgressMessage; IsCancelButtonEnabled = false; if (!WindowsCredentialManager.Write( Context.PublicIp, Context.Credential.User, Context.Credential.Password, WindowsCredentialManager.CredentialType.DomainPassword, WindowsCredentialManager.CredentialPersistence.Session)) { Debug.WriteLine($"Failed to save credential for {Context.PublicIp}, last error is {Marshal.GetLastWin32Error()}"); // It's OKay to continue, the Debugger2 will prompt UI to ask for credential. } if (!GetAllProcessesList()) { return(Task.FromResult <IAttachDebuggerStep>(HelpStepViewModel.CreateStep(Context))); } else if (Processes.Count() == 1) { return(Task.FromResult(Attach())); } else { EnableSelection(); // Returns null so that the user stays on the step to pick a process. return(Task.FromResult <IAttachDebuggerStep>(null)); } }
/// <summary> /// Creates the step that asks user to open online documentation. /// </summary> public static HelpStepViewModel CreateStep(AttachDebuggerContext context) { var content = new HelpStepContent(); var step = new HelpStepViewModel(content, context); content.DataContext = step; return(step); }
private IAttachDebuggerStep Attach() { IsListVisible = false; ProgressMessage = String.Format( Resources.AttachDebuggerAttachingProcessMessageFormat, SelectedProcess.Name); var startTimestamp = DateTime.Now; try { if (SelectedEngine == s_detectEngineTypeItemName) { SelectedProcess.Process.Attach(); } else { SelectedProcess.Process.Attach2(SelectedEngine); } } catch (COMException ex) { EventsReporterWrapper.ReportEvent( RemoteDebuggerAttachedEvent.Create(CommandStatus.Failure)); Debug.WriteLine($"Attach debugger got exception. {ex}"); UserPromptUtils.ErrorPrompt( message: String.Format(Resources.AttachDebuggerAttachErrorMessageFormat, SelectedProcess.Name), title: Resources.UiDefaultPromptTitle); ResetDefaultSelection(); return(HelpStepViewModel.CreateStep(Context)); } EventsReporterWrapper.ReportEvent(RemoteDebuggerAttachedEvent.Create( CommandStatus.Success, DateTime.Now - startTimestamp)); Context.DialogWindow.Close(); return(null); }
public override async Task <IAttachDebuggerStep> OnStartAsync() { IsCancelButtonEnabled = true; ProgressMessage = Resources.AttachDebuggerInstallSetupProgressMessage; bool installed = false; var startTimestamp = DateTime.Now; // The following try catch is for adding Analytics in failure case. try { installed = await _installer.Install(CancelToken); } catch (PowerShellFailedToConnectException) { UserPromptUtils.ErrorPrompt( message: Resources.AttachDebuggerConnectionFailedMessage, title: Resources.UiDefaultPromptTitle); } catch (Exception ex) when(!ErrorHandlerUtils.IsCriticalException(ex)) { Debug.WriteLine($"{ex}"); UserPromptUtils.ErrorPrompt( message: Resources.AttachDebuggerInstallerError, title: Resources.UiDefaultPromptTitle, errorDetails: ex.Message); } if (installed) { EventsReporterWrapper.ReportEvent(RemoteDebuggerRemoteToolsInstalledEvent.Create( CommandStatus.Success, DateTime.Now - startTimestamp)); } else if (!CancelToken.IsCancellationRequested) { EventsReporterWrapper.ReportEvent( RemoteDebuggerRemoteToolsInstalledEvent.Create(CommandStatus.Failure)); } if (installed) { // Reset start time to measure performance of starting remote tools startTimestamp = DateTime.Now; RemoteToolSession session; // The following try catch is for adding analytics where there is exception try { session = new RemoteToolSession( Context.PublicIp, Context.Credential.User, Context.Credential.Password, GoogleCloudExtensionPackage.Instance.SubscribeClosingEvent, GoogleCloudExtensionPackage.Instance.UnsubscribeClosingEvent); } catch (Exception ex) when(!ErrorHandlerUtils.IsCriticalException(ex)) { EventsReporterWrapper.ReportEvent( RemoteDebuggerRemoteToolsStartedEvent.Create(CommandStatus.Failure)); throw; } ProgressMessage = String.Format( Resources.AttachDebuggerTestConnectPortMessageFormat, Context.DebuggerPort.Description, Context.PublicIp, Context.DebuggerPort.PortInfo.Port); Stopwatch watch = Stopwatch.StartNew(); while (!CancelToken.IsCancellationRequested && watch.Elapsed < s_waitConnectionTimeout && !session.IsStopped) { if (await Context.DebuggerPort.ConnectivityTest(CancelToken)) { EventsReporterWrapper.ReportEvent(RemoteDebuggerRemoteToolsStartedEvent.Create( CommandStatus.Success, DateTime.Now - startTimestamp)); return(ListProcessStepViewModel.CreateStep(Context)); } await Task.Delay(500); } EventsReporterWrapper.ReportEvent( RemoteDebuggerRemoteToolsStartedEvent.Create(CommandStatus.Failure)); } return(HelpStepViewModel.CreateStep(Context)); }