Compile on the Fly

D

Daren Fox

I am writing an application that will require new commands to be added while
the program is still running. I thought I had found the answer in .nets
compiler facilities. I would seperate my commands out into a dll and compile
this at startup and when the source file is changed. This works fine on
startup of the application. But when I try to recompile the dll during
runtime it doesnt seem to work. If I leave the current dll in place then it
just carries on using the old dll and if i delete it then the compile
function returns that it cannot find the new dll.

Help would be appreciated.

Public Function CompileCommands() As String

Dim VBP As New VBCodeProvider()

Dim CVB As System.CodeDom.Compiler.ICodeCompiler

CVB = VBP.CreateCompiler

Dim PM As New System.CodeDom.Compiler.CompilerParameters()

PM.GenerateInMemory = True

PM.GenerateExecutable = False



PM.OutputAssembly = "commands.dll"

PM.MainClass = "command"

PM.IncludeDebugInformation = False

Dim ASM As System.Reflection.Assembly

'I believe this is to get all the assemblies of the current

'application and add them as references to the new assembly

PM.ReferencedAssemblies.Add("OpenTelnet.exe")

For Each ASM In AppDomain.CurrentDomain.GetAssemblies()

PM.ReferencedAssemblies.Add(ASM.Location)

Next

'here we do the deed

Dim Results As System.CodeDom.Compiler.CompilerResults

Results = CVB.CompileAssemblyFromFile(PM, Application.StartupPath &
"\defaultcommands\commands.vb")

'CVB.CompileAssemblyFromSource(PM, )

'this is just to list out all the errors if any

Dim Err As System.CodeDom.Compiler.CompilerError

Dim strerr As String

For Each err In Results.Errors

strerr = strerr & "Number " & err.ErrorNumber & " Text " & err.ErrorText & "
Line " & err.Line & vbCrLf

Next

If Results.Errors.Count > 0 Then

Return strerr

Exit Function

End If

'now we create an instance of the assembly newly created

'and set it to an object notice this is also a good example of late binding

Dim vargs As Object

commandobj = Results.CompiledAssembly.CreateInstance("commands.command",
False, Reflection.BindingFlags.CreateInstance, Nothing, vargs, Nothing,
Nothing)



End Function



Cheers

Daren
 
T

Tom Spink

May I ask why this needs to be done? Perhaps I can offer an alternate
solution, using the System.Reflection.Emit namespace. It contains classes
that allow you to dynamically build an assembly in memory.

--
HTH,
-- Tom Spink, Über Geek

Please respond to the newsgroup,
so all can benefit

"Maybe it's a game called 'Punish the User'"


: I am writing an application that will require new commands to be added
while
: the program is still running. I thought I had found the answer in .nets
: compiler facilities. I would seperate my commands out into a dll and
compile
: this at startup and when the source file is changed. This works fine on
: startup of the application. But when I try to recompile the dll during
: runtime it doesnt seem to work. If I leave the current dll in place then
it
: just carries on using the old dll and if i delete it then the compile
: function returns that it cannot find the new dll.
:
: Help would be appreciated.
:
: Public Function CompileCommands() As String
:
: Dim VBP As New VBCodeProvider()
:
: Dim CVB As System.CodeDom.Compiler.ICodeCompiler
:
: CVB = VBP.CreateCompiler
:
: Dim PM As New System.CodeDom.Compiler.CompilerParameters()
:
: PM.GenerateInMemory = True
:
: PM.GenerateExecutable = False
:
:
:
: PM.OutputAssembly = "commands.dll"
:
: PM.MainClass = "command"
:
: PM.IncludeDebugInformation = False
:
: Dim ASM As System.Reflection.Assembly
:
: 'I believe this is to get all the assemblies of the current
:
: 'application and add them as references to the new assembly
:
: PM.ReferencedAssemblies.Add("OpenTelnet.exe")
:
: For Each ASM In AppDomain.CurrentDomain.GetAssemblies()
:
: PM.ReferencedAssemblies.Add(ASM.Location)
:
: Next
:
: 'here we do the deed
:
: Dim Results As System.CodeDom.Compiler.CompilerResults
:
: Results = CVB.CompileAssemblyFromFile(PM, Application.StartupPath &
: "\defaultcommands\commands.vb")
:
: 'CVB.CompileAssemblyFromSource(PM, )
:
: 'this is just to list out all the errors if any
:
: Dim Err As System.CodeDom.Compiler.CompilerError
:
: Dim strerr As String
:
: For Each err In Results.Errors
:
: strerr = strerr & "Number " & err.ErrorNumber & " Text " & err.ErrorText &
"
: Line " & err.Line & vbCrLf
:
: Next
:
: If Results.Errors.Count > 0 Then
:
: Return strerr
:
: Exit Function
:
: End If
:
: 'now we create an instance of the assembly newly created
:
: 'and set it to an object notice this is also a good example of late
binding
:
: Dim vargs As Object
:
: commandobj = Results.CompiledAssembly.CreateInstance("commands.command",
: False, Reflection.BindingFlags.CreateInstance, Nothing, vargs, Nothing,
: Nothing)
:
:
:
: End Function
:
:
:
: Cheers
:
: Daren
:
:
 
D

Daren Fox

Sure.

I am writing a MUD, (telnet style game) and obviously it will evolve over
time. So I needed a way to be able to "script" the commands that people will
use to interact with the game. So that I can change/add commands over time
without taking down the whole system.

If you do have another way then that would be cool.
 
H

Herfried K. Wagner [MVP]

Hello,

Daren Fox said:
runtime it doesnt seem to work. If I leave the current dll in place then it
just carries on using the old dll and if i delete it then the compile
function returns that it cannot find the new dll.

If you use the DLL, you must unload the whole 'AppDomain' the DLL is loaded
into. You can create a separate 'AppDomain', load the DLL into it and then
unload the 'AppDomain' in order to "free" the DLL:

http://msdn.microsoft.com/library/en-us/dncscol/html/csharp05162002.asp

Plug-in/out sample written in C# by Thomas Scheidegger:

http://www.codeproject.com/csharp/livecodedotnet.asp
 
Top