ASP.net:如何运行Reflection.Type,并将结果输出到webform文本框中?

时间:2022-12-02 10:13:45

I've only been coding for a little over a year, so if I seem to be missing something obvious, feel free to explain.

我只编写了一年多的编码,所以如果我似乎错过了一些明显的东西,请随意解释。

I'm heading up a study group for my C# class, and want to put together an ASP.net page that can be run locally with VS and a browser, and where the user can build classes in the namespace, code a main method in a webform textbox, and see the output on the right side of the screen (like a web tutorial, except that security isn't a concern: I'm just going to throw a project up on Bitbucket).

我正在为我的C#类编写一个学习小组,并想组建一个可以在VS和浏览器本地运行的ASP.net页面,并且用户可以在命名空间中构建类,编写一个主方法一个webform文本框,并看到屏幕右侧的输出(就像一个网络教程,除了安全性不是一个问题:我只是想在Bitbucket上投放一个项目)。

So, I'm building, compiling, and instantiating a class and Main method, and have figured out how to access the DLL file created by the CompiilerResults, but I can't figure out how to execute the file from the code behind, or get any output into a string variable. I would settle for an execution, and seeing the results in the Console; the important thing is that the entered code has to run. Here is what I have (most of the commented code is there to test output):

所以,我正在构建,编译和实例化一个类和Main方法,并且已经找到了如何访问由CompiilerResults创建的DLL文件,但我无法弄清楚如何从后面的代码执行该文件,或者获取任何输出到字符串变量。我会满足于执行,并在控制台中看到结果;重要的是输入的代码必须运行。这是我的(大多数注释代码是测试输出):

The MasterPage:

MasterPage:

<%@ Master Language="C#" AutoEventWireup="true" CodeFile="MasterPage.master.cs" Inherits="MasterPage" %>


<!DOCTYPE html>

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title></title>
    <asp:ContentPlaceHolder id="head" runat="server">
    </asp:ContentPlaceHolder>
    <asp:ContentPlaceHolder ID="stylesheets" runat="server">
        <link rel="stylesheet" href="MasterPage.master.css" type="text/css" />
    </asp:ContentPlaceHolder>
</head>
<body>
    <div>
        <asp:ContentPlaceHolder ID="header" runat="server">

        </asp:ContentPlaceHolder>
    </div>
    <div>

        <asp:ContentPlaceHolder id="codeColumn" runat="server">

        </asp:ContentPlaceHolder>

        <asp:ContentPlaceHolder ID="outputColumn" runat="server">

        </asp:ContentPlaceHolder>
    </div>
    <form runat="server">
        <asp:Label ID="headerLabel" Font-Size="X-Large" runat="server"></asp:Label>
        <!-- User enters code here: -->
        <asp:TextBox ID="codeTextArea" TextMode="MultiLine" Columns ="50" Rows ="30" runat="server"></asp:TextBox>
        <!-- Results of code, or caught errors, should be output here: -->
        <asp:TextBox ID="outputTextArea" TextMode="MultiLine" Rows="30" runat="server"></asp:TextBox>
        <!-- Clicking the submit button should start the code behind to handle errors, and run clean code: -->
        <asp:Button ID="submitButton" Text="Run!" OnClick="submitButton_Click" runat="server" />
    </form>
    <div>
        <asp:ContentPlaceHolder ID="footer" runat="server">
            <asp:HyperLink NavigateUrl="~/Default.aspx" runat="server">First Tutorial</asp:HyperLink>
            <asp:HyperLink NavigateUrl="~/Default.aspx" runat="server">Next Tutorial</asp:HyperLink>
        </asp:ContentPlaceHolder>
    </div>
</body>
</html>

And the code behind:

而背后的代码:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using Microsoft.CSharp;
using System.CodeDom.Compiler;
using System.Reflection;

