2009-03-18
| Table of Contents: |
| Rate This Article: | Add This Article To: |
( Page 3 of 4 )
Using Dynamic Code
Creating controls at runtime is one strategy for dealing with scenarios where you can’t determine full application functionality at design time. However, dynamically creating controls won’t work in all situations. Sometimes you must build executable code while your application is running in order to compensate for different machine configurations, user needs, environmental demands, or other requirements. When an application runs on a machine over which you have no control (such as a shrink-wrapped application), the need to create dynamic code occurs more often.
Fortunately, .NET provides you with a host of dynamic code options (and not always a lot of information on how to use them). For example, you can create an executable that runs independently of the host application or a DLL that you can load into your running application and execute. You use an executable when you need to perform an external task, such as running a script—the DLL option works best for augmenting existing application functionality.
You can run dynamic code from a file or within memory. Use a file when you need to run the code more than once. A check in your code makes it possible to run the external file again without recompiling it. Use a memory image when you need to perform a task once, such as a setup requirement.
It’s also possible to vary the source of the code. For example, you can use strings to build the code you need directly in an application. This approach works best when you require maximum flexibility and the code itself isn’t very long or involved. It’s also possible to build the code from a file, just as Visual Studio does. This approach works best for relatively stable, yet complex coding requirements. It’s also the option of choice for scripts, should your application support scripting. The third choice is to use the Document Object Model (DOM) to build the code as a series of CodeDom trees. The trees consist of CodeCompileUnits. It’s sort of like building an XML file using DOM. I personally prefer the other two methods of creating an executable, but I’m sure this third approach has adherents that wouldn’t do it any other way. The point is that you have options.
The best way to begin working with dynamically created code is to view an example. Listing 3 shows a basic “Hello World” sort of example. In this case, the example builds the code directly within the source code so you can see how things work and generates an external (rather than an in-memory) executable.
Listing 3: A Dynamic Coding Example
Private Sub btnTest3_Click() Handles btnTest3.Click
' Create a compiler.
Dim Comp As VBCodeProvider = New VBCodeProvider()
' Define the parameters for the code you want to compile.
Dim Parms As CompilerParameters = New CompilerParameters()
' We do want to create an executable, rather than a DLL.
Parms.GenerateExecutable = True
' The compiler will create an output assembly called Output.
Parms.OutputAssembly = "Output"
' The compiler won't treat warnings as errors.
Parms.TreatWarningsAsErrors = False
' Add any assembly you want to reference.
Parms.ReferencedAssemblies.Add("System.Windows.Forms.dll")
' Define the code you want to run.
Dim SampleCode As StringBuilder = New StringBuilder()
SampleCode.Append("Imports System.Windows.Forms" + vbCrLf)
SampleCode.Append("Module TestAssembly" + vbCrLf)
SampleCode.Append("Sub Main()" + vbCrLf)
SampleCode.Append("MessageBox.Show(" + Chr(34) + _
"Dynamically Created Code!" + _
Chr(34) + ")" + vbCrLf)
SampleCode.Append("End Sub" + vbCrLf)
SampleCode.Append("End Module" + vbCrLf)
' Define the code to run.
Dim Executable As CompilerResults = _
Comp.CompileAssemblyFromSource(Parms, SampleCode.ToString())
' Display error messages if there are any.
If Executable.Errors.HasErrors Then
For Each Item As CompilerError In Executable.Errors
MessageBox.Show(Item.ErrorText)
Next
Else
' If there aren't any error messages, start the
' executable.
Process.Start("Output")
End If
End Sub
The example strips things down a bit more than you probably would for a real world application. However, it does show all the basics. You begin by creating a compiler, Comp, using the VBCodeProvider. Older versions of .NET used a different approach, but this is the new approach that Microsoft recommends and it works very well.
In order to use the compiler, you must create parameters that describe the application. These parameters (of type CompilerParameters) also appear for any application you create within Visual Studio, but now you define them yourself. The code begins by setting GenerateExecutable to True, which simply means you want an EXE file, instead of a DLL.
The Parms.OutputAssembly property contains the name of the output file. You only need to provide this information when you want to create a file, rather than generate the executable in-memory. If you want to generate an in-memory version of the executable instead, you would set the Parms.GenerateInMemory property to True.
Use the Parms.TreatWarningsAsErrors property to determine how to treat warning messages. The default settings treats them as errors, which means that your application could fail to compile for the smallest of reasons. Most developers use the default setting while they develop the application, but set it to False for a finished application.
Most applications require external DLLs to run correctly. Certainly, you can’t create any Windows forms application without referencing an external DLL. Normally, you accomplish this task using the References folder. However, when creating code dynamically you rely on the Parms.ReferencedAssemblies property. Simply add the DLLs you need as shown.
Now that you’ve defined your project, you need to create the source code for it. As previously mentioned, you can rely on an external file or DOM. However, the example builds the code in place so you can see what’s going on. It’s a little hard to see precisely what the code looks like though, so here it is in its original form:
Imports System.Windows.Forms
Module TestAssembly
Sub Main()
MessageBox.Show("Dynamically Created Code!")
End Sub
End Module
This is a very simple example that displays a dialog box. Note the use of vbCrLf at the end of each line. If you don’t take this approach, the error information you receive back from the compiler won’t be very enlightening and the application itself won’t compile. The vbCrLf entries serve the same purpose in this code as they do in your application code—you’re just added them in a different way.
At this point, you can finally compile the code using the Comp.CompileAssemblyFromSource() method. You use the CompileAssemblyFromDom() method when working with DOM and the CompileAssemblyFromFile() when working with a file. In all three cases, the compiler creates the output you requested using the parameters and source code that you want to provide. The output of this operation appears in Executable, which is of type CompilerResults.
Compilations fail more often than developers would like. No matter where you use dynamic coding techniques, you must assume that some percentage of the compilations will fail and address the issue. In this case, the code simply looks for errors and displays them in a message box when the compilation fails. Otherwise, the code relies on the Process.Start() method to start the executable.
![]() |
|


