有关Vb的CodeDom动态编译
来源:互联网 发布:喜马拉雅山攀登 知乎 编辑:程序博客网 时间:2024/06/06 11:40
本人对于代码什么的完全是个渣滓,写的不好也希望不要见怪。
在使用VB6时,想要动态编译的话大部分人会选择Script Control控件,用Windows脚本宿主运行VBS来代替Vb部分功能,从而实现动态编译。然而,VBS毕竟是脚本语言,在各个方面上都有很大的限制,在VB.NET甚至后续去除.NET标签的VB中使用这种方法,局限性被再次放大,很多人开始寻找新的方法。
现在在.NET平台上动态编译已经有CodeDom这种选择了,个人有一次需要动态编译就在网上查了些资料,基本上都是有看没有懂。但在看了有一个关于使用vbc.exe编译的时候突然有所体会。
想使用CodeDom进行动态编译,需要了解两个货色:VBCodeProvider与CompilerParameters。去掉各种难懂的语言通俗地讲,前者是编译器,后者是用来设置的。编译的时候肯定要设置许多编译属性,所以CompilerParameters是主要的操作对象,而VBCodeProvider用作于设置完成后一键编译。这些内容需要了解,不然可能New了这个又New那个,还是没什么成色。所以,就先新建一个类,起名为VBPro,写入:
Imports System.CodeDom.CompilerPublic Class VBPro Dim VBProvid As New VBCodeProvider() Dim VBComp As New CompilerParametersEnd Class
既然VBComp是主要的操作对象,就来了解基本要用的VBComp的成员或方法:
GenerateExecutable(Boolean):编译成直接的可执行文件(exe)还是间接的可执行文件(dll)
GenerateInMemory(Boolean):是否在内存中生成
OutputAssembly(String):输出路径
ReferencedAssemblies.Add:添加引用的程序集
CompilerOptions(String):汇编选项,可以理解为命令行参数
了解了大概后,可以写一个公共方法来进行编译:
Imports System.CodeDom.CompilerPublic Class VBPro Dim VBProvid As New VBCodeProvider() Dim VBComp As New CompilerParameters Public Sub BuildProgram(SourcePath As String, BuildPath As String) End SubEnd Class
用SourcePath指示源代码文件,BuildPath指示输出文件,然后就可以把刚刚了解的一些成员加进去:
Imports System.CodeDom.CompilerPublic Class VBPro Dim VBProvid As New VBCodeProvider() Dim VBComp As New CompilerParameters Public Sub BuildProgram(SourcePath As String, BuildPath As String) VBComp.GenerateExecutable = True '生成EXE文件而不是DLL VBComp.GenerateInMemory = False '生成真实的文件而不是在内存中生成 VBComp.OutputAssembly = BuildPath '确定生成路径 VBComp.ReferencedAssemblies.Add("System.dll") '引用System程序集 End SubEnd Class
该设置的都差不多了,那如何进行最重要的编译呢?要知道,如果没有编译这一句,其实上面的可以说是没什么用。编译比想象中的简单,就一句话:
Dim VBPrg As CompilerResults = VBProvid.CompileAssemblyFromFile(VBComp, SourcePath)
选取路径为SourcePath的源代码文件进行编译,VBPrg代表此次编译的程序。为了防止编译时因为源代码文件代码的书写错误,还可以加上错误检测,总体就是:
Imports System.CodeDom.CompilerPublic Class VBPro Dim VBProvid As New VBCodeProvider() Dim VBComp As New CompilerParameters Public Sub BuildProgram(SourcePath As String, BuildPath As String) VBComp.GenerateExecutable = True '生成EXE文件而不是DLL VBComp.GenerateInMemory = False '生成真实的文件而不是在内存中生成 VBComp.OutputAssembly = BuildPath '确定生成路径 VBComp.ReferencedAssemblies.Add("System.dll") '引用System程序集 Dim VBPrg As CompilerResults = VBProvid.CompileAssemblyFromFile(VBComp, SourcePath) If VBPrg.NativeCompilerReturnValue = 0 Then Else For Each ErIm As CompilerError In VBPrg.Errors MsgBox(ErIm.ErrorText, vbCritical, "编译错误 ") Next End If End SubEnd Class
这样就可以生成了,这里的代码面向的是.NET Framework 4.5+,较低的版本编译的时候可能会生成在默认的随机隐藏路径,这个时候就要用MoveFile剪切过去。
在SourcePath指向的路径中可以写下一些代码,如:
Imports System.Windows.FormsModule Module1 Sub Main MessageBox.Show("Hello World") End SubEnd Module
需要注意的是,它默认没有引用程序集,所以要手动Imports。最后生成运行,会发现其他的地方都还好,就是生成的是控制台应用,可能有些人会反感。下面的例子让VB编译器生成WindowsForm窗体程序:
Imports System.CodeDom.CompilerPublic Class VBPro Dim VBProvid As New VBCodeProvider() Dim VBComp As New CompilerParameters Public Sub BuildProgram(SourcePath As String, BuildPath As String) VBComp.GenerateExecutable = True '生成EXE文件而不是DLL VBComp.GenerateInMemory = False '生成真实的文件而不是在内存中生成 VBComp.OutputAssembly = BuildPath '确定生成路径 VBComp.ReferencedAssemblies.Add("System.dll") '引用System程序集 VBComp.CompilerOptions = ("/target:winexe") '命令参数 Dim VBPrg As CompilerResults = VBProvid.CompileAssemblyFromFile(VBComp, SourcePath) If VBPrg.NativeCompilerReturnValue = 0 Then Else For Each ErIm As CompilerError In VBPrg.Errors MsgBox(ErIm.ErrorText, vbCritical, "编译错误 ") Next End If End SubEnd Class
只是多了“命令参数”这一段,就可以生成窗体程序,对应的有
/target:exe
/target:winexe
/target:library
/target:module
共四种编译模式。窗体程序也是默认不带窗体,因为VS给的是模板而这里是空的,需要WithEvents之类的手动生成完整的一个窗体。然而问题还没有解决完成,运行后发现窗体会一闪而过,就是执行完全部代码自动退出而不保留窗体。这就不是编译的问题了,而是我们习惯用"Show"启动窗体的关系,要在选取的源代码文件上做文章:
Imports System.Windows.FormsModule Module1 Public WithEvents Form1 As New Form Public WithEvents Butn1 As New Button Sub Main() Form1.Visible = True 'Form1.Show() 不使用"Show",换成下面的: Application.Run(Form1) End Sub Private Sub Form1_Load() Handles Form1.Load Form1.Controls.Add(Butn1) End Sub Private Sub Butn1_Click() Handles Butn1.Click MessageBox.Show("Hello World") End SubEnd Module
窗体就不会自动卸载了,同时由于不是模板的关系,XP视觉效果自动关闭,要在过程中添加。完整的就是:
Imports System.Windows.FormsModule Module1 Public WithEvents Form1 As New Form Public WithEvents Butn1 As New Button Sub Main() Application.EnableVisualStyles() '添加XP视觉效果(XPManifest) Form1.Visible = True 'Form1.Show() 不使用"Show",换成下面的: Application.Run(Form1) End Sub Private Sub Form1_Load() Handles Form1.Load Form1.Controls.Add(Butn1) End Sub Private Sub Butn1_Click() Handles Butn1.Click MessageBox.Show("Hello World") End SubEnd Module
将视觉效果(XPManifest)添加上去后,一个简单的CodeDom动态编译器就算是完成了。
写的很渣,有什么描述错误的地方也希望大家提出来,我也会进行改正。
- 有关Vb的CodeDom动态编译
- 简单利用CodeDom动态编译的例子
- CodeDOM动态生成与编译
- 使用CODEDOM动态实现代码的生成,编译
- 使用 .Net Framework 的 System.CodeDom 命名空间动态生成源代码并编译
- 利用CodeDom和反射动态编译并执行程序集
- 有关VB.net2005动态链SQL SERVER2000的问题
- CodeDom计算器——动态计算数学表达式的实现
- 使用CodeDom执行动态代码
- codeDOM及动态生成类
- 简单的CodeDOM示例
- 一些codedom的资料。
- CodeDom
- 有关vb.net的调试
- 有关VB的程序问题
- 有关编译的问题
- 有关PowerBuilder的编译
- 有关编译的库
- Shell常用命令
- zcmu 1882: wjw的括号游戏
- 将字符串的图片展示到webview上
- OpenJ_Bailian
- iDT算法
- 有关Vb的CodeDom动态编译
- Oracle10g RAC (OCFS2)开启关闭及日常检查
- HDU 6162 Ch’s gift(树链剖分+线段树)
- 关注民生民情——华北水利水电大学“情艺”国情社情调查团
- 回答阿里社招面试如何准备,顺便谈谈对于Java程序猿学习当中各个阶段的建议
- Class.forName()用法详解
- NLP深度学习 —— CS224学习笔记3
- 状态码收集
- JSONP实现跨域请求JSON数据