public partial class MasterPage : System.Web.UI.MasterPage
{
    protected void Page_Load(object sender, EventArgs e)
    {

    }
    protected void submitButton_Click(object sender, EventArgs e)
    {
        if (codeTextArea.Text != null)
        {
            // Build a class and assembly:
            CSharpCodeProvider provider = new CSharpCodeProvider();
            CompilerParameters parameters = new CompilerParameters();
            string codeString = @"using System;namespace StudyGroup { public class WebProgram { 

            private String _outputString = ""output""; public static void Main() { ";
            codeString += codeTextArea.Text;
            codeString += @" } } }";
            CompilerResults results = provider.CompileAssemblyFromSource(parameters, codeString);
            var path = results.PathToAssembly;

            // Output:

            string outputString = "";

            // Error handling:

            if (results.Errors.HasErrors)
            {
                outputString += "You haz errors:\n";
                foreach (CompilerError error in results.Errors)
                {
                    outputString += error.ErrorText;
                    outputString += "\n";
                }
                //throw new InvalidOperationException(outputString);
                outputTextArea.Text = outputString;
            }
            else
            {

                // Instantiate an instance and invoke Main method:

                var assembly = Assembly.LoadFrom(path);
                var program = assembly.GetType("StudyGroup.WebProgram");
                var instance = Activator.CreateInstance(program);
                var main = program.GetMethod("Main");
                main.Invoke(instance, null);

                // Add properties and methods of Type to output:

                outputString += instance.GetType();
                var methods = program.GetMethods();
                foreach(MethodInfo m in methods)
                {
                    outputString += m.Name;
                }
                var properties = program.GetProperties();
                foreach(PropertyInfo p in properties)
                {
                    outputString += p.Name;
                    outputString += p.GetMethod;
                }
                /*foreach (String s in results.Output)
                {
                    outputString += s;
                    outputString += "\n";
                }*/
                //outputString += Console.Out;

                // Output:

                Console.WriteLine(outputString);
                Console.ReadLine();
                outputTextArea.Text = outputString;
            }
        }
    }
}

2 个解决方案

#1


0  

I've gotten the program to run in the console without Reflection.Type, using System.Diagnostics.Process.Start, sending the path to the DLL (or EXE) file, retrieved by the CompilerResults. However, I can't get the Console output into a variable. I set Console.Out to a StreamWriter and then a TextWriter, but neither seemed to have any effect from within my code behind, and putting the code directly into the codeString var, and writing the Console output to file, threw an error (this file being used by another process). I can post updated code, if anybody is interested.

我已经让程序在没有Reflection.Type的控制台中运行,使用System.Diagnostics.Process.Start,将路径发送到由CompilerResults检索的DLL(或EXE)文件。但是,我无法将控制台输出变为变量。我将Console.Out设置为StreamWriter,然后设置为TextWriter,但是我的代码后面似乎都没有任何影响,并且将代码直接放入codeString var,并将Console输出写入文件,引发了错误(此文件)被另一个进程使用)。如果有兴趣的话,我可以发布更新的代码。

#2


0  

And, I think I've got it!

而且,我想我已经拥有了!

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using Microsoft.CSharp;
using System.CodeDom.Compiler;
using System.Reflection;
using System.IO;

