运行时从字符串到控制台 exe 的代码生成在 C# .NET6 中不起作用
Codegeneration at runtime from a string to console exe is not working in C# .NET6
我有一些代码必须能够在运行时生成控制台应用程序(使用 System.CodeDom 进行代码生成)。我已经做了很多次了,但是在 NET 6 中,现在我正在为它和新的 API 而苦苦挣扎。在下面的代码中,我尝试简单地从一个字符串进行编译。请参阅下面的静态 class 方法 Start() 然后应该生成应用程序。
编译看起来不错,最后没有错误。但是当启动生成的AppCodegenerated.exe时,它显示了一些引用异常System.Runtime。
请帮忙,有什么想法吗?已经研究了很多但找不到任何有用的解决方案..
//-
我使用了 Visual Studio 2022 / NET 6 和论文 Nuget 的:
using Basic.Reference.Assemblies;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.Text;
using System.Text;
namespace CompilerSimplified
{
public static class Compiler
{
public static bool Start()
{
string FileName = "AppCodegenerated";
string ExePath = AppDomain.CurrentDomain.BaseDirectory + @"\" + FileName + ".exe";
string code = @"using System; Console.WriteLine(""Hello.""); Console.ReadLine(); ";
// ------- References -------------
// .net platform references
List<MetadataReference> References = new List<MetadataReference>();
foreach (var item in ReferenceAssemblies.Net60) // ReferenceAssemblies from Nuget: Basic.Reference.Assemblies;
References.Add(item);
// or tried this: loop manually through system platform
//string[] fileEntries = Directory.GetFiles(@"C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref.0.0\ref\net6.0\", "*.dll");
//foreach (string fileName in fileEntries)
// references.Add(MetadataReference.CreateFromFile(fileName));MetadataReference.CreateFromFile(fileName));
// ------- References END -------------
// delete existing file
if (File.Exists(ExePath))
File.Delete(ExePath);
// compiler options
CSharpCompilationOptions DefaultCompilationOptions =
new CSharpCompilationOptions(outputKind: OutputKind.ConsoleApplication, platform: Platform.AnyCpu)
.WithOverflowChecks(true).WithOptimizationLevel(OptimizationLevel.Release);
// encode soucre code
string sourceCode = SourceText.From(code, Encoding.UTF8).ToString();
// CSharp options
var parsedSyntaxTree = Parse(sourceCode, "", CSharpParseOptions.Default.WithLanguageVersion(LanguageVersion.CSharp10));
// compilation
var compilation = CSharpCompilation.Create(FileName, new SyntaxTree[] { parsedSyntaxTree }, references: References, DefaultCompilationOptions);
var result = compilation.Emit(ExePath);
// return
if (result.Success)
return true;
else
return false;
}
private static SyntaxTree Parse(string text, string filename = "", CSharpParseOptions options = null)
{
var stringText = SourceText.From(text, Encoding.UTF8);
return SyntaxFactory.ParseSyntaxTree(stringText, options, filename);
}
}
}
以上代码运行良好,没有错误,并将 AppCodegenerated.exe 导出到项目 /bin 文件夹中。
执行此生成的 AppCodegenerated.exe 在输出控制台上显示以下内容:
Unhandled exception: System.IO.FileNotFoundException:
The file or assembly "System.Runtime, Version = 6.0.0.0, Culture = neutral,
PublicKeyToken = b03f5f7f11d50a3a" or a dependency on it was not found.
The system can not find the stated file.
不可能像上面的初始方法那样直接代码生成控制台应用程序。一种可能的解决方案是首先生成一个 dll(我在上面的示例代码中提到的工作正常),然后从那里将该 .dll 包含到一个 .exe 中,从那里功能可以 运行.
我有一些代码必须能够在运行时生成控制台应用程序(使用 System.CodeDom 进行代码生成)。我已经做了很多次了,但是在 NET 6 中,现在我正在为它和新的 API 而苦苦挣扎。在下面的代码中,我尝试简单地从一个字符串进行编译。请参阅下面的静态 class 方法 Start() 然后应该生成应用程序。
编译看起来不错,最后没有错误。但是当启动生成的AppCodegenerated.exe时,它显示了一些引用异常System.Runtime。
请帮忙,有什么想法吗?已经研究了很多但找不到任何有用的解决方案..
//-
我使用了 Visual Studio 2022 / NET 6 和论文 Nuget 的:
using Basic.Reference.Assemblies;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.Text;
using System.Text;
namespace CompilerSimplified
{
public static class Compiler
{
public static bool Start()
{
string FileName = "AppCodegenerated";
string ExePath = AppDomain.CurrentDomain.BaseDirectory + @"\" + FileName + ".exe";
string code = @"using System; Console.WriteLine(""Hello.""); Console.ReadLine(); ";
// ------- References -------------
// .net platform references
List<MetadataReference> References = new List<MetadataReference>();
foreach (var item in ReferenceAssemblies.Net60) // ReferenceAssemblies from Nuget: Basic.Reference.Assemblies;
References.Add(item);
// or tried this: loop manually through system platform
//string[] fileEntries = Directory.GetFiles(@"C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref.0.0\ref\net6.0\", "*.dll");
//foreach (string fileName in fileEntries)
// references.Add(MetadataReference.CreateFromFile(fileName));MetadataReference.CreateFromFile(fileName));
// ------- References END -------------
// delete existing file
if (File.Exists(ExePath))
File.Delete(ExePath);
// compiler options
CSharpCompilationOptions DefaultCompilationOptions =
new CSharpCompilationOptions(outputKind: OutputKind.ConsoleApplication, platform: Platform.AnyCpu)
.WithOverflowChecks(true).WithOptimizationLevel(OptimizationLevel.Release);
// encode soucre code
string sourceCode = SourceText.From(code, Encoding.UTF8).ToString();
// CSharp options
var parsedSyntaxTree = Parse(sourceCode, "", CSharpParseOptions.Default.WithLanguageVersion(LanguageVersion.CSharp10));
// compilation
var compilation = CSharpCompilation.Create(FileName, new SyntaxTree[] { parsedSyntaxTree }, references: References, DefaultCompilationOptions);
var result = compilation.Emit(ExePath);
// return
if (result.Success)
return true;
else
return false;
}
private static SyntaxTree Parse(string text, string filename = "", CSharpParseOptions options = null)
{
var stringText = SourceText.From(text, Encoding.UTF8);
return SyntaxFactory.ParseSyntaxTree(stringText, options, filename);
}
}
}
以上代码运行良好,没有错误,并将 AppCodegenerated.exe 导出到项目 /bin 文件夹中。
执行此生成的 AppCodegenerated.exe 在输出控制台上显示以下内容:
Unhandled exception: System.IO.FileNotFoundException:
The file or assembly "System.Runtime, Version = 6.0.0.0, Culture = neutral,
PublicKeyToken = b03f5f7f11d50a3a" or a dependency on it was not found.
The system can not find the stated file.
不可能像上面的初始方法那样直接代码生成控制台应用程序。一种可能的解决方案是首先生成一个 dll(我在上面的示例代码中提到的工作正常),然后从那里将该 .dll 包含到一个 .exe 中,从那里功能可以 运行.