如何在当前Visual Studio主机内部的Visual Studio扩展中调试用Roslyn编译的代码?

玛莉·莱米尔(Maly Lemire)

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

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

    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());

            }
        }
    }

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

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

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

玛莉·莱米尔(Maly Lemire)

似乎实际上是不可能的。

当前的Visual Studio实例无法调试自身。

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

这是我的代码,供进一步参考:

Process vsProcess = Process.GetCurrentProcess();

string solutionPath = CurrentWorkspace.CurrentSolution.FilePath;

SyntaxTree syntaxTree = CSharpSyntaxTree.ParseText([email protected]"
            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");
}

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

visual studio代码:如何在当前文件中进行不区分大小写的搜索?

在当前的Visual Studio 2013中运行Visual Studio 2008

如何防止Visual Studio Code在当前选项卡中打开文件?

Visual Studio 2013在当前选择中查找和替换

如何在Visual Studio代码中调试打字稿文件

如何在当今的Visual Studio中打开空白应用程序(XAML)?- C#

如何在Visual Studio中编译Objective-C代码

如何在Visual Studio代码中安装扩展

使用批处理文件在当前文件夹中运行Visual Studio代码

如何在CMake for Visual Studio中获取当前配置(发布/调试)

如何在visual studio中调试python

如何在Visual Studio 2015中使用roslyn C#编译器?

在Visual Studio中调试exe代码

无法在Visual Studio代码中调试Go

如何在 Visual Studio Code Remote - SSH 扩展中确认新的远程主机密钥?

在Visual Studio 2013中使用Roslyn编译器

如何在Visual Studio代码(VS代码)中选择当前单词?

您可以在Visual Studio Code中在当前行周围添加边框吗

如何在Visual Studio Code上调试Ruby代码?

如何在Visual Studio 2017中禁用Roslyn语言服务?

收到错误消息“扩展主机意外终止。” 在Visual Studio代码中

如何在Visual Studio 2010中从Linux进行远程编译和调试

如何在Visual Studio代码中使用特定的端口和本地主机调试django Web应用程序?

如何在Visual Studio中进行调试期间查找WPF / C#中当前预订事件的所有方法

什么是Visual Studio 2015中的“ Roslyn代码修复”?

是否可以在Visual Studio包中逐步浏览Roslyn代码

在Visual Studio中使用自编译的Roslyn?

Roslyn编译失败,但与Visual Studio兼容

如何使用Visual Studio代码调试Django