动态执行 VB.NET 和 C# 代码
有时候我们需要尝试动态地与一些代码进行交互,而不是只能执行程序内已编死的代码,那该怎么办呢?
我首先推荐各种脚本语言,如Javascript、Lua、Python等等,这些脚本语言有很多优秀的第三方类库,可以很方便的与 .NET 系统集成,让我们的程序中执行动态代码。
但如果你一定想用VB.NET或者C#的代码来运行一段程序,这里就要用到动态编译的功能了。
下面是我写的两个实例,你只需要在窗体 FormMain
中添加一个 button
和一个 textbox
即可,默认名为 Button1
、TextBox1
。
VB.NET代码
Imports System.CodeDom.Compiler Imports System.Reflection Public Class FormMain Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click ' 编译参数 Dim cpars As New CompilerParameters ' 编译参数,如 /optimize /removeintchecks 等 cpars.CompilerOptions = "/optimize " cpars.GenerateInMemory = True '在内存中编译而不输出文件 cpars.GenerateExecutable = False '并不输出执行文件 cpars.IncludeDebugInformation = False '不需要调试信息 ' 导入类库(根据自己代码的需要导入) cpars.ReferencedAssemblies.Add("mscorlib.dll") cpars.ReferencedAssemblies.Add("System.dll") cpars.ReferencedAssemblies.Add("System.Data.dll") cpars.ReferencedAssemblies.Add("System.Deployment.dll") cpars.ReferencedAssemblies.Add("System.Drawing.dll") cpars.ReferencedAssemblies.Add("System.Windows.Forms.dll") cpars.ReferencedAssemblies.Add("System.Xml.dll") cpars.ReferencedAssemblies.Add("Microsoft.VisualBasic.dll") ' 编译参数,为导入的类库设置全局引用(否则必须使用完整的命名空间名称才能正确调用函数) cpars.CompilerOptions &= " /imports:" & _ "Microsoft.VisualBasic," & _ "System," & _ "System.Collections," & _ "System.Collections.Generic," & _ "System.Drawing," & _ "System.Windows.Forms" ' 设置编译器 Dim vbc As New VBCodeProvider 'Dim vbc = CodeDomProvider.CreateProvider("VisualBasic") '等效方法 ' 一个简单的模板类 Dim codex As String = _ "Public Class CompClass" & vbCrLf & _ " Shared Function RunCode() As Object" & vbCrLf & _ " '$" & vbCrLf & _ " End Function" & vbCrLf & _ "End Class" ' 替换代码到模板类中 Dim code As String = codex.Replace("'$", TextBox1.Text) ' 编译并返回 Dim resut As CompilerResults = vbc.CompileAssemblyFromSource(cpars, code) ' 如果发生了错误 Then ).ToString) Return End If ' 尝试调用代码 Dim asm As Assembly = resut.CompiledAssembly '获取程序集 ' 获取我们编写的静态方法 Dim mi As MethodInfo = asm.GetType("CompClass").GetMethod("RunCode") ' 执行代码,并获取返回值 Dim ret As Object = mi.Invoke(Nothing, Nothing) ' 对返回值进行处理 If ret IsNot Nothing Then MsgBox(ret.ToString) End If End Sub End Class
执行程序,在 Textbox1 里写入一些VB代码,按 Button1 即可立即执行里面的代码。
如果拥有返回值,程序还可以获取代码的返回值,但有可能需要你进行拆箱处理。
C#代码
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Text; using System.Windows.Forms; using System.Reflection; using System.CodeDom.Compiler; namespace WindowsFormsApplication1 { public partial class FormMain : Form { public FormMain() { InitializeComponent(); } private void Button1_Click(object sender, EventArgs e) { // 编译参数 var cpars = new CompilerParameters(); cpars.CompilerOptions = "/optimize "; cpars.GenerateInMemory = true; cpars.GenerateExecutable = false; cpars.IncludeDebugInformation = false; // 导入类库(根据自己代码的需要导入) cpars.ReferencedAssemblies.Add("mscorlib.dll"); cpars.ReferencedAssemblies.Add("System.dll"); cpars.ReferencedAssemblies.Add("System.Data.dll"); cpars.ReferencedAssemblies.Add("System.Deployment.dll"); cpars.ReferencedAssemblies.Add("System.Drawing.dll"); cpars.ReferencedAssemblies.Add("System.Windows.Forms.dll"); cpars.ReferencedAssemblies.Add("System.Xml.dll"); // 编译器实例 var csc = new Microsoft.CSharp.CSharpCodeProvider(); //var csc = CodeDomProvider.CreateProvider("CSharp"); // 一个简单的模板类 // 因为C#的编译器无法设置全局命名空间,所以需要在代码中导入命名空间 var codex = @" using System; using System.Collections; using System.Collections.Generic; using System.Text; using System.Drawing; using System.Windows.Forms; class CompClass{ static public object RunCode(){ //$ return null; } } "; // 替换代码到模板类中 var code = codex.Replace("//$", TextBox1.Text); // 编译并返回 var resut = csc.CompileAssemblyFromSource(cpars, code); // 错误警告 ) { MessageBox.Show(resut.Errors[].ToString()); return; } // 调用代码 var asm = resut.CompiledAssembly; var mi = asm.GetType("CompClass").GetMethod("RunCode"); object ret = mi.Invoke(null, null); if (ret != null) { MessageBox.Show(ret.ToString()); } } } }
C#的代码流程与VB的基本相同,区别在于C#的编译器没有导入全局命名空间的参数,因此需要在模板类里写入你需要导入的命名空间。
其他的用法基本都一样。
PS: 我有空再写一点与第三方脚本库进行交互的代码示例。
动态执行 VB.NET 和 C# 代码的更多相关文章
- C#动态执行代码
在开始之前,先熟悉几个类及部分属性.方法:CSharpCodeProvider.ICodeCompiler.CompilerParameters.CompilerResults.Assem ...
- (转+整理)C#中动态执行代码
通过微软提供的CSharpCodeProvider,CompilerParameters,CompilerResults等类,可以在运行时,动态执行自己写的代码文件.原理就是把你的代码文件动态编译成e ...
- 动态执行文本vba代码
动态执行文本vba代码 Public Sub StringExecute(s As String) Dim vbComp As Object Set vbComp = ThisWorkbook.VBP ...
- Javascript动态执行JS(new Function与eval比较)
new Function与eval可以动态执行JS,只要把拼接好的JS方法,然后以字符串的形式传入到这两个函数,可以执行,其中new Function用在模板引擎比较多. 用 Function 类直接 ...
- PHP 动态执行
PHP 动态执行 在页面上直接输入代码,点击执行,返回执行结果 方法很简单,主要使用了 $newfunc = create_function('', $code); 函数来实现. 代码如下: < ...
- JDK1.8中如何用ScriptEngine动态执行JS
JDK1.8中如何用ScriptEngine动态执行JS jdk1.6开始就提供了动态脚本语言诸如JavaScript动态的支持.这无疑是一个很好的功能,毕竟Java的语法不是适合成为动态语言.而JD ...
- 【05】Firebug动态执行JavaScript
Firebug动态执行JavaScript 您可以使用Firebug来编写并实时执行一个JavaScript. 这是为了测试,并确保该脚本工作正常,这是将JavaScript代码部署在生产环境前的好方 ...
- 根据数据库记录动态生成C#类及其公共属性并动态执行的解决方案
原文:根据数据库记录动态生成C#类及其公共属性并动态执行的解决方案 问题: C#中,想动态产生这么一个类: public class StatisticsData { public ...
- 第6.6节 Python动态执行小结
一. Python动态执行支持通过输入数据流或文件传入Python源代码串,进行编译后执行,可以通过这种方式扩展Python程序的功能: 二. 动态执行方法可能导致恶意攻击,因此使用时需要 ...
随机推荐
- 第一次java实验报告
实验一Java开发环境的熟悉-1 步骤: mkdir +20165213exp1创建20165213exp1这个目录 cd +20165213zqh进入这个目录 mkdir+src+bin创建目录sr ...
- nginx指令中的优化(配置文件)
nginx指令中的优化(配置文件)worker_processes 8; nginx进程数,建议按照cpu数目来指定,一般为它的倍数.worker_cpu_affinity 00000001 0000 ...
- 用visual studio 2017来调试python
https://www.visualstudio.com/zh-hans/thank-you-downloading-visual-studio/?sku=Professional&rel=1 ...
- 在win8 App中,StorageFile比Path更好用
Skip the path: stick to the StorageFile: http://blogs.msdn.com/b/wsdevsol/archive/2012/12/05/stray-f ...
- 【Erlang】源码安装
Erlang介绍 Erlang(['ə:læŋ])是一种通用的面向并发的编程语言,它由瑞典电信设备制造商爱立信所辖的CS-Lab开发,目的是创造一种可以应对大规模并发活动的编程语言和运行环境. Erl ...
- spring学习七 spring和dynamic project进行整合
spring和web项目进行整合,其实就是在项目启动时,就创建spring容器,然后在servlet中使用spring容器进行开. 注意:为了页面可以访问到servlet,因此servlet必须放进t ...
- one or more
想到以后如果一直都是这样,那么以后的生活是多么多么可怕啊. 感觉毫无期盼.没有意义. 如果变得理所当然那是多么多么让人害怕的事,吓得让人发抖. 所以在以后漫长的岁月里,还是一个人吧 如果相互看不惯,感 ...
- Java语法基础课 原码 反码 补码
原码就是符号位加上真值的绝对值, 即用第一位表示符号, 其余位表示值. 反码的表示方法是:正数的反码是其本身:负数的反码是在其原码的基础上, 符号位不变,其余各个位取反. 补码的表示方法是在反码的基础 ...
- 将驼峰转化为下化线(将型如AbcDef转化为abc_def)
strtolower(preg_replace('/((?<=[a-z])(?=[A-Z]))/', '_', 'AbcDef'))
- p标签在div中垂直居中,并且div高度随着p标签文字内容的变化而变化
1.div设置flex布局 div{ display: flex; align-items: center; } 2.div不要设置height,设置min-height