1.VS是怎么编译的
2.通过vbc.exe来编译应用程序
3.在代码中通过VBCodeProvider动态编译应用程序
只要你家有.net Framework,就能找到vbc。vbc的地址是 C:\Windows\Microsoft.NET\Framework\.net版本(比如v4.0.30319)\vbc.exe.

技术分享

首先cd到指定路径下然后调用vbc。vbc功能强大,这里列出一部分。

 

 

/out:<file>                       指定输出文件名。
/target:exe                       创建控制台应用程序(默认)。 (缩写: /t)
/target:winexe                    创建 Windows 应用程序。
/target:library                   创建库程序集。
/target:module                    创建可添加到程序集的模块。
/target:appcontainerexe           创建在 AppContainer 中运行的 Windows
                                  应用程序。
/target:winmdobj                  创建 Windows 元数据中间文件
/doc[+|-]                         生成 XML 文档文件。
/doc:<file>                       将 XML 文档文件生成到 <file>。

                                  – 输入文件 –
/addmodule:<file_list>            从指定模块中引用元数据。
/link:<file_list>                 嵌入所指定互操作程序集中的元数据。 (缩写: /l)
/recurse:<wildcard>               根据通配符规范,包括当前目录及子目录下的所有文
                                  件。
/reference:<file_list>            从指定的程序集引用元数据。 (缩写: /r)

                                  – 资源 –
/linkresource:<resinfo>           将指定文件链接为外部程序集资源。resinfo:
                                  <file>[,<name>[,public|private]] (缩写:
                                  /linkres)
/nowin32manifest                  默认清单不应嵌入在输出 PE 的清单部分中。
/resource:<resinfo>               将指定文件添加为嵌入的程序集资源。resinfo:
                                  <file>[,<name>[,public|private]] (缩写: /res)
/win32icon:<file>                 为默认 Win32 资源指定 Win32 图标文件(.ico)。
/win32manifest:<file>             提供的文件嵌入在输出 PE 的清单部分中。
/win32resource:<file>             指定 Win32 资源文件(.res)。

                                  – 代码生成 –
/optimize[+|-]                    启用优化。
/removeintchecks[+|-]             移除整数检查。默认为“关”。
/debug[+|-]                       发出调试信息。
/debug:full                       发出完全调试信息(默认)。
/debug:pdbonly                    只发出 PDB 文件。

                                  – 错误和警告 –
/nowarn                           禁用所有警告。
/nowarn:<number_list>             禁用各个警告的列表。
/warnaserror[+|-]                 将所有警告视为错误。
/warnaserror[+|-]:<number_list>   将警告列表视为错误。

这里详细介绍几个参数:

1./target

缩写为/t 他指定了编译类型。有四种选项 exe(将编译成控制台应用程序) ,winexe(将编译成 窗体应用程序),library(编译成类库【*.dll】)和module(编译成模块)。

例如 /t:exe

2./reference:<file_list>           

缩写: /r 从指定的程序集引用元数据。  它的作用就相当于vs里的添加引用。可以通过指定这个参数来添加引用,vbc为我们默认引用了许多类库。他们保存在vbc.rsp里。默认的vbc.rsp也就是默认添加的引用如下。

# This file contains command-line options that the VB
# command line compiler (VBC) will process as part
# of every compilation, unless the “/noconfig” option
# is specified. 

# Reference the common Framework libraries
/r:Accessibility.dll
/r:System.Configuration.dll
/r:System.Configuration.Install.dll
/r:System.Data.dll
/r:System.Data.OracleClient.dll
/r:System.Deployment.dll
/r:System.Design.dll
/r:System.DirectoryServices.dll
/r:System.dll
/r:System.Drawing.Design.dll
/r:System.Drawing.dll
/r:System.EnterpriseServices.dll
/r:System.Management.dll
/r:System.Messaging.dll
/r:System.Runtime.Remoting.dll
/r:System.Runtime.Serialization.Formatters.Soap.dll
/r:System.Security.dll
/r:System.ServiceProcess.dll
/r:System.Transactions.dll
/r:System.Web.dll
/r:System.Web.Mobile.dll
/r:System.Web.RegularExpressions.dll
/r:System.Web.Services.dll
/r:System.Windows.Forms.Dll
/r:System.XML.dll

