动态执行 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) ' 如果发生了错误 If resut.Errors.Count > 0 Then MsgBox(resut.Errors(0).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); // 错误警告 if (resut.Errors.Count > 0) { MessageBox.Show(resut.Errors[0].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: 我有空再写一点与第三方脚本库进行交互的代码示例。
低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
利用 LibWebP-NET 解码与编码 WebP 格式图片
原文: 利用 LibWebP-NET 解码与编码 WebP 格式图片 WebP 格式是谷歌开发并发展的一种最新的网络图片格式,具有压缩率高、解码快、免版权、开源等优点。 大部分先进的网页浏览器、图片浏览器都支持该格式,Windows用户可以通过安装 WebP Codecfor Windows 在系统中查阅WebP图片。 虽然 WebP 是开源格式,但目前 .NET 平台对 WebP 的支持并不好,只能依靠第三方的类库来加载 WebP 格式。 在这里我推荐 LibWebP-NET 这个开源类库,可以在 .NET 中对 WebP 图片进行解码和编码。 LibWebP-NET 只是简单的对于WebP的C++类库的一个.NET封包,其核心代码仍在 libwebp.dll 这个动态链接库文件中,因此不支持在普通的ASP.NET空间中运行。 并且因为动态链接库对于系统的限制,因此有x86和x64两个版本的C++类库文件,应用于不同的操作系统。 我个人推荐您在.NET工程属性的编译选项中,使用x86兼容模式,这样只需要附上x86版的 libwebp.dll 文件即可。 下面的测试代码,为我修改版的...
- 下一篇
C# 获取当前屏幕的宽高和位置
上一篇博客《C# 获取当前屏幕DPI》,介绍了如何获取当前屏幕的DPI设置 本章主要介绍如何获取当前窗口所在屏幕的信息 当前屏幕信息 如果当前是单屏幕,可以直接获取主屏幕 var primaryScreen = Screen.PrimaryScreen; 如果当前是多屏,建议通过窗口句柄获取Screen信息 var window = Window.GetWindow(ExportButton);//获取当前主窗口 var intPtr = new WindowInteropHelper(window).Handle;//获取当前窗口的句柄 var screen = Screen.FromHandle(intPtr);//获取当前屏幕 获取屏幕高宽/位置 DpiPercent DPI转换比例常量,DpiPercent = 96; 为何DpiPercent为96 ?有一个概念“设备无关单位尺寸”,其大小为1/96英寸。比如: 【物理单位尺寸】=1/96英寸 * 96dpi = 1像素; 【物理单位尺寸】=1/96英寸 * 120dpi = 1.25像素; 关于WPF单位和系统DPI,可以参...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- Docker使用Oracle官方镜像安装(12C,18C,19C)
- CentOS7,CentOS8安装Elasticsearch6.8.6
- CentOS6,CentOS7官方镜像安装Oracle11G
- CentOS7编译安装Cmake3.16.3,解决mysql等软件编译问题
- SpringBoot2编写第一个Controller,响应你的http请求并返回结果
- CentOS8编译安装MySQL8.0.19
- SpringBoot2配置默认Tomcat设置,开启更多高级功能
- Windows10,CentOS7,CentOS8安装Nodejs环境
- Docker快速安装Oracle11G,搭建oracle11g学习环境
- CentOS8,CentOS7,CentOS6编译安装Redis5.0.7