RError.com

RError.com Logo RError.com Logo

RError.com Navigation

  • 主页

Mobile menu

Close
  • 主页
  • 系统&网络
    • 热门问题
    • 最新问题
    • 标签
  • Ubuntu
    • 热门问题
    • 最新问题
    • 标签
  • 帮助
主页 / 问题 / 918122
Accepted
trydex
trydex
Asked:2020-12-11 01:48:28 +0000 UTC2020-12-11 01:48:28 +0000 UTC 2020-12-11 01:48:28 +0000 UTC

如何从 Roslyn 的入口点执行代码

  • 772

需要做的是允许用户在我的服务器上执行 C# 代码(类似于dotnetfiddle.net)。Asp.net 核心应用程序。

有一种方法效果很好:

public static async Task<ScriptState<object>> ExecuteScriptAsync(string code, IEnumerable<Assembly> references,
    IEnumerable<string> usings)
{
    var options = ScriptOptions.Default.WithReferences(references).WithImports(usings);

    return await CSharpScript.RunAsync(code, options);
}

该方法的问题ExecuteScript是它将不再执行这样的代码:

class Program 
{
    public static void Main() 
    {
        throw new System.Exception();   
    }
}

如何使代码像在控制台应用程序中一样运行,即 方法Main是切入点?


更新

找到了这段代码。它可以工作,但是如果您添加到脚本中,它会因错误“当前上下文中不存在Console.WriteLine("hi")该名称”而中断。Console

var script = @"using System;
                public static class Program
                {
                    public static int Main(string[] args)
                    {
                        var x = 7 * 8;
                        return x;
                    }
                }";

var assemblyPath = Path.GetDirectoryName(typeof(object).Assembly.Location);
var refs = new List<PortableExecutableReference>
{
    MetadataReference.CreateFromFile(typeof(object).Assembly.Location),
    MetadataReference.CreateFromFile(Path.Combine(assemblyPath, "mscorlib.dll")),
    MetadataReference.CreateFromFile(Path.Combine(assemblyPath, "System.dll")),
    MetadataReference.CreateFromFile(Path.Combine(assemblyPath, "System.Core.dll")),
    MetadataReference.CreateFromFile(Path.Combine(assemblyPath, "System.Runtime.dll")),
    MetadataReference.CreateFromFile(Assembly.GetEntryAssembly().Location)
};

// Parse the script to a SyntaxTree
var syntaxTree = CSharpSyntaxTree.ParseText(script);
var options = new CSharpCompilationOptions(OutputKind.ConsoleApplication);
// Compile the SyntaxTree to a CSharpCompilation
var compilation = CSharpCompilation.Create("Script",
    new[] { syntaxTree },
    refs,
    new CSharpCompilationOptions(
        OutputKind.ConsoleApplication,
        optimizationLevel: OptimizationLevel.Release,
        assemblyIdentityComparer: DesktopAssemblyIdentityComparer.Default));

