如何在当前Visual Studio主机内部的Visual Studio扩展中调试用Roslyn编译的代码? [英] How to debug code compiled with Roslyn in a Visual Studio extension inside current Visual Studio host?

查看:133
本文介绍了如何在当前Visual Studio主机内部的Visual Studio扩展中调试用Roslyn编译的代码?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个Visual Studio扩展,该扩展使用Roslyn在当前打开的解决方案中获取项目,对其进行编译并从中运行方法。该项目可以由程序员进行修改。

I have a Visual Studio extensions that use Roslyn to get a project in current opened solution, compile it and run methods from it. The project can be modified by the programmer.

我已经从当前VisualStudioWorkspace的Visual Studio扩展中成功编译了一个项目。

I have successfully compiled a project in a Visual Studio extension from the current VisualStudioWorkspace.

    private static Assembly CompileAndLoad(Compilation compilation)
    {
        using (MemoryStream dllStream = new MemoryStream())
        using (MemoryStream pdbStream = new MemoryStream())
        {
            EmitResult result = compilation.Emit(dllStream, pdbStream);

            if (!result.Success)
            {
                IEnumerable<Diagnostic> failures = result.Diagnostics.Where(diagnostic =>
                    diagnostic.IsWarningAsError ||
                    diagnostic.Severity == DiagnosticSeverity.Error);

                string failuresException = "Failed to compile code generation project : \r\n";

                foreach (Diagnostic diagnostic in failures)
                {
                    failuresException += $"{diagnostic.Id} : {diagnostic.GetMessage()}\r\n";
                }

                throw new Exception(failuresException);
            }
            else
            {

                dllStream.Seek(0, SeekOrigin.Begin);
                return AppDomain.CurrentDomain.Load(dllStream.ToArray(), pdbStream.ToArray());

            }
        }
    }

然后我可以在当前域中加载程序集,获取其类型并调用方法。

Then I can load the assembly in current domain, get it's types and invoke methods.

问题是如果加载的当前配置需要允许程序员放置断点解决方案是调试。

The problem is that I need to allow the programmer to put breakpoints if the current configuration of the loaded solution is debug.

我需要通过扩展在当前Visual Studio Host中运行一些代码,并允许在当前Visual Studio实例中对其进行调试。

I need to run some code in current Visual Studio Host from an extension and allow it to be debugged in the current Visual Studio instance.

推荐答案

似乎实际上是不可能的。

Seems like this is actually impossible.

当前的Visual Studio实例无法调试

The current visual studio instance cannot debug itself.

我尝试用roslyn创建一个控制台应用程序,将其附加到调试器,然后从中运行生成代码。但是VisualStudioWorkspace仅在VisualStudio内部可用(不可序列化,并且不能通过DTE com接口使用)。因此,剩下的唯一解决方案是使用MBBuildWorkspace。由于它的行为与Visual Studio工作区不同,因此我放弃了该项目。

I've tried creating a Console Application with roslyn, attaching it to the debugger and then run the generation code from it. But the VisualStudioWorkspace is only available inside VisualStudio (Not serializable and not avalaible througt DTE com interface). So the only solution left was using MBBuildWorkspace. Since it does not have that same behavior as Visual studio workspace, I've abandoned the project.

以下是我的代码供进一步参考:

Here's my code for further references :

Process vsProcess = Process.GetCurrentProcess();

string solutionPath = CurrentWorkspace.CurrentSolution.FilePath;

SyntaxTree syntaxTree = CSharpSyntaxTree.ParseText($@"
            using System;
            using System.Threading.Tasks;

            namespace CodeGenApplication
            {{
                public class Program 
                {{
                    public static void Main(string[] args) 
                    {{

                    Console.ReadLine();
                    int vsProcessId = Int32.Parse(args[0]);
                    CodeGenApp.Test(""{solutionPath.Replace(@"\", @"\\")}"", ""{projectName}"", ""{_codeGenProjectName}"");
                    Console.ReadLine();
                    }}
                }}
            }}");

string assemblyName = Path.GetRandomFileName();

Project codeGenProject = CurrentWorkspace.CurrentSolution.Projects.Where(x => x.Name == _codeGenProjectName).FirstOrDefault();

List<MetadataReference> references = codeGenProject.MetadataReferences.ToList();

CSharpCompilation compilation = CSharpCompilation.Create(

    assemblyName,
    syntaxTrees: new[] { syntaxTree },
    references: references,
    options: new CSharpCompilationOptions(OutputKind.ConsoleApplication));

// Emit assembly to streams.
EmitResult result = compilation.Emit("CodeGenApplication.exe", "CodeGenApplication.pdb");

if (!result.Success)
{
    IEnumerable<Diagnostic> failures = result.Diagnostics.Where(diagnostic =>
        diagnostic.IsWarningAsError ||
        diagnostic.Severity == DiagnosticSeverity.Error);
}
else
{
    Process codeGenProcess = new Process();
    codeGenProcess.StartInfo.FileName = "CodeGenApplication.exe";
    codeGenProcess.StartInfo.Arguments = vsProcess.Id.ToString();
    codeGenProcess.StartInfo.UseShellExecute = false;
    codeGenProcess.StartInfo.CreateNoWindow = true;
    codeGenProcess.StartInfo.LoadUserProfile = true;
    codeGenProcess.StartInfo.RedirectStandardError = true;
    codeGenProcess.StartInfo.RedirectStandardInput = true;
    codeGenProcess.StartInfo.RedirectStandardOutput = false;
    codeGenProcess.Start();
    foreach (EnvDTE.Process dteProcess in _dte.Debugger.LocalProcesses)
    {
        if (dteProcess.ProcessID == codeGenProcess.Id)
        {
            dteProcess.Attach();
        }
    }
    codeGenProcess.StandardInput.WriteLine("Start");
}

这篇关于如何在当前Visual Studio主机内部的Visual Studio扩展中调试用Roslyn编译的代码?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