/r:System.Workflow.Activities.dll
/r:System.Workflow.ComponentModel.dll
/r:System.Workflow.Runtime.dll
/r:System.Runtime.Serialization.dll
/r:System.ServiceModel.dll

/r:System.Core.dll
/r:System.Xml.Linq.dll
/r:System.Data.Linq.dll
/r:System.Data.DataSetExtensions.dll
/r:System.Web.Extensions.dll
/r:System.Web.Extensions.Design.dll
/r:System.ServiceModel.Web.dll

# Import System and Microsoft.VisualBasic
/imports:System
/imports:Microsoft.VisualBasic
/imports:System.Linq
/imports:System.Xml.Linq

/optioninfer+

下面我们来一个简单的vbc编译例子。

首先我们编写了一个最最简单的vb代码。如下:

Imports System.Windows.Forms
Module Module1

    Sub Main()
        MessageBox.Show("Hello World")
    End Sub

End Module

我们把它保存到vbc的目录下。名为a.txt

我们调用cmd,cd 到指定目录下,调用vbc.exe执行下面的命令:vbc.exe a.txt.然后回车。编译成功。

技术分享

这时目录下出现了一个a.exe的文件。点击执行,效果如下。

技术分享

消息框弹出了。后面还有个黑框框。有人可能会问了,这里并没有什么/r /t的,为什么会成功呢?这就是默认的缘故。我们说了,/t默认为exe(控制台),/r默认引用了vbc.rsp里的程序集。所以可以成功。

下面进入第三部分,vbnet的动态编译。

动态编译,即在代码中动态编译出程序。方法有很多,可以调用vbc,也可以使用反射,但我们这里使用一种较为简单的方法VBCodeProvider。

为使用,首先添加引用

Imports System.Reflection
Imports System.CodeDom.Compiler

然后,声明VBCodeProvider对象。

 

      Dim cp As New VBCodeProvider()

这样,就创建了一个vb编译器实例。

我们还要再声明一个参数对象。CompilerParameters

  Dim cParameters As New CompilerParameters()

我就不放出CompilerParameters的成员列表了。大家可从http://msdn.microsoft.com/query/dev14.query?appId=Dev14IDEF1&l=ZH-CN&k=k%28System.CodeDom.Compiler.CompilerParameters%29;k%28TargetFrameworkMoniker-.NETFramework 查看。

这里讲一下它的几个重要的属性

1.GenerateExecutable 通过它可以设置是否编译成exe文件。我们这里为true。

2.GenerateInMemory 他可以指示是否在内存中生成输出。 这里为false。

3. OutputAssembly 用它来设置输出程序集的名称。

4.ReferencedAssemblies 获取本程序引用的程序集。可以通过ReferencedAssemblies的Add方法添加引用。

设置完了之后来上这一句获得编译结果

Dim cresult As CompilerResults = pc.CompileAssemblyFromFile(cParameters, "a.txt")

 

这就是说,用cParameters作为参数编译a.txt这个文件,返回编译结果给cresult

 

然后对cresult进行操作保存生成的exe,详见代码。

好了,用这个方法方法,我们用代码编译a.txt

我很懒,就直接写在form的load里面了。

 

Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
        声明
        Dim pc As VBCodeProvider = New VBCodeProvider
        Dim cParameters As New CompilerParameters()
        cParameters.GenerateExecutable = True 生成exe文件
        cParameters.GenerateInMemory = False 不在内存中生成



        添加引用
        cParameters.ReferencedAssemblies.Add("System.dll")
        cParameters.ReferencedAssemblies.Add("System.Windows.Forms.dll")

        编译并返回结果
        Dim cresult As CompilerResults = pc.CompileAssemblyFromFile(cParameters, "a.txt")
        If cresult.NativeCompilerReturnValue = 0 Then
            如果编译成功
            Try
                避免重名而报错,删除旧文件
                My.Computer.FileSystem.DeleteFile("a.exe")
            Catch ex As Exception

            End Try
            把生成的文件移动到目标目录下(因为他是保存在一个特定的地方, 文件名也是随机的)
            My.Computer.FileSystem.MoveFile(cresult.PathToAssembly, "a.exe")
        Else
            For Each a As CompilerError In cresult.Errors
                出错,显示错误信息
                MsgBox(a.ErrorText)
            Next
        End If



    End Sub

这样,一个简单编译器就做好了。