現在のVisualStudioホスト内のVisualStudio拡張機能でRoslynを使用してコンパイルされたコードをデバッグするにはどうすればよいですか?

マリーレミア

Roslynを使用して現在開いているソリューションでプロジェクトを取得し、コンパイルしてメソッドを実行するVisualStudio拡張機能があります。プロジェクトはプログラマーが変更できます。

現在のVisualStudioWorkspaceからVisualStudio拡張機能でプロジェクトを正常にコンパイルしました。

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

            }
        }
    }

次に、現在のドメインにアセンブリを読み込み、その型を取得してメソッドを呼び出すことができます。

問題は、ロードされたソリューションの現在の構成がデバッグである場合、プログラマーがブレークポイントを設定できるようにする必要があることです。

拡張機能から現在のVisualStudioホストでコードを実行し、現在のVisualStudioインスタンスでデバッグできるようにする必要があります。

マリーレミア

これは実際には不可能のようです。

現在のVisualStudioインスタンスはそれ自体をデバッグできません。

roslynを使用してコンソールアプリケーションを作成し、デバッガーにアタッチして、そこから生成コードを実行してみました。ただし、VisualStudioWorkspaceはVisualStudio内でのみ使用できます(シリアル化できず、DTE comインターフェイスを介して使用できません)。したがって、残った唯一の解決策はMBBuildWorkspaceを使用することでした。Visual Studioワークスペースと同じ動作をしないため、プロジェクトを中止しました。

これがさらなる参照のための私のコードです:

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");
}

この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。

侵害の場合は、連絡してください[email protected]

編集
0

コメントを追加

0

関連記事

Related 関連記事

ホットタグ

アーカイブ