public VSMonoDebuggerProjectSettings?GetProjectSettingsFromStartupProject() { NLogService.TraceEnteringMethod(); try { ThreadHelper.ThrowIfNotOnUIThread(); var startupProject = GetStartupProject(); var projectFullName = startupProject.FullName; if (File.Exists(projectFullName)) { var projectConfigFile = Path.ChangeExtension(projectFullName, ".VSMonoDebugger.config"); if (File.Exists(projectConfigFile)) { LogInfo($"Local project config file {projectConfigFile} found."); var projectConfigFileContent = File.ReadAllText(projectConfigFile); return(VSMonoDebuggerProjectSettings.DeserializeFromJson(projectConfigFileContent)); } } } catch (Exception ex) { // *.VSMonoDebugger.config can contain illigal escape characters for WindowsPath "C:\Temp" => "C:\\Temp" // Don't fix it ... user has to be json conform LogInfo("Please validate that the local project config file (*.VSMonoDebugger.config) conatins no illigal escape character sequences for WindowsDeployPath!"); LogError(ex); } return(null); }
private void Connect() { // NLogService.TraceEnteringMethod(Logger); if (this.IsConnected) { return; } if (this.ReconnectCurrentCount >= ReconnectMaxCount) { HostOutputWindowEx.WriteLineLaunchErrorAsync("Reconnect max count"); Logger.Error("Reconnect max count"); return; } try { this.Client = new TcpClient(); this.Client.NoDelay = true; this.Client.ReceiveTimeout = 10000; this.Client.SendTimeout = 10000; this.Client.Connect(this.NotifyServer, this.NotifyPort); ReconnectCurrentCount = 0; } catch (Exception e) { HostOutputWindowEx.WriteLineLaunchErrorAsync(e.ToString()); NLogService.LogError(Logger, e); this.Clear(); ReconnectCurrentCount += 1; } }
public static void CheckDatabasePath(IDataBase database, string path, string name) { CheckAndCreatePath(path); if (!System.IO.File.Exists(Path.Combine(path, name))) { database.Connect(path); database.Execute(@"CREATE TABLE NLogX ( Id INTEGER PRIMARY KEY AUTOINCREMENT, Time DATETIME, Level NVARCHAR, Threadname NVARCHAR, Source NVARCHAR, SourceDetails NVARCHAR, Message NVARCHAR, MessageId INTEGER, Logger NVARCHAR, Callsite NVARCHAR, Exception NVARCHAR )"); using (NLogService nLog = new NLogService()) { nLog.Initial(); nLog.Info("Created database"); } } }
private int BuildStartupProject() { ThreadHelper.ThrowIfNotOnUIThread(); var sb = (SolutionBuild2)_dte.Solution.SolutionBuild; try { var startProject = GetStartupProject(); var activeConfiguration = _dte.Solution.SolutionBuild.ActiveConfiguration as SolutionConfiguration2; var activeConfigurationName = activeConfiguration.Name; var activeConfigurationPlatform = activeConfiguration.Name; var startProjectName = startProject.FullName; Logger.Info($"BuildProject {startProject.FullName} {activeConfigurationName}|{activeConfigurationPlatform}"); sb.BuildProject($"{activeConfigurationName}|{activeConfigurationPlatform}", startProject.FullName, true); } catch (Exception ex) { NLogService.LogError(Logger, ex); Logger.Info($"BuildProject failed - Fallback: BuildSolution"); // Build complete solution (fallback solution) return(BuildSolution()); } return(sb.LastBuildInfo); }
public async Task CreateMdbForAllDependantProjectsAsync(Action <string> msgOutput) { NLogService.TraceEnteringMethod(); await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync(); var sb = (SolutionBuild2)_dte.Solution.SolutionBuild; var startProject = GetStartupProject(); var dependantProjects = CollectAllDependentProjects(startProject, msgOutput); var outputDirectories = CollectOutputDirectories(sb, msgOutput); foreach (var projectName in dependantProjects.Keys) { try { if (outputDirectories.ContainsKey(projectName)) { var outputDir = outputDirectories[projectName]; LogInfo($"{projectName} - OutputDir: {outputDir}"); await ConvertPdb2MdbAsync(outputDir, msgOutput); } else { LogInfo($"{projectName} - OutputDir: NOT FOUND!"); } } catch (Exception ex) { LogError(ex); } } }
public DebugOptions CreateDebugOptions(UserSettings settings) { NLogService.TraceEnteringMethod(); ThreadHelper.ThrowIfNotOnUIThread(); var startupAssemblyPath = GetStartupAssemblyPath(); var targetExeFileName = Path.GetFileName(startupAssemblyPath); var outputDirectory = Path.GetDirectoryName(startupAssemblyPath); var startArguments = GetStartArguments(); var preDebugScript = settings.DeployAndDebugOnLocalWindowsSystem ? settings.PreDebugScriptWithParametersWindows : settings.PreDebugScriptWithParameters; preDebugScript = ReplaceDebugParameters(preDebugScript, settings, targetExeFileName, startArguments, "\n"); var debugScript = settings.DeployAndDebugOnLocalWindowsSystem ? settings.DebugScriptWithParametersWindows : settings.DebugScriptWithParameters; debugScript = ReplaceDebugParameters(debugScript, settings, targetExeFileName, startArguments, "\n"); var debugOptions = new DebugOptions() { StartupAssemblyPath = startupAssemblyPath, UserSettings = settings, OutputDirectory = outputDirectory, TargetExeFileName = targetExeFileName, StartArguments = startArguments, PreDebugScript = preDebugScript, DebugScript = debugScript, }; return(debugOptions); }
public /*override*/ int DestroyProgram(IDebugProgram2 pProgram) { NLogService.TraceEnteringMethod(Logger); _activeProgram = null; _eventCallback = null; return(_engine.DestroyProgram(pProgram)); }
public /*override*/ int Attach(IDebugProgram2[] rgpPrograms, IDebugProgramNode2[] rgpProgramNodes, uint celtPrograms, IDebugEventCallback2 pCallback, enum_ATTACH_REASON dwReason) { NLogService.TraceEnteringMethod(Logger); if (rgpPrograms.Length != 1) { NLogService.Logger.Error("The debug engine can only be attached to one program at the time."); return(VisualStudioExtensionConstants.S_FALSE); } if (_activeProgram != null) { NLogService.Logger.Error("The debug engine is already attached."); return(VisualStudioExtensionConstants.S_FALSE); } _activeProgram = rgpPrograms[0]; _eventCallback = pCallback; try { _session.Run(_startInfo, _startInfo.SessionOptions); } catch (Exception ex) { Debug.WriteLine(ex.Message + " - " + ex.StackTrace); } return(_engine.Attach(rgpPrograms, rgpProgramNodes, celtPrograms, pCallback, dwReason)); }
/// <summary> /// Initialization of the package; this method is called right after the package is sited, so this is the place /// where you can put all the initialization code that rely on services provided by VisualStudio. /// </summary> protected override void Initialize() { base.Initialize(); try { NLogService.Setup($"{nameof(VSMonoDebuggerPackage)}.log"); UserSettingsManager.Initialize(this); DebugEngineInstallService.TryRegisterAssembly(); VSMonoDebuggerCommands.Initialize(this); } catch (UnauthorizedAccessException uex) { VsShellUtilities.ShowMessageBox( this, "Failed finish installation of VSMonoDebugger - Please run Visual Studio once as Administrator...", $"{nameof(VSMonoDebuggerPackage)} - Register mono debug engine", OLEMSGICON.OLEMSGICON_CRITICAL, OLEMSGBUTTON.OLEMSGBUTTON_OK, OLEMSGDEFBUTTON.OLEMSGDEFBUTTON_FIRST); NLogService.Logger.Error(uex); } catch (Exception ex) { NLogService.Logger.Error(ex); } }
/// <summary> /// Initialization of the package; this method is called right after the package is sited, so this is the place /// where you can put all the initialization code that rely on services provided by VisualStudio. /// </summary> protected override async System.Threading.Tasks.Task InitializeAsync(CancellationToken cancellationToken, IProgress <ServiceProgressData> progress) { try { NLogService.Setup($"{nameof(VSMonoDebuggerPackage)}.log"); DebugEngineInstallService.TryRegisterAssembly(); await JoinableTaskFactory.SwitchToMainThreadAsync(cancellationToken); UserSettingsManager.Initialize(this); VSMonoDebuggerCommands.Initialize(this); } catch (UnauthorizedAccessException uex) { await JoinableTaskFactory.SwitchToMainThreadAsync(cancellationToken); var package = this as Package; VsShellUtilities.ShowMessageBox( package, "Failed finish installation of VSMonoDebugger - Please run Visual Studio once as Administrator...", $"{nameof(VSMonoDebuggerPackage)} - Register mono debug engine", OLEMSGICON.OLEMSGICON_CRITICAL, OLEMSGBUTTON.OLEMSGBUTTON_OK, OLEMSGDEFBUTTON.OLEMSGDEFBUTTON_FIRST); NLogService.Logger.Error(uex); } catch (Exception ex) { NLogService.Logger.Error(ex); } await base.InitializeAsync(cancellationToken, progress); }
public /*override*/ int GetEngineId(out Guid pguidEngine) { NLogService.TraceEnteringMethod(); var temp = _engine.GetEngineId(out pguidEngine); pguidEngine = new Guid(DebugEngineGuids.XamarinEngineString); return 0; }
protected override void OnStartup(StartupEventArgs e) { NLogService nLogService = new NLogService(Directory.GetCurrentDirectory()); var host = nLogService.BuildHost(CreateHostBuilder); var mainWindow = host.Services.GetRequiredService <MainWindow>(); mainWindow.Show(); }
public /*override*/ int LaunchSuspended(string pszServer, IDebugPort2 pPort, string pszExe, string pszArgs, string pszDir, string bstrEnv, string pszOptions, enum_LAUNCH_FLAGS dwLaunchFlags, uint hStdInput, uint hStdOutput, uint hStdError, IDebugEventCallback2 pCallback, out IDebugProcess2 ppProcess) { NLogService.TraceEnteringMethod(); var base64Options = SerializeDebuggerOptions(pszOptions); var result = _engine.LaunchSuspended(pszServer, pPort, pszExe, pszArgs, pszDir, bstrEnv, base64Options, dwLaunchFlags, hStdInput, hStdOutput, hStdError, pCallback, out ppProcess); return(result); }
public void NotifyToEngineDetach(bool bStopPlay) { NLogService.TraceEnteringMethod(Logger); string Message = string.Format("cmd:Detach;value:{0}", bStopPlay); byte[] Data = System.Text.UnicodeEncoding.Unicode.GetBytes(Message); Send(Data); }
private string SerializeDebuggerOptions(string jsonDebugOptions) { try { NLogService.TraceEnteringMethod(Logger); var debugOptions = DebugOptions.DeserializeFromJson(jsonDebugOptions); _session = new MonoDebugSession(); LogMonoDebuggerAssemblyPaths(); if (debugOptions.UserSettings.EnableVerboseDebugLogging) { RegisterEventHandlers(); } var connectionTimeout = 30000; var evaluationTimeout = 30000; var startupProject = StartupProject; XamarinEngine.DebugOptions = debugOptions; var softDebuggerConnectArgs = new SoftDebuggerConnectArgs(debugOptions.TargetExeFileName, debugOptions.GetHostIP(), debugOptions.GetMonoDebugPort()); // TODO implement programm output via stream //softDebuggerConnectArgs.RedirectOutput = true; //softDebuggerConnectArgs.OutputPort = ???; //_session.VirtualMachine.StandardOutput ??? softDebuggerConnectArgs.TimeBetweenConnectionAttempts = (int)debugOptions.UserSettings.TimeBetweenConnectionAttemptsInMs; softDebuggerConnectArgs.MaxConnectionAttempts = (int)debugOptions.UserSettings.MaxConnectionAttempts; _startInfo = new StartInfo( softDebuggerConnectArgs, new DebuggingOptions() { EvaluationTimeout = evaluationTimeout, MemberEvaluationTimeout = evaluationTimeout, ModificationTimeout = evaluationTimeout, SocketTimeout = connectionTimeout }, startupProject ); SessionMarshalling sessionMarshalling = new SessionMarshalling(_session, _startInfo); using (MemoryStream ms = new MemoryStream()) { BinaryFormatter bf = new BinaryFormatter(); ObjRef oref = RemotingServices.Marshal(sessionMarshalling); bf.Serialize(ms, oref); return(Convert.ToBase64String(ms.ToArray())); } } catch (Exception ex) { Logger.Error(ex); throw; } }
public void Send(byte[] Data) { NLogService.TraceEnteringMethod(Logger); this.ReconnectCurrentCount = 0; lock (LockObject) { WaittingToSendDatas.AddLast(Data); } }
private void Clear() { NLogService.TraceEnteringMethod(Logger); // this.WaittingToSendDatas.Clear(); if (this.Client != null) { this.Client.Close(); this.Client = null; } }
private int BuildSolution() { NLogService.TraceEnteringMethod(Logger); ThreadHelper.ThrowIfNotOnUIThread(); var sb = (SolutionBuild2)_dte.Solution.SolutionBuild; sb.Build(true); return(sb.LastBuildInfo); }
public bool IsStartupProjectAvailable() { NLogService.TraceEnteringMethod(); ThreadHelper.ThrowIfNotOnUIThread(); var sb = (SolutionBuild2)_dte.Solution.SolutionBuild; return(sb.StartupProjects != null && ((Array)sb.StartupProjects).Cast <string>().Count() > 0); }
public async Task OverrideRunCommandAsync() { NLogService.TraceEnteringMethod(); await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync(); // https://stackoverflow.com/questions/15908652/how-to-programmatically-override-the-build-and-launch-actions // https://visualstudioextensions.vlasovstudio.com/2017/06/29/changing-visual-studio-2017-private-registry-settings/ // https://github.com/3F/vsCommandEvent var _dteEvents = _dte.Events; _startCommandEvents = _dte.Events.CommandEvents["{5EFC7975-14BC-11CF-9B2B-00AA00573819}", 295]; _startCommandEvents.BeforeExecute += OnBeforeStartCommand; }
public /*override*/ int Attach(IDebugProgram2[] rgpPrograms, IDebugProgramNode2[] rgpProgramNodes, uint celtPrograms, IDebugEventCallback2 pCallback, enum_ATTACH_REASON dwReason) { NLogService.TraceEnteringMethod(); try { _session.Run(_startInfo, _startInfo.SessionOptions); } catch (Exception ex) { Debug.WriteLine(ex.Message + " - " + ex.StackTrace); } return(_engine.Attach(rgpPrograms, rgpProgramNodes, celtPrograms, pCallback, dwReason)); }
public void AttachDebuggerToRunningProcess(DebugOptions debugOptions) { NLogService.TraceEnteringMethod(); ThreadHelper.ThrowIfNotOnUIThread(); if (DebugEngineGuids.UseAD7Engine == EngineType.XamarinEngine) { // Workaround to get StartProject XamarinEngine.StartupProject = GetStartupProject(); } IntPtr pInfo = GetDebugInfo(debugOptions); var sp = new ServiceProvider((IServiceProvider)_dte); try { var dbg = sp.GetService(typeof(SVsShellDebugger)) as IVsDebugger; if (dbg == null) { logger.Error($"GetService did not returned SVsShellDebugger"); } int hr = dbg.LaunchDebugTargets(1, pInfo); Marshal.ThrowExceptionForHR(hr); } catch (Exception ex) { logger.Error(ex); string msg = null; var sh = sp.GetService(typeof(SVsUIShell)) as IVsUIShell; if (sh != null) { sh.GetErrorInfo(out msg); } if (!string.IsNullOrWhiteSpace(msg)) { logger.Error(msg); } throw; } finally { if (pInfo != IntPtr.Zero) { Marshal.FreeCoTaskMem(pInfo); } } }
private string GetStartArguments() { ThreadHelper.ThrowIfNotOnUIThread(); try { Project startupProject = GetStartupProject(); Configuration configuration = startupProject.ConfigurationManager.ActiveConfiguration; return(configuration.Properties.Item("StartArguments").Value?.ToString() ?? string.Empty); } catch (Exception ex) { NLogService.LogError(Logger, ex); return(string.Empty); } }
private Task <bool> StartDebuggerAsync(SshDeltaCopy.Options options, DebugOptions debugOptions, bool deploy, bool debug, Func <string, Task> writeOutput, RedirectOutputOptions redirectOutputOption) { NLogService.TraceEnteringMethod(Logger); return(Task.Run <bool>(async() => { var errorHelpText = new StringBuilder(); Action <string> writeLineOutput = s => writeOutput(s + Environment.NewLine).Wait(); try { errorHelpText.AppendLine($"SSH Login: {options.Username}@{options.Host}:{options.Port} Directory: {options.DestinationDirectory}"); using (SshDeltaCopy sshDeltaCopy = new SshDeltaCopy(options)) { sshDeltaCopy.LogOutput = writeLineOutput; if (deploy) { Logger.Info($"StartDebuggerAsync - deploy"); errorHelpText.AppendLine($"SSH: Start deployment from '{options.SourceDirectory}' to '{options.DestinationDirectory}'."); sshDeltaCopy.DeployDirectory(options.SourceDirectory, options.DestinationDirectory); errorHelpText.AppendLine($"SSH Deployment was successful."); // We are creating mdb files on local machine with pdb2mdb //var createMdbCommand = sshDeltaCopy.RunSSHCommand($@"find . -regex '.*\(exe\|dll\)' -exec {debugOptions.UserSettings.SSHPdb2mdbCommand} {{}} \;", false); //msgOutput(createMdbCommand.Result); } if (debug) { Logger.Info($"StartDebuggerAsync - debug"); await DebugAsync(debugOptions, writeOutput, redirectOutputOption, errorHelpText, writeLineOutput, sshDeltaCopy); } } } catch (Exception ex) { var additionalErrorMessage = $"SSHDebugger: {ex.Message}\n\nExecuted steps:\n{errorHelpText.ToString()}"; await writeOutput(additionalErrorMessage); throw new Exception(additionalErrorMessage, ex); } return true; })); }
/// <summary> /// Initialization of the package; this method is called right after the package is sited, so this is the place /// where you can put all the initialization code that rely on services provided by VisualStudio. /// </summary> /// <param name="cancellationToken">A cancellation token to monitor for initialization cancellation, which can occur when VS is shutting down.</param> /// <param name="progress">A provider for progress updates.</param> /// <returns>A task representing the async work of package initialization, or an already completed task if there is none. Do not return null from this method.</returns> protected override async Task InitializeAsync(CancellationToken cancellationToken, IProgress <ServiceProgressData> progress) { NLogService.Setup($"{nameof(LocalMonoDebuggerPackage)}.log"); DebugEngineInstallService.TryRegisterAssembly(); // When initialized asynchronously, the current thread may be a background thread at this point. // Do any initialization that requires the UI thread after switching to the UI thread. await JoinableTaskFactory.SwitchToMainThreadAsync(cancellationToken); var dte = await GetServiceAsync(typeof(EnvDTE.DTE)) as EnvDTE.DTE; var menuCommandService = await GetServiceAsync(typeof(IMenuCommandService)) as OleMenuCommandService; OptionsManager.Initialize(this); monoExt = new MonoVSExtension(this, dte); commands = new Commands(this, menuCommandService, monoExt); }
/// <summary> /// Initialization of the package; this method is called right after the package is sited, so this is the place /// where you can put all the initialization code that rely on services provided by VisualStudio. /// </summary> protected override async System.Threading.Tasks.Task InitializeAsync(CancellationToken cancellationToken, IProgress <ServiceProgressData> progress) { try { NLogService.Setup($"{nameof(VSMonoDebuggerPackage)}.log"); DebugEngineInstallService.TryRegisterAssembly(); // see https://github.com/microsoft/VSSDK-Extensibility-Samples/tree/master/AsyncPackageMigration await JoinableTaskFactory.SwitchToMainThreadAsync(cancellationToken); var dte = await GetServiceAsync(typeof(EnvDTE.DTE)) as EnvDTE.DTE; var menuCommandService = await GetServiceAsync(typeof(IMenuCommandService)) as OleMenuCommandService; // TODO replace by services UserSettingsManager.Initialize(this); _monoVisualStudioExtension = new MonoVisualStudioExtension(this, dte); _monoDebuggerCommands = new VSMonoDebuggerCommands(this, menuCommandService, _monoVisualStudioExtension); await AttachToEngineCommand.InitializeAsync(this, menuCommandService, _monoVisualStudioExtension); } catch (UnauthorizedAccessException uex) { await JoinableTaskFactory.SwitchToMainThreadAsync(cancellationToken); var package = this as Package; VsShellUtilities.ShowMessageBox( package, "Failed finish installation of VSMonoDebugger - Please run Visual Studio once as Administrator...", $"{nameof(VSMonoDebuggerPackage)} - Register mono debug engine", OLEMSGICON.OLEMSGICON_CRITICAL, OLEMSGBUTTON.OLEMSGBUTTON_OK, OLEMSGDEFBUTTON.OLEMSGDEFBUTTON_FIRST); Logger.Error(uex); } catch (Exception ex) { Logger.Error(ex); } await base.InitializeAsync(cancellationToken, progress); }
private void Receive() { // NLogService.TraceEnteringMethod(Logger); try { if (!this.IsConnected) { return; } int DataCount = this.CurrentDataLength; if (DataCount == 0) { DataCount = DataHeaderSize; } byte[] Data = new byte[DataCount]; if (DataCount > 0 && this.Client.Available >= DataCount) { this.Client.GetStream().Read(Data, 0, DataCount); if (!BitConverter.IsLittleEndian) { Array.Reverse(Data); } if (this.CurrentDataLength == 0) { this.CurrentDataLength = BitConverter.ToInt32(Data, 0); } else { this.CurrentDataLength = 0; string DataText = System.Text.UTF8Encoding.UTF8.GetString(Data); Logger.Debug(string.Format("Receive: {0}", DataText)); // todo 回调 } } } catch (Exception e) { HostOutputWindowEx.WriteLineLaunchErrorAsync(e.ToString()); NLogService.LogError(Logger, e); Clear(); } }
public async Task BuildStartupProjectAsync() { NLogService.TraceEnteringMethod(); await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync(); var failedBuilds = BuildStartupProject(); if (failedBuilds > 0) { Window window = _dte.Windows.Item("{34E76E81-EE4A-11D0-AE2E-00A0C90FFFC3}");//EnvDTE.Constants.vsWindowKindOutput OutputWindow outputWindow = (OutputWindow)window.Object; outputWindow.ActivePane.Activate(); outputWindow.ActivePane.OutputString($"{failedBuilds} project(s) failed to build. See error and output window!"); _errorListProvider.Show(); throw new Exception($"{failedBuilds} project(s) failed to build. See error and output window!"); } }
private Task ConvertPdb2MdbAsync(string outputDirectory, Action <string> msgOutput) { return(Task.Run(() => { msgOutput?.Invoke($"Start ConvertPdb2Mdb: {outputDirectory} ..."); var assemblyFiles = Directory.EnumerateFiles(outputDirectory, "*.exe", SearchOption.AllDirectories) .Union(Directory.EnumerateFiles(outputDirectory, "*.dll", SearchOption.AllDirectories)); foreach (string file in assemblyFiles) { var pdbFile = Path.ChangeExtension(file, "pdb"); if (!File.Exists(pdbFile)) { // No *.pdb file found for file continue; } var mdbFile = file + ".mdb"; if (File.GetLastWriteTime(pdbFile) <= File.GetLastWriteTime(mdbFile)) { // No newer *.pdb file found msgOutput?.Invoke($"No mdb file creation needed for {file}. (*.pdb file write time <= *.mdb file write time)"); continue; } msgOutput?.Invoke($"Creating mdb file for {file}"); try { Pdb2Mdb.Converter.Convert(file); } catch (Exception ex) { NLogService.LogError(Logger, ex); msgOutput?.Invoke($"Error while creating mdb file for {file}. {ex.Message}"); } } msgOutput?.Invoke($"End ConvertPdb2Mdb."); })); }
public void AttachDotnetDebuggerToRunningProcess(DebugOptions debugOptions) { NLogService.TraceEnteringMethod(Logger); var extensionInstallationDirectory = GetExtensionInstallationDirectoryOrNull(); if (extensionInstallationDirectory == null) { Logger.Error($"{nameof(extensionInstallationDirectory)} is null!"); } var settings = debugOptions.UserSettings; var launchJson = settings.LaunchJsonContent; var jsonStringPlinkExe = JsonConvert.SerializeObject(Path.Combine(extensionInstallationDirectory, "plink.exe")).Trim('"'); launchJson = launchJson.Replace(settings.PLINK_EXE_PATH, jsonStringPlinkExe); var sshPassword = string.IsNullOrWhiteSpace(settings.SSHPrivateKeyFile) ? $"-pw {settings.SSHPassword} {settings.SSHFullUrl}" : $"-i {settings.SSHPrivateKeyFile} {settings.SSHFullUrl}"; launchJson = launchJson.Replace(settings.PLINK_SSH_CONNECTION_ARGS, $"{sshPassword} "); var jsonStringDeployPath = JsonConvert.SerializeObject(debugOptions.UserSettings.SSHDeployPath).Trim('"'); launchJson = launchJson.Replace(settings.DEPLOYMENT_PATH, jsonStringDeployPath); launchJson = launchJson.Replace(settings.TARGET_EXE_FILENAME, debugOptions.TargetExeFileName); var jsonStringStartArguments = JsonConvert.SerializeObject(debugOptions.StartArguments).Trim('"'); launchJson = launchJson.Replace(settings.START_ARGUMENTS, jsonStringStartArguments); string launchJsonFile = Path.Combine(GetStartupProjectPath(), "launch.json"); Logger.Info($"Path of launch.json = {launchJsonFile}"); File.WriteAllText(launchJsonFile, launchJson); Logger.Info($"Project {debugOptions.StartupAssemblyPath} was built successfully. Invoking remote debug command"); var dte2 = _dte as DTE2; dte2.ExecuteCommand("DebugAdapterHost.Launch", $"/LaunchJson:\"{launchJsonFile}\" /EngineGuid:541B8A8A-6081-4506-9F0A-1CE771DEBC04"); }