动态执行 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程序的功能: 二. 动态执行方法可能导致恶意攻击,因此使用时需要 ...
随机推荐
- js中将斜杠\替换的方法
js中将/替换的方法replace(/\//g, '-') 中间涉及到js的一些转义问题,试了几个方法,发现这个可以,就记下来.
- js值类型与引用类型
JavaScript值类型和引用类型有哪些 (1)值类型:数值.布尔值.null.undefined. (2)引用类型:对象.数组.函数. 三.如何理解值类型和引用类型及举例 我们可以用“连锁店”和“ ...
- Alpha 冲刺 (3/10)
队名 火箭少男100 组长博客 林燊大哥 作业博客 Alpha 冲鸭鸭鸭! 成员冲刺阶段情况 林燊(组长) 过去两天完成了哪些任务 协调各成员之间的工作 协助后端界面的开发 搭建项目运行的服务器环境 ...
- mysql字符集调整总结
字符集是一套符号和编码的规则,不论是在oracle数据库还是在mysql数据库,都存在字符集的选择问题.对于数据库来说,字符集又是比较重要的,因为数据库存储的数据大部分都是各种文字,字符集对于数据库的 ...
- 2018.10.24 bzoj3195: [Jxoi2012]奇怪的道路(状压dp)
传送门 f[i][j][k]f[i][j][k]f[i][j][k]表示前iii个点连了jjj条边,第i−K+1i-K+1i−K+1~iii个点连边数的奇偶性为kkk时的方案数. 转移规定只能从后向前 ...
- 查看MySQL语句变量了多少行数据
explain MySQL语句 列如 explain SELECT * FROM 表名 WHERE id=1;
- (9)How to take a picture of a black hole
https://www.ted.com/talks/katie_bouman_what_does_a_black_hole_look_like/transcript 00:13In the movie ...
- java Concurrent包学习笔记(一):ExecutorService
一.介绍 ExecutorService是java.util.concurrent包中的一个线程池实现接口.其有两个实现类: 1)ThreadPoolExecutor:普通线程池通过配置线程池大小,能 ...
- 实例讲解Silverlight 初始控件如何获得焦点
这个问题本来是在我实际的项目中遇到过的,但这其实是当初项目要求,要求一进入就要使得在用户名那个文字框中聚焦,而不是再用鼠标去点击获得焦点,后来自己费了点时间解决了.本来我没太注意就过去了,没想到在QQ ...
- 大压力下Redis参数调整要点
调整以下参数,可以大幅度改善Redis集群的稳定性: 为何大压力下要这样调整? 最重要的原因之一Redis的主从复制,两者复制共享同一线程,虽然是异步复制的,但因为是单线程,所以也十分有限.如果主从间 ...