diff --git a/src/Extension/RemoteDebuggerLauncher/PackageConstants.cs b/src/Extension/RemoteDebuggerLauncher/PackageConstants.cs index 22741ae..705652e 100644 --- a/src/Extension/RemoteDebuggerLauncher/PackageConstants.cs +++ b/src/Extension/RemoteDebuggerLauncher/PackageConstants.cs @@ -181,13 +181,18 @@ public static class SecureShell public const string DefaultKnownHostsFileName = "known_hosts"; /// SSH key scanner arguments. - public const string KeyScanArguments = "-4 -p {1} {0}"; + /// No space after {2} because SshForceIPv4 includes a trailing space. + public const string KeyScanArguments = "{2}-p {1} {0}"; + + /// Argument for SSH to force IPv4 usage. + public const string SshForceIPv4 = "-4 "; /// SSH executable. public const string SshExecutable = "ssh.exe"; /// The SSH arguments to add server fingerprint to known_hosts file. - public const string SshArguments = "{0}@{1} -p {2} -i \"{3}\" \"echo DONE\""; + /// No space after {4} because SshForceIPv4 includes a trailing space. + public const string SshArguments = "{0}@{1} {4}-p {2} -i \"{3}\" \"echo DONE\""; /// HTTPS Developer Certificate name. public const string HttpsCertificateName = "DevCert.pfx"; diff --git a/src/Extension/RemoteDebuggerLauncher/RemoteOperations/SecureShellKeySetupService.cs b/src/Extension/RemoteDebuggerLauncher/RemoteOperations/SecureShellKeySetupService.cs index bb18930..165e6e4 100644 --- a/src/Extension/RemoteDebuggerLauncher/RemoteOperations/SecureShellKeySetupService.cs +++ b/src/Extension/RemoteDebuggerLauncher/RemoteOperations/SecureShellKeySetupService.cs @@ -11,6 +11,7 @@ using System.IO; using System.Text; using System.Threading.Tasks; +using Microsoft.VisualStudio.Shell; using Microsoft.VisualStudio.Threading; using RemoteDebuggerLauncher.Infrastructure; using Renci.SshNet; @@ -106,7 +107,7 @@ public async Task AuthorizeKeyAsync(SecureShellKeySetupSettings settings) var defaultKeysFolder = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), PackageConstants.SecureShell.DefaultKeyPairFolder); var knownHostsFilePath = Path.Combine(defaultKeysFolder, PackageConstants.SecureShell.DefaultKnownHostsFileName); - var arguments = string.Format(PackageConstants.SecureShell.KeyScanArguments, settings.HostName, settings.HostPort); + var arguments = string.Format(PackageConstants.SecureShell.KeyScanArguments, settings.HostName, settings.HostPort, settings.ForceIPv4 ? PackageConstants.SecureShell.SshForceIPv4 : string.Empty); var startInfo = new ProcessStartInfo(PackageConstants.SecureShell.KeyScanExecutable, arguments) { CreateNoWindow = true, @@ -124,6 +125,8 @@ public async Task AuthorizeKeyAsync(SecureShellKeySetupSettings settings) var stdError = await process.StandardError.ReadToEndAsync(); var exitCode = await process.WaitForExitAsync(); + await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync(); + if (exitCode == 0) { if (FileHelper.ContainsText(knownHostsFilePath, settings.HostName)) @@ -155,7 +158,7 @@ private async Task RegisterServerFingerprintWithConnectionAsync(SecureShel const string SshDoneMarker = "DONE"; // open a pseudo console windows to run the ssh command - var arguments = string.Format(PackageConstants.SecureShell.SshArguments, settings.UserName, settings.HostName, settings.HostPort, settings.PrivateKeyFile); + var arguments = string.Format(PackageConstants.SecureShell.SshArguments, settings.UserName, settings.HostName, settings.HostPort, settings.PrivateKeyFile, settings.ForceIPv4 ? PackageConstants.SecureShell.SshForceIPv4 : string.Empty); var startInfo = new ProcessStartInfo(PackageConstants.SecureShell.SshExecutable, arguments) { CreateNoWindow = false, diff --git a/src/Extension/RemoteDebuggerLauncher/RemoteOperations/SecureShellKeySetupSettings.cs b/src/Extension/RemoteDebuggerLauncher/RemoteOperations/SecureShellKeySetupSettings.cs index 7ccc331..774eb6d 100644 --- a/src/Extension/RemoteDebuggerLauncher/RemoteOperations/SecureShellKeySetupSettings.cs +++ b/src/Extension/RemoteDebuggerLauncher/RemoteOperations/SecureShellKeySetupSettings.cs @@ -1,4 +1,4 @@ -// ---------------------------------------------------------------------------- +// ---------------------------------------------------------------------------- // // Copyright (c) Michael Koster. All rights reserved. // Licensed under the MIT License. @@ -17,6 +17,7 @@ namespace RemoteDebuggerLauncher.RemoteOperations internal class SecureShellKeySetupSettings { private readonly bool forceIPv4; + public SecureShellKeySetupSettings(SetupSshViewModel viewModel) { HostName = viewModel.HostName; @@ -67,5 +68,10 @@ public SecureShellKeySetupSettings(SetupSshViewModel viewModel) /// Gets the private key file. /// public string PrivateKeyFile { get; } + + /// + /// Gets a value indicating whether to force IPv4 usage. + /// + public bool ForceIPv4 => forceIPv4; } } diff --git a/src/Extension/RemoteDebuggerLauncher/RemoteOperations/SecureShellPassphraseDialog.xaml b/src/Extension/RemoteDebuggerLauncher/RemoteOperations/SecureShellPassphraseDialog.xaml deleted file mode 100644 index 861164a..0000000 --- a/src/Extension/RemoteDebuggerLauncher/RemoteOperations/SecureShellPassphraseDialog.xaml +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file