public partial class MasterPage : System.Web.UI.MasterPage
{
    protected void Page_Load(object sender, EventArgs e)
    {

    }
    protected void submitButton_Click(object sender, EventArgs e)
    {
        if (codeTextArea.Text != null)
        {

            // Build a class and assembly:
            CSharpCodeProvider provider = new CSharpCodeProvider();
            CompilerParameters parameters = new CompilerParameters();
            parameters.GenerateExecutable = true;
            string codeString = @"using System; using System.IO; namespace StudyGroup { public class WebProgram {  private String _outputString = ""output""; public static void Main() {  ";
            codeString += codeTextArea.Text;
            codeString += @" } } }";
            CompilerResults results = provider.CompileAssemblyFromSource(parameters, codeString);
            var path = results.PathToAssembly;

            // Output:

            string outputString = "";

            // Error handling:

            if (results.Errors.HasErrors)
            {
                outputString += "You haz errors:\n";
                foreach (CompilerError error in results.Errors)
                {
                    outputString += error.ErrorText;
                    outputString += "\n";
                }
                //throw new InvalidOperationException(outputString);
                outputTextArea.Text = outputString;
            }
            else
            {

                // Instantiate an instance and invoke Main method:

                //var assembly = Assembly.LoadFrom(path);
                var process = new System.Diagnostics.Process();
                process.StartInfo.UseShellExecute = false;
                process.StartInfo.RedirectStandardOutput = true;
                process.StartInfo.FileName = path;

                process.Start();

                var moreOutput = process.StandardOutput.ReadToEnd();

                outputString += moreOutput;

                // Output:

                Console.WriteLine(outputString);
                Console.ReadLine();
                outputTextArea.Text = outputString;
            }
        }
    }
}

#1


0  

I've gotten the program to run in the console without Reflection.Type, using System.Diagnostics.Process.Start, sending the path to the DLL (or EXE) file, retrieved by the CompilerResults. However, I can't get the Console output into a variable. I set Console.Out to a StreamWriter and then a TextWriter, but neither seemed to have any effect from within my code behind, and putting the code directly into the codeString var, and writing the Console output to file, threw an error (this file being used by another process). I can post updated code, if anybody is interested.

我已经让程序在没有Reflection.Type的控制台中运行,使用System.Diagnostics.Process.Start,将路径发送到由CompilerResults检索的DLL(或EXE)文件。但是,我无法将控制台输出变为变量。我将Console.Out设置为StreamWriter,然后设置为TextWriter,但是我的代码后面似乎都没有任何影响,并且将代码直接放入codeString var,并将Console输出写入文件,引发了错误(此文件)被另一个进程使用)。如果有兴趣的话,我可以发布更新的代码。

#2


0  

And, I think I've got it!

而且,我想我已经拥有了!

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using Microsoft.CSharp;
using System.CodeDom.Compiler;
using System.Reflection;
using System.IO;

public partial class MasterPage : System.Web.UI.MasterPage
{
    protected void Page_Load(object sender, EventArgs e)
    {

    }
    protected void submitButton_Click(object sender, EventArgs e)
    {
        if (codeTextArea.Text != null)
        {

            // Build a class and assembly:
            CSharpCodeProvider provider = new CSharpCodeProvider();
            CompilerParameters parameters = new CompilerParameters();
            parameters.GenerateExecutable = true;
            string codeString = @"using System; using System.IO; namespace StudyGroup { public class WebProgram {  private String _outputString = ""output""; public static void Main() {  ";
            codeString += codeTextArea.Text;
            codeString += @" } } }";
            CompilerResults results = provider.CompileAssemblyFromSource(parameters, codeString);
            var path = results.PathToAssembly;

            // Output:

            string outputString = "";

            // Error handling:

            if (results.Errors.HasErrors)
            {
                outputString += "You haz errors:\n";
                foreach (CompilerError error in results.Errors)
                {
                    outputString += error.ErrorText;
                    outputString += "\n";
                }
                //throw new InvalidOperationException(outputString);
                outputTextArea.Text = outputString;
            }
            else
            {

                // Instantiate an instance and invoke Main method:

                //var assembly = Assembly.LoadFrom(path);
                var process = new System.Diagnostics.Process();
                process.StartInfo.UseShellExecute = false;
                process.StartInfo.RedirectStandardOutput = true;
                process.StartInfo.FileName = path;

                process.Start();

                var moreOutput = process.StandardOutput.ReadToEnd();

                outputString += moreOutput;

                // Output:

                Console.WriteLine(outputString);
                Console.ReadLine();
                outputTextArea.Text = outputString;
            }
        }
    }
}