From cd533d4000294883c7973bd21350b6a008d66044 Mon Sep 17 00:00:00 2001 From: Damian Suess Date: Mon, 2 May 2022 19:21:28 -0400 Subject: [PATCH 1/3] Added link to PuTTY --- readme.md | 3 ++- src/VsLinuxDebugger/Core/RemoteDebugger.cs | 5 ++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/readme.md b/readme.md index ea16b4c..ee536f7 100644 --- a/readme.md +++ b/readme.md @@ -19,7 +19,7 @@ Now developers can build, deploy and debug projects on their remote Linux (Ubunt ![VS Menu](docs/ScreenShot-MenuItems.png) * Build and upload to remote devices (_yes, this is a real pain_) -* Remote debugging (_P-Link only_) +* Remote debugging (_[P-Link](http://www.chiark.greenend.org.uk/~sgtatham/putty/download.html) only_) * VS Linux Debugger will automatically detect and install `vsdbg` for you! ### Customize your connections @@ -77,6 +77,7 @@ To contribute, please pick off an item from the project or issue page. We'd love ## References +* [PuTTY PLink](http://www.chiark.greenend.org.uk/~sgtatham/putty/download.html) * [Extension Docs](https://docs.microsoft.com/en-us/visualstudio/extensibility/creating-a-settings-category?view=vs-2022) * [Extension Sample](https://github.com/microsoft/VSSDK-Extensibility-Samples/tree/master/Options) * [Offroad Debugging](https://github.com/Microsoft/MIEngine/wiki/Offroad-Debugging-of-.NET-Core-on-Linux---OSX-from-Visual-Studio) diff --git a/src/VsLinuxDebugger/Core/RemoteDebugger.cs b/src/VsLinuxDebugger/Core/RemoteDebugger.cs index 8349c54..d27cda8 100644 --- a/src/VsLinuxDebugger/Core/RemoteDebugger.cs +++ b/src/VsLinuxDebugger/Core/RemoteDebugger.cs @@ -12,6 +12,9 @@ namespace VsLinuxDebugger.Core { public class RemoteDebugger { + private const string DebugAdapterHost = "DebugAdapterHost.Launch"; + private const string DebugAdapterLaunchJson = "/LaunchJson:"; + private bool _buildSuccessful; private TaskCompletionSource _buildTask = null; private DTE _dte; @@ -179,7 +182,7 @@ private void BuildDebugAttacher() Logger.Output($"- DebugAdapterHost.Launch /LaunchJson:\"{_launchJsonPath}\""); DTE2 dte2 = (DTE2)Package.GetGlobalService(typeof(SDTE)); - dte2.ExecuteCommand("DebugAdapterHost.Launch", $"/LaunchJson:\"{_launchJsonPath}\""); + dte2.ExecuteCommand(DebugAdapterHost, $"{DebugAdapterLaunchJson}\"{_launchJsonPath}\""); // launchConfigName = "Debug on Linux"; // DebugAdapterHost.Launch /LaunchJson:LaunchTester\Properties\launch.json /ConfigurationName:"{launchConfigName}" From 47fe53a7d313ce8118621768282d2171e9f7b245 Mon Sep 17 00:00:00 2001 From: Damian Suess Date: Tue, 3 May 2022 11:29:12 -0400 Subject: [PATCH 2/3] Added ability to download `plink.exe` and bundle it into the project (if it exists). Still need to add an `MSBuild /t:UpdateDependencies` to properly pre-download --- .gitignore | 1 + src/VsLinuxDebugger/VsLinuxDebugger.csproj | 17 +++++++++++++++++ 2 files changed, 18 insertions(+) diff --git a/.gitignore b/.gitignore index 117fec4..700dfd3 100644 --- a/.gitignore +++ b/.gitignore @@ -78,3 +78,4 @@ TestResult.xml /[Dd]ocs/backup /[Tt]ests /[Tt]ools +/src/VsLinuxDebugger/plink.exe diff --git a/src/VsLinuxDebugger/VsLinuxDebugger.csproj b/src/VsLinuxDebugger/VsLinuxDebugger.csproj index 75d73a5..c7ba684 100644 --- a/src/VsLinuxDebugger/VsLinuxDebugger.csproj +++ b/src/VsLinuxDebugger/VsLinuxDebugger.csproj @@ -133,4 +133,21 @@ --> + + + + https://the.earth.li/~sgtatham/putty/latest/w64/plink.exe + + + + + + + + + true + Always + + \ No newline at end of file From 77005036e50e451ebf08e199ec13dc91f1763d36 Mon Sep 17 00:00:00 2001 From: Damian Suess Date: Tue, 3 May 2022 13:16:32 -0400 Subject: [PATCH 3/3] #20 Added lookup of embedded `plink.exe`. NOTE: For now, you must still pass in the Remote UserPass for remote debugging with PLINK to work. --- src/VsLinuxDebugger/Commands.Impl.cs | 3 - src/VsLinuxDebugger/Core/LaunchBuilder.cs | 107 +++++++++++++----- src/VsLinuxDebugger/DebuggerPackage.cs | 3 - .../OptionsPages/OptionsPage.DotNet.cs | 6 +- .../OptionsPages/OptionsPage.Local.cs | 14 ++- 5 files changed, 89 insertions(+), 44 deletions(-) diff --git a/src/VsLinuxDebugger/Commands.Impl.cs b/src/VsLinuxDebugger/Commands.Impl.cs index 2902b12..0c77efd 100644 --- a/src/VsLinuxDebugger/Commands.Impl.cs +++ b/src/VsLinuxDebugger/Commands.Impl.cs @@ -127,13 +127,10 @@ private UserOptions ToUserOptions() HostIp = Settings.HostIp, HostPort = Settings.HostPort, - LocalPlinkEnabled = Settings.LocalPlinkEnabled, LocalPLinkPath = Settings.LocalPLinkPath, RemoteDebugDisplayGui = Settings.RemoteDebugDisplayGui, RemoteDeployBasePath = Settings.RemoteDeployBasePath, - ////RemoteDeployDebugPath = Settings.RemoteDeployDebugPath, - ////RemoteDeployReleasePath = Settings.RemoteDeployReleasePath, RemoteDotNetPath = Settings.RemoteDotNetPath, RemoteVsDbgPath = Settings.RemoteVsDbgPath, diff --git a/src/VsLinuxDebugger/Core/LaunchBuilder.cs b/src/VsLinuxDebugger/Core/LaunchBuilder.cs index be9e248..6b19a56 100644 --- a/src/VsLinuxDebugger/Core/LaunchBuilder.cs +++ b/src/VsLinuxDebugger/Core/LaunchBuilder.cs @@ -84,36 +84,7 @@ public string GenerateLaunchJson(bool vsdbgLogging = false) { string adapter, adapterArgs; - //// var sshEndpoint = $"{_opts.UserName}@{_opts.HostIp}:{_opts.HostPort}"; - var sshEndpoint = $"{_opts.UserName}@{_opts.HostIp}"; - - var vsdbgLogPath = ""; - if (vsdbgLogging) - vsdbgLogPath = $" --engineLogging={LinuxPath.Combine(RemoteDeployProjectFolder, "_vsdbg.log")}"; - - if (!_opts.LocalPlinkEnabled) - { - //// SSH Key alt-args: - //// $"-i \"{_opts.UserPrivateKeyPath}\" -o \"StrictHostKeyChecking no\" {RemoteUserName}@{RemoteHostIp} {_opts.RemoteVsDbgPath} --interpreter=vscode {vsdbgLogPath}") - var sshPassword = !_opts.UserPrivateKeyEnabled - ? $"-pw {_opts.UserPass}" - : $"-i {_opts.UserPrivateKeyPath} -o \"StrictHostKeyChecking no\""; - - adapter = "ssh.exe"; - adapterArgs = $"{sshPassword} {sshEndpoint} {_opts.RemoteVsDbgPath} --interpreter=vscode {vsdbgLogPath}"; - } - else - { - // TODO: Consider packing PLink.exe - //// "%LocalAppData%\\microsoft\\visualstudio\\16.0_c1d3f8c1\\extensions\\cruad2hg.efs\\plink.exe"; - //// var plinkPath = Path.Combine(GetExtensionDirectory(), "plink.exe").Trim('"'); - - adapter = _opts.LocalPLinkPath; - adapterArgs = $"-ssh -pw {RemoteUserPass} {RemoteUserName}@{RemoteHostIp} -batch -T {RemoteVsDbgPath} {vsdbgLogPath}"; - - //// adapterArgs = $"-ssh -pw {RemoteUserPass} {RemoteUserName}@{RemoteHostIp} -batch -T {RemoteVsDbgPath} --interpreter=vscode {vsdbgLogPath}"; - //// adapterArgs = $"-ssh -pw {_options.UserPass} {_options.UserName}@{_options.HostIp}:{_options.HostPort} -batch -T {_options.RemoteVsDbgPath} --interpreter=vscode"; - } + (adapter, adapterArgs) = GetAdapter(vsdbgLogging); var obj = new Launch( RemoteDotNetPath, @@ -147,5 +118,81 @@ public string GenerateLaunchJson(bool vsdbgLogging = false) return outputPath; } + + private (string adapterPath, string adapterArgs) GetAdapter(bool vsdbgLogging = false) + { + // NOTE: Removed ":{RemoteHostPort}" because it failed to launch with PLink + // var sshEndpoint = $"{_opts.UserName}@{_opts.HostIp}:{_opts.HostPort}"; + var sshEndpoint = $"{RemoteUserName}@{RemoteHostIp}"; + + var vsdbgLogPath = ""; + if (vsdbgLogging) + vsdbgLogPath = $" --engineLogging={LinuxPath.Combine(RemoteDeployProjectFolder, "_vsdbg.log")}"; + + ////if (!_opts.LocalPlinkEnabled) + ////{ + //// adapter = "ssh.exe"; + //// adapterArgs = $"{sshPassword} {sshEndpoint} {_opts.RemoteVsDbgPath} --interpreter=vscode {vsdbgLogPath}"; + ////} + ////else + ////{ + + string plinkPath = string.Empty; + + // Adapter Path: + // PLink.exe - Use manual path or embedded + if (!string.IsNullOrEmpty(_opts.LocalPLinkPath) && File.Exists(_opts.LocalPLinkPath)) + { + plinkPath = _opts.LocalPLinkPath; + } + else + { + plinkPath = Path.Combine(GetExtensionDirectory(), "plink.exe").Trim('"'); + } + + // Adapter Arguments: + // NOTE: + // 1. SSH Private Key ("-i PPK") fails with PLINK. Must use manual password until this is resolved. + // 2. Strict Host Key Checking is disabled by default; this doesn't need set. + // + // REF: https://linuxhint.com/ssh-stricthostkeychecking/ + // $"-i \"{_opts.UserPrivateKeyPath}\" -o \"StrictHostKeyChecking no\" {RemoteUserName}@{RemoteHostIp} {_opts.RemoteVsDbgPath} --interpreter=vscode {vsdbgLogPath}") + // + //// var strictKeyChecking = " -o \"StrictHostKeyChecking no\""; + //// strictKeyChecking = ""; + //// + ////var sshPassword = !_opts.UserPrivateKeyEnabled + //// ? $"-pw {RemoteUserPass}" + //// : $"-i \"{_opts.UserPrivateKeyPath}{strictKeyChecking}\""; + // + var sshPassword = $"-pw {RemoteUserPass}"; + + // TODO: Figure out why "-i " isn't working. + if (string.IsNullOrEmpty(RemoteUserPass)) + Logger.Output("You must provide a User Password to debug."); + + var adapter = plinkPath; + var adapterArgs = $"-ssh {sshPassword} {sshEndpoint} -batch -T {RemoteVsDbgPath} {vsdbgLogPath}"; + //// adapterArgs = $"-ssh {sshPassword} {sshEndpoint} -batch -T {RemoteVsDbgPath} --interpreter=vscode {vsdbgLogPath}"; + + return (adapter, adapterArgs); + } + + /// Attempt to get the extension's local directory. + /// Path of this VSIX or empty string. + private string GetExtensionDirectory() + { + var path = string.Empty; + try + { + var uri = new Uri(typeof(LaunchBuilder).Assembly.CodeBase, UriKind.Absolute); + path = Path.GetDirectoryName(uri.LocalPath); + } + catch (Exception) + { + } + + return path; + } } } diff --git a/src/VsLinuxDebugger/DebuggerPackage.cs b/src/VsLinuxDebugger/DebuggerPackage.cs index e1b1db5..acdc0c0 100644 --- a/src/VsLinuxDebugger/DebuggerPackage.cs +++ b/src/VsLinuxDebugger/DebuggerPackage.cs @@ -36,13 +36,10 @@ public sealed partial class DebuggerPackage : AsyncPackage public string HostIp => _optionsPage.HostIp; public int HostPort => _optionsPage.HostPort; - public bool LocalPlinkEnabled => _optionsPage.PLinkEnabled; public string LocalPLinkPath => _optionsPage.PLinkPath; public bool RemoteDebugDisplayGui => _optionsPage.RemoteDebugDisplayGui; public string RemoteDeployBasePath => _optionsPage.RemoteDeployBasePath; - ////public string RemoteDeployDebugPath => $"{_optionsPage.RemoteDeployBasePath}/TMP"; - ////public string RemoteDeployReleasePath => $"{_optionsPage.RemoteDeployBasePath}/TMP"; public string RemoteDotNetPath => _optionsPage.RemoteDotNetPath; public string RemoteVsDbgPath => _optionsPage.RemoteVsDbgPath; diff --git a/src/VsLinuxDebugger/OptionsPages/OptionsPage.DotNet.cs b/src/VsLinuxDebugger/OptionsPages/OptionsPage.DotNet.cs index d306fd7..5948f16 100644 --- a/src/VsLinuxDebugger/OptionsPages/OptionsPage.DotNet.cs +++ b/src/VsLinuxDebugger/OptionsPages/OptionsPage.DotNet.cs @@ -5,7 +5,7 @@ namespace Xeno.VsLinuxDebug.OptionsPages { public partial class OptionsPage : DialogPage { - private const string Experimental = "Expermimental"; + private const string Experimental = "Warning Expermimental"; private const string RemoteDebugger = "Remote Debugger"; [Category(Experimental)] @@ -17,7 +17,7 @@ public partial class OptionsPage : DialogPage [Category(RemoteDebugger)] [DisplayName("Upload to folder")] - [Description("Folder for to transfer files to. For HOME folder, use './VLSDbg' and not '~/VLSDbg'")] + [Description("Folder for to transfer files to. For HOME folder, use './VSLinuxDbg' and not '~/VSLinuxDbg'")] public string RemoteDeployBasePath { get; set; } = $"./VSLinuxDbg"; // "VSLDebugger" [Category(RemoteDebugger)] @@ -27,7 +27,7 @@ public partial class OptionsPage : DialogPage [Category(RemoteDebugger)] [DisplayName("Visual Studio Debugger Path")] - [Description("Remote Machine Visual Studio Debugger Path (Samples: `vsdbg`, `/.vsdbg/vsdbg`, `~/.vs-debugger/vs2022/vsdbg`")] + [Description("Remote Machine Visual Studio Debugger Path (Samples: `vsdbg`, `~/vsdbg/vsdbg`, `~/.vs-debugger/vs2022/vsdbg`")] public string RemoteVsDbgPath { get; set; } = "~/vsdbg/vsdbg"; [Category(Experimental)] diff --git a/src/VsLinuxDebugger/OptionsPages/OptionsPage.Local.cs b/src/VsLinuxDebugger/OptionsPages/OptionsPage.Local.cs index 3627425..1d6ecd8 100644 --- a/src/VsLinuxDebugger/OptionsPages/OptionsPage.Local.cs +++ b/src/VsLinuxDebugger/OptionsPages/OptionsPage.Local.cs @@ -16,13 +16,17 @@ public partial class OptionsPage : DialogPage ////[Description("Publish the solution instead of building. Apply setting for ASP.NET/Blazor projects.")] ////public bool Publish { get; set; } = false; - [Category(Local)] - [DisplayName("PLink: Enable Plink instead of SSH")] - [Description("Set to TRUE to debug with PLINK.EXE and FALSE for SSH.")] - public bool PLinkEnabled { get; set; } = false; + ////[Category(Local)] + ////[DisplayName("PLink: Enable Plink instead of SSH")] + //// + //// [Category(Local)] + //// to TRUE to debug with PLINK.EXE and FALSE for SSH.")] + //// + //// [Category(Local)] + //// Enabled { get; set; } = false; [Category(Local)] - [DisplayName("PLink: Local Path")] + [DisplayName("PLink Local Path (blank to use embedded)")] [Description(@"Full path to local PLINK.EXE file. (i.e. 'C:\temp\putty\plink.exe')")] public string PLinkPath { get; set; } = "";