在运行时创建可执行程序集

问题描述 投票:0回答:1

如何将单个代码作为字符串编译为工作且独立的 .exe 文件?我尝试了三种不同的方法:

  • CSharpCodeProvider
    :这工作正常,但我需要它用于较新的.NET 7,并且此解决方案不适用于此版本。
  • CSharpScript
    :这也可以正常工作,但我需要将实际生成的程序集存储到磁盘上的工作 .exe 文件中。
  • CSharpCompiler
    :我想我需要这个,但是,我无法让它工作,我仍然在引用方面遇到一些问题。

有没有办法自动添加这些引用?总是,当我添加引用时,它会报告缺少另一个引用。

我正在使用的代码,但不起作用。

using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using System.Reflection;

var code = """
    using System;

    // Just a demo program.
    Console.WriteLine("Hello, World!");
    """;

var compilation = CSharpCompilation.Create("DynamicCode")
    .WithOptions(new CSharpCompilationOptions(OutputKind.ConsoleApplication))
    .AddReferences(
        MetadataReference.CreateFromFile(Assembly.Load("System.Private.CoreLib").Location),
        MetadataReference.CreateFromFile(Assembly.Load("System").Location)
    )
    .AddSyntaxTrees(SyntaxFactory.ParseSyntaxTree(code));

// Note: I also tried adding references using the typeof keyword,
// so like typeof(object).Assembly.Location, but that also didn't work.

using var stream = new MemoryStream();
var emitResult = compilation.Emit(stream);

if (emitResult.Success)
{
    var exePath = "DynamicCode.exe";
    File.WriteAllBytes(exePath, stream.ToArray());
    Console.WriteLine($"DynamicCode.exe saved successfully.");
}
else
{
    Console.WriteLine("Failed:");
    foreach (var diagnostic in emitResult.Diagnostics)
    {
        Console.WriteLine(diagnostic);
    }
}

我从输出中得到了什么(编译时):

(4,1): error CS0103: Console name does not exist in the current context.

当我使用以下引用而不是在代码中使用时:

var compilation = CSharpCompilation.Create("DynamicCode")
    .WithOptions(new CSharpCompilationOptions(OutputKind.ConsoleApplication))
    .AddReferences(AppDomain.CurrentDomain.GetAssemblies().Select(x => MetadataReference.CreateFromFile(x.Location)))
    .AddSyntaxTrees(SyntaxFactory.ParseSyntaxTree(code));

我在运行应用程序时收到此消息,加上输出程序集约为 3kB,这对我来说似乎很奇怪:

Unhandled Exception: System.IO.FileNotFoundException: Unable to load file or assembly System.Private.CoreLib, Version=7.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e, or one of its dependencies. The system cannot find the specified file.

那么我做错了什么吗?有没有一种自动添加引用的方法,或者一些“更好”的添加引用的方法?我尝试了诸如ChatGPT之类的东西,但它没有帮助我,所以我不知道问题出在哪里。

如果实际的解决方案有效,是否有办法将程序集编译成.NET Framework v4.7.2?我想保持与旧平台的兼容性,但我的项目是用.NET 7编码的,所以

CSharpCodeProvider
无法使用。

c# roslyn
1个回答
0
投票

回答1个问题: 要使用控制台调用,您可能需要库的链接

System.Console

问题 2 的回答:我使用类似的方法来获取库的路径:

var path = Path.GetDirectoryName(typeof(object).Assembly.Location)!;
var consoleAssemblyPath = Path.Combine(DefaultAssemblysPath, "System.Console.dll");
var rumtimeAssemblyPath = Path.Combine(DefaultAssemblysPath, "System.Runtime.dll");
© www.soinside.com 2019 - 2024. All rights reserved.