From 77b37339decd9c023d4ced37e677797f5b72c3ae Mon Sep 17 00:00:00 2001 From: Roy Ben-Shabat Date: Mon, 4 Jun 2018 19:46:22 +0300 Subject: Implemented VSIX remote debugger!!!! --- .../Tango.BuildExtensions/RemoteDebugCommand.cs | 167 ++++++++++++++++----- 1 file changed, 132 insertions(+), 35 deletions(-) (limited to 'Software/Visual_Studio/VSIX/Tango.BuildExtensions/RemoteDebugCommand.cs') diff --git a/Software/Visual_Studio/VSIX/Tango.BuildExtensions/RemoteDebugCommand.cs b/Software/Visual_Studio/VSIX/Tango.BuildExtensions/RemoteDebugCommand.cs index 5b019eddc..2acc25187 100644 --- a/Software/Visual_Studio/VSIX/Tango.BuildExtensions/RemoteDebugCommand.cs +++ b/Software/Visual_Studio/VSIX/Tango.BuildExtensions/RemoteDebugCommand.cs @@ -12,6 +12,14 @@ using Microsoft.VisualStudio.Shell.Interop; using System.Linq; using System.IO; using System.Diagnostics; +using Tango.Transport; +using Tango.Transport.Adapters; +using Tango.Transport.Transporters; +using System.IO.Compression; +using Tango.Core.IO; +using Tango.PMR.IO; +using Google.Protobuf; +using EnvDTE; namespace Tango.BuildExtensions { @@ -20,7 +28,10 @@ namespace Tango.BuildExtensions /// internal sealed class RemoteDebugCommand : VSIXBase { - private const string SHARED_PATH = @"\\twine01\data\RemoteDebugging"; + private DebuggerEvents _dteDebuggerEvents; + private ITransporter transporter; + private bool _attached; + private string processId; /// /// Command ID. @@ -49,6 +60,10 @@ namespace Tango.BuildExtensions throw new ArgumentNullException("package"); } + _dteDebuggerEvents = DTE.Events.DebuggerEvents; + + _dteDebuggerEvents.OnEnterDesignMode += _dteDebuggerEvents_OnEnterDesignMode; + this.package = package; OleMenuCommandService commandService = this.ServiceProvider.GetService(typeof(IMenuCommandService)) as OleMenuCommandService; @@ -60,6 +75,33 @@ namespace Tango.BuildExtensions } } + private async void _dteDebuggerEvents_OnEnterDesignMode(dbgEventReason Reason) + { + if (_attached) + { + if (Reason == dbgEventReason.dbgEventReasonStopDebugging) + { + _attached = false; + + if (transporter != null) + { + OpenVSProgress("Tango Remote Runner", "Closing remote process...", true); + + await transporter.SendRequest(new KillProcessRequest() + { + ProcessID = processId, + }); + await transporter.Disconnect(); + transporter = null; + + await System.Threading.Tasks.Task.Delay(2000); + + CloseVSProgress(); + } + } + } + } + /// /// Gets the instance of the command. /// @@ -104,6 +146,8 @@ namespace Tango.BuildExtensions private void RunRemote() { + _attached = false; + try { String projectName = DTE.Solution.Properties.Item("StartupProject").Value.ToString(); @@ -112,56 +156,109 @@ namespace Tango.BuildExtensions if (dlg.ShowDialog() == System.Windows.Forms.DialogResult.OK) { - System.Threading.Tasks.Task.Factory.StartNew(() => + System.Threading.Tasks.Task.Factory.StartNew(async () => { - OpenProgressForm(); + try + { + OpenVSProgress("Tango Remote Runner", "Connecting to " + dlg.SelectedRemoteRunner.HostName + "...", true); + + ITransportAdapter adapter = new TcpTransportAdapter(dlg.SelectedRemoteRunner.Address, dlg.SelectedRemoteRunner.Port); + transporter = new BasicTransporter(adapter); + await transporter.Connect(); + + SetVSProgress("Building " + projectName + "..."); + + var project = GetSolutionProjects().SingleOrDefault(x => x.Name == projectName); + + String filePath = GetProjectOutputFilePath(project); + String folder = Path.GetDirectoryName(filePath); + String fileName = Path.GetFileName(filePath); + + DTE.Solution.SolutionBuild.BuildProject("Debug", project.FullName, true); + + var tempFolder = TemporaryManager.Default.CreateFolder(); + var zipFile = tempFolder.CreateFile(".zip"); + + await zipFile.DeleteAsync(); + SetVSProgress("Packaging project..."); + ZipFile.CreateFromDirectory(folder, zipFile.Path); + + FileInfo zipFileInfo = new FileInfo(zipFile); + + CloseVSProgress(); + + OpenVSProgress("Tango Remote Runner", "Uploading project...", false); + + var upResponse = await transporter.SendRequest(new FileUploadRequest() + { + FileName = zipFile.FileName, + Length = zipFileInfo.Length, + }); + + var uploadResponse = upResponse.Message; + + int currentFilePosition = 0; + + do + { + using (FileStream fs = new FileStream(zipFileInfo.FullName, FileMode.Open)) + { + fs.Position = currentFilePosition; + + FileChunkUploadRequest chunkRequest = new FileChunkUploadRequest(); + chunkRequest.UploadID = uploadResponse.UploadID; + + long remaining = zipFileInfo.Length - currentFilePosition; + + byte[] buffer = new byte[uploadResponse.MaxChunkLength < remaining ? uploadResponse.MaxChunkLength : remaining]; + await fs.ReadAsync(buffer, 0, buffer.Length); + chunkRequest.Buffer = ByteString.CopyFrom(buffer); + + await transporter.SendRequest(chunkRequest); + + currentFilePosition += buffer.Length; + + SetVSProgress("Uploading project...", "", currentFilePosition, (int)zipFileInfo.Length); + } + + } while (currentFilePosition < zipFileInfo.Length); - SetProgressText("Building " + projectName + "..."); + Wait(1000); - var project = GetSolutionProjects().SingleOrDefault(x => x.Name == projectName); + CloseVSProgress(); - String filePath = GetProjectOutputFilePath(project); - String folder = Path.GetDirectoryName(filePath); - String fileName = Path.GetFileName(filePath); - String remoteFolder = Path.Combine(dlg.SharedFolder, projectName); - String remoteFilePath = Path.Combine(remoteFolder, fileName); + OpenVSProgress("Tango Remote Runner", "Executing remote process...", true); - DTE.Solution.SolutionBuild.BuildProject("Debug", project.FullName, true); + var response = await transporter.SendRequest(new ExecuteProcessRequest() + { + UploadID = uploadResponse.UploadID, + FileName = fileName, + }, TimeSpan.FromSeconds(30)); - Directory.CreateDirectory(remoteFolder); + processId = response.Message.ProcessID; - CopyDirectory(folder, remoteFolder, true, (file) => - { - SetProgressText("Copying " + Path.GetFileName(file) + "..."); - }); + SetVSProgress("Attaching Debugger..."); - String PsExecPath = GetFullPathToContentFile("PsExec.exe"); + var debugger = DTE.Debugger as EnvDTE80.Debugger2; + var transport = debugger.Transports.Item("Remote"); + var process = debugger.GetProcesses(transport, dlg.SelectedRemoteRunner.Address).Item(fileName) as EnvDTE80.Process2; + process.Attach(); + _attached = true; - SetProgressText("Executing remote process..."); - Process p = new Process(); - p.StartInfo.FileName = PsExecPath; - p.StartInfo.UseShellExecute = false; - p.StartInfo.WindowStyle = ProcessWindowStyle.Hidden; - p.StartInfo.CreateNoWindow = true; - p.EnableRaisingEvents = true; - p.StartInfo.RedirectStandardError = true; - p.StartInfo.RedirectStandardOutput = false; - p.ErrorDataReceived += (x, e) => + CloseVSProgress(); + } + catch (Exception ex) { - SetProgressText("The process will start shortly, please wait..."); - Wait(20000); - CloseProgressForm(); - }; - p.StartInfo.Arguments = String.Format("-u {0} -p {1} -i {2} \"{3}\" -accepteula", dlg.UserName, dlg.Password, dlg.HostName, remoteFilePath); - p.Start(); - p.BeginErrorReadLine(); + CloseVSProgress(); + ShowMessage(ex.Message); + } }); } } catch (Exception ex) { - CloseProgressForm(); + CloseVSProgress(); ShowMessage(ex.Message); } } -- cgit v1.3.1