//CodeDomProvider codeDomProvider = new CodeDomProvider();
using (var outputStream = new MemoryStream())
using (var pdbStream = new MemoryStream())
{
    // Emit assembly to streams.
    var result = compilation.Emit(outputStream, pdbStream);
    if (!result.Success)
    {
        return;
    }

    // Load the emitted assembly.
    var assembly = Assembly.Load(outputStream.ToArray(), pdbStream.ToArray());

    // Invoke the entry point.
    var x = assembly.EntryPoint.Invoke(null, null);
c#
  • 1 1 个回答
  • 10 Views

1 个回答

  • Voted
  1. Best Answer
    MSDN.WhiteKnight
    2020-12-11T12:30:35Z2020-12-11T12:30:35Z

    Assembly.Load,尤其是从字节数组中,是一个非常糟糕的主意,因为它无法随后从内存中卸载程序集,即 在服务器应用程序中工作时,内存迟早会耗尽,并且必须重新启动服务器。另外,您如何限制您运行的代码的权限,以使其不会使您的系统崩溃?如果你的目标是 .NET Core,则应用域不可用。更正确的做法是将代码编译成文件,并在权限有限的用户下的新进程中运行,并截取其输出:

    using System;
    using System.Collections.Generic;
    using System.IO;
    using System.Diagnostics;
    using System.Reflection;
    using Microsoft.CodeAnalysis;
    using Microsoft.CodeAnalysis.CSharp;
    
    namespace RoslynTest
    {
        class Program
        {
            static void RunScript()
            {
                var script = @"using System;
                    public static class Program
                    {
                        public static int Main(string[] args)
                        {
                            var x = 7 * 8;
                            Console.WriteLine(x.ToString());
                            return x;
                        }
                    }";
    
                var assemblyPath = Path.GetDirectoryName(typeof(object).Assembly.Location);
                var refs = new List<PortableExecutableReference>
                {
                     MetadataReference.CreateFromFile(typeof(object).Assembly.Location),
                     MetadataReference.CreateFromFile(Path.Combine(assemblyPath, "mscorlib.dll")),
                     MetadataReference.CreateFromFile(Path.Combine(assemblyPath, "System.dll")),
                    MetadataReference.CreateFromFile(Path.Combine(assemblyPath, "System.Core.dll")),
                    MetadataReference.CreateFromFile(Path.Combine(assemblyPath, "System.Runtime.dll")),
                    MetadataReference.CreateFromFile(Assembly.GetEntryAssembly().Location)
                };
    
    
                // Parse the script to a SyntaxTree
                var syntaxTree = CSharpSyntaxTree.ParseText(script);
                var options = new CSharpCompilationOptions(OutputKind.ConsoleApplication);
                // Compile the SyntaxTree to a CSharpCompilation
                var compilation = CSharpCompilation.Create("Script",
                    new[] { syntaxTree },
                    refs,
                    new CSharpCompilationOptions(
                        OutputKind.ConsoleApplication,
                        optimizationLevel: OptimizationLevel.Release,                    
                        assemblyIdentityComparer: DesktopAssemblyIdentityComparer.Default)
                        );
    
                var result = compilation.Emit("script.exe");
                if (!result.Success)
                {
                    throw new ApplicationException("Cannot compile script");
                }            
    
                ProcessStartInfo psi = new ProcessStartInfo();
                psi.FileName = "script.exe";
                psi.UseShellExecute = false;
                psi.RedirectStandardOutput = true;
                psi.RedirectStandardInput = true; 
                psi.UserName = "Vasya";
                psi.Password = "123";
    
                var process = new Process();
                using (process)
                {
                    process.StartInfo = psi;                
                    process.Start();
    
                    while (!process.StandardOutput.EndOfStream)
                    {
                        string res = process.StandardOutput.ReadLine();                    
                        Console.WriteLine(res);
                    }
                }
            }
        }
    }
    

    该代码是为 .NET Framework / Windows 量身定制的,但我认为为 .NET Core 重新制作它并不难,因为使用的所有库都在 .NET Standard 中。从 .NET Core 2.1 开始,以不同用户身份运行进程应该可以在所有操作系统上的 .NET Core 中运行。


    笔记。.NET Core 3.0 引入了从内存中卸载程序集的功能,但这仍然不能解决安全问题。

    • 3

相关问题

Sidebar

Stats

  • 问题 10021
  • Answers 30001
  • 最佳答案 8000
  • 用户 6900
  • 常问
  • 回答
  • Marko Smith

    是否可以在 C++ 中继承类 <---> 结构?

    • 2 个回答
  • Marko Smith

    这种神经网络架构适合文本分类吗?

    • 1 个回答
  • Marko Smith

    为什么分配的工作方式不同?

    • 3 个回答
  • Marko Smith

    控制台中的光标坐标

    • 1 个回答
  • Marko Smith

    如何在 C++ 中删除类的实例?

    • 4 个回答
  • Marko Smith

    点是否属于线段的问题

    • 2 个回答
  • Marko Smith

    json结构错误

    • 1 个回答
  • Marko Smith

    ServiceWorker 中的“获取”事件

    • 1 个回答
  • Marko Smith

    c ++控制台应用程序exe文件[重复]

    • 1 个回答
  • Marko Smith

    按多列从sql表中选择

    • 1 个回答
  • Martin Hope
    Alexandr_TT 圣诞树动画 2020-12-23 00:38:08 +0000 UTC
  • Martin Hope
    Suvitruf - Andrei Apanasik 什么是空? 2020-08-21 01:48:09 +0000 UTC
  • Martin Hope
    Air 究竟是什么标识了网站访问者? 2020-11-03 15:49:20 +0000 UTC
  • Martin Hope
    Qwertiy 号码显示 9223372036854775807 2020-07-11 18:16:49 +0000 UTC
  • Martin Hope
    user216109 如何为黑客设下陷阱,或充分击退攻击? 2020-05-10 02:22:52 +0000 UTC
  • Martin Hope
    Qwertiy 并变成3个无穷大 2020-11-06 07:15:57 +0000 UTC
  • Martin Hope
    koks_rs 什么是样板代码? 2020-10-27 15:43:19 +0000 UTC
  • Martin Hope
    Sirop4ik 向 git 提交发布的正确方法是什么? 2020-10-05 00:02:00 +0000 UTC
  • Martin Hope
    faoxis 为什么在这么多示例中函数都称为 foo? 2020-08-15 04:42:49 +0000 UTC
  • Martin Hope
    Pavel Mayorov 如何从事件或回调函数中返回值?或者至少等他们完成。 2020-08-11 16:49:28 +0000 UTC

热门标签

javascript python java php c# c++ html android jquery mysql

Explore

  • 主页
  • 问题
    • 热门问题
    • 最新问题
  • 标签
  • 帮助

Footer

RError.com

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

帮助

© 2023 RError.com All Rights Reserve   沪ICP备12040472号-5