如何编译用户输入的代码?

时间:2014-03-08 02:16:59

标签: vb.net compiler-construction interface

我需要创建一个简单的vb.net程序来运行用户输入的一段代码(也在vb.net中)。但我需要我的程序来编译和运行它。

任何人都知道如何做到这一点?

1 个答案:

答案 0 :(得分:2)

几年前我实际上写了一篇博文(链接如下)。以下示例来自2010年,今天可能有更好的方法来解决这个问题。可以在代码注释中找到更多解释。

本质:

  • 从文件中读取代码。
  • 创建VB.NET CodeProvider的实例
  • 创建编译器参数并将它们传递给编译器
  • 编译代码
  • 检查错误
  • 创建包含代码
  • 的类的实例
  • 创建参数以传递给我们的编译代码
  • 执行代码并查看结果

下面是一个用于在文本文件中执行代码并在TextBox中显示结果的示例,但可以轻松地用于解析文本框中的代码。 (更多信息请见vbCity Blog):

包含:

Imports System.IO   
Imports System.Reflection   
Imports System.CodeDom   
Imports System.CodeDom.Compiler   
Imports Microsoft.VisualBasic

<强>代码:

' Read code from file
Dim input = My.Computer.FileSystem.ReadAllText("Code.txt")

' Create "code" literal to pass to the compiler.
'
' Notice the <% = input % > where the code read from the text file (Code.txt) 
' is inserted into the code fragment.
Dim code = <code>
               Imports System
               Imports System.Windows.Forms

               Public Class TempClass
                   Public Sub UpdateText(ByVal txtOutput As TextBox)
                       <%= input %>
                   End Sub
               End Class
           </code>

' Create the VB.NET Code Provider.
Dim vbProv = New VBCodeProvider()
' Create parameters to pass to the compiler.
Dim vbParams = New CompilerParameters()
' Add referenced assemblies.
vbParams.ReferencedAssemblies.Add("mscorlib.dll")
vbParams.ReferencedAssemblies.Add("System.dll")
vbParams.ReferencedAssemblies.Add("System.Windows.Forms.dll")
vbParams.GenerateExecutable = False
' Ensure we generate an assembly in memory and not as a physical file.
vbParams.GenerateInMemory = True

' Compile the code and get the compiler results (contains errors, etc.)
Dim compResults = vbProv.CompileAssemblyFromSource(vbParams, code.Value)

' Check for compile errors
If compResults.Errors.Count > 0 Then

    ' Show each error.
    For Each er In compResults.Errors
        MessageBox.Show(er.ToString())
    Next

Else

    ' Create instance of the temporary compiled class.
    Dim obj As Object = compResults.CompiledAssembly.CreateInstance("TempClass")
    ' An array of object that represent the arguments to be passed to our method (UpdateText).
    Dim args() As Object = {Me.txtOutput}
    ' Execute the method by passing the method name and arguments.
    Dim t As Type = obj.GetType().InvokeMember("UpdateText", BindingFlags.InvokeMethod, Nothing, obj, args)

End If