• Welcome to Valhalla Legends Archive.
 

VB .NET System.CodeDom

Started by Smurfling, October 29, 2003, 08:18 AM

Previous topic - Next topic

Smurfling

I got a little problem, but first of all the code:

   Private VBP As New VBCodeProvider
   Private CVB As System.CodeDom.Compiler.ICodeCompiler
   Private PM As New System.CodeDom.Compiler.CompilerParameters
   Private Results As System.CodeDom.Compiler.CompilerResults


Public Function CodeD()

      Dim FILE_NAME As String = "ChatEvents.txt"
       Dim fsIn As New FileStream(FILE_NAME, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)
       Dim sr As New StreamReader(fsIn)
       Dim i As Integer
       Dim k As Integer
       Dim TheKey As String
       TheKey = sr.ReadToEnd
       sr.Close()
       fsIn.Close()

       CVB = VBP.CreateCompiler
       PM.GenerateInMemory = True
       PM.OutputAssembly = "CEvents.dll"
       PM.MainClass = "ChatEvents"
       PM.IncludeDebugInformation = False
       Dim ASM As System.Reflection.Assembly
       PM.ReferencedAssemblies.Clear()
       For Each ASM In AppDomain.CurrentDomain.GetAssemblies()
           PM.ReferencedAssemblies.Add(ASM.Location)
       Next
       Results = CVB.CompileAssemblyFromSource(PM, TheKey)

       Dim RunObj As New Object
       Dim vArgs() As Object

       RunObj = Results.CompiledAssembly.CreateInstance("CEvents" & "." & "ChatEvents", False, Reflection.BindingFlags.CreateInstance, Nothing, vArgs, Nothing, Nothing)
       If Not RunObj Is Nothing Then
           RunObj.ProcessEvents(hID, hUserFlag, hPing, hUsername, hText, bla)
       End If

End Function


Well, the code itself works fine - it's reading the code out of the .txt file, creating the .dll within the memory and all's ok. But now if i change the code within the .txt and want to update and recreate the dll there's always remaining the old code. It only works if i close the app and start it again. Can someone give me a little hint how to get it done?

Banana fanna fo fanna

Can you explain to me what CodeDom does and how it works? I've been trying to write a new language for .NET but haven't figured out the "right way" (converting source files to jscript.net)

Smurfling

#2
Ok i'll try to do so...  ;D


Introduction:

CodeDom stands for the Code Document Object Model.
A popular use of the CodeDom is for developing automatic source code generators which minimize repetitive coding tasks, and minimize the number of human-generated source code lines being created.


Advantages:
  • The CodeDom is based upon a single model for rendering source code. Therefore, source code may be generated for any language that supports the CodeDom specification. (VBScript, VB, .NET,...)
  • The CodeDom allows programs to be dynamically created, compiled, and executed at runtime.
  • The CodeDom provides a language independent object model for representing the structure of source code in memory.
Limitations:
  • There is no support for aliasing a namespace.
  • There is no support for nested namespaces.
  • There is no support for variable declaration lists.
  • There is no support for the "unsafe" modifier.
Finally:

This is just a short overview, for more Information search msdn.microsoft.com. There are lot's of things i don't know about CodeDOM, i am just learning to use it's possibilities to the fullest.

As far as i can tell you from the knowledge i have yet is that CodeDOM is for existing languages only, that means writing a new language for .NET could be hard/impossible to do with it. But if you only want to execute p.e. a VBScript within JScript CodeDOM is the thing you should go for.

For what i am using CodeDOM is making my bot scriptable to the max., almost everything will be loaded through CD.



   'The Code Provider for Visual Basic . NET
   Private VBP As New VBCodeProvider
   'The Code Compiler
   Private CVB As System.CodeDom.Compiler.ICodeCompiler
   'The Parameters for compilation
   Private PM As New System.CodeDom.Compiler.CompilerParameters
   'Will hold the compiled script
   Private Results As System.CodeDom.Compiler.CompilerResults


Public Function CodeD()

      'Load VB .NET Script Source from ChatEvents.txt
      Dim FILE_NAME As String = "ChatEvents.txt"
       Dim fsIn As New FileStream(FILE_NAME, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)
       Dim sr As New StreamReader(fsIn)
       Dim i As Integer
       Dim k As Integer
       Dim TheKey As String
       TheKey = sr.ReadToEnd
       sr.Close()
       fsIn.Close()

       'Creating the VB Compiler
       CVB = VBP.CreateCompiler
       'Creating the assembly in memory
       PM.GenerateInMemory = True
       'Setting the assembly name
       PM.OutputAssembly = "CEvents.dll"
       'Setting the main class of the script
       PM.MainClass = "ChatEvents"
       'I don't need debug info ;)
       PM.IncludeDebugInformation = False
       'Adding references to the assembly
       Dim ASM As System.Reflection.Assembly
       PM.ReferencedAssemblies.Clear()
       For Each ASM In AppDomain.CurrentDomain.GetAssemblies()
           PM.ReferencedAssemblies.Add(ASM.Location)
       Next
       'Filling the results with the compiled script
       Results = CVB.CompileAssemblyFromSource(PM, TheKey)

       'Running the compiled script
       Dim RunObj As New Object
       Dim vArgs() As Object

       RunObj = Results.CompiledAssembly.CreateInstance("CEvents" & "." & "ChatEvents", False, Reflection.BindingFlags.CreateInstance, Nothing, vArgs, Nothing, Nothing)
       If Not RunObj Is Nothing Then
           'Calling the Function ProcessEvents within the script
           RunObj.ProcessEvents(hID, hUserFlag, hPing, hUsername, hText, bla)
       End If

End Function


O yea, here would be the script ChatEvents.txt - that's a simple one, don't want to fill pages with the real script here ;)


Imports System.Windows.Forms
Imports Microsoft.VisualBasic
Imports System

namespace CEvents
Public Class ChatEvents

Public Function ProcessEvents(ByVal eID As Long, ByVal eUserFlag As Long, ByVal ePing As Long, ByVal eUsername As String, ByVal eText As String, ByVal Socket As BdNBot2004.clsBNLSSocket)
   Const EID_SHOWUSER& = &H1
   Const EID_JOIN& = &H2
   Const EID_LEAVE& = &H3
   Const EID_WHISPER& = &H4
   Const EID_TALK& = &H5
   Const EID_BROADCAST& = &H6
   Const EID_CHANNEL& = &H7
   Const EID_USERFLAGS& = &H9
   Const EID_WHISPERSENT& = &HA
   Const EID_CHANNELFULL& = &HD
   Const EID_CHANNELDOESNOTEXIST& = &HE
   Const EID_CHANNELRESTRICTED& = &HF
   Const EID_INFO& = &H12
   Const EID_ERROR& = &H13
   Const EID_EMOTE& = &H17
   
       Select Case eID
           Case EID_WHISPER
               If eText = ":TIME" Then
                   Socket.Insert(Socket.Type.tNTString, "/w " & eUsername & " " & DateTime.Now)
                   Socket.SendPacket(&HE)
                   Exit Function
               End If
        End Select
   End Function
End Class
end namespace


But o well, i still don't have my problem solved and can't find anything about it on the net... any help would still be appreciated :P

Smurfling

#3
O man i love to try out each possibility until you find the right ;)

Finally solved it by my own, for those who perhaps wanna know how to reload the dll:


           Dim FILE_NAME As String = "ChatEvents.txt"
           Dim fsIn As New FileStream(FILE_NAME, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)
           Dim sr As New StreamReader(fsIn)
           Dim i As Integer
           Dim k As Integer
           Dim TheKey As String
           TheKey = sr.ReadToEnd
           sr.Close()
           fsIn.Close()

           Results = CVB.CompileAssemblyFromSource(PM, TheKey)

The only secret was to leave the compiler and options alone (if you touch them it won't work) and only to reload the source & compile them into results again ;)

Edited: If i think about it now that i solved it this is the first thing you should think about - just reload source and recompile, but o well i always try to to things the hard way

Banana fanna fo fanna

Could I create an extension to CodeDom which compiles language X?

Zorm

Would it be possible to take advantage of this in like C/C++?
"Now, gentlemen, let us do something today which the world make talk of hereafter."
- Admiral Lord Collingwood

Banana fanna fo fanna


K

#7
Yup, the System.CodeDom namespace is a lot of fun, and very useful for making things plugin friendly without too much effort.
Example!

Skywing

Quote from: K on November 01, 2003, 04:38 PM
Yup, the System.CodeDom namespace is a lot of fun, and very useful for making things plugin friendly without too much effort.
Example!
Isn't having a "File" and "This File" menu kind of silly, BTW?

What're you using to parse and color code text in your editor?

K

#9
Quote from: Skywing on November 01, 2003, 05:45 PM
Isn't having a "File" and "This File" menu kind of silly, BTW?

What're you using to parse and color code text in your editor?

Haha yes, I didn't notice that.  I added the options like Quit, Save All, etc under File and the file specific ones under this file.  Sounds like a merger is in order.

As for the coloring, it's done using a combination of regular expressions and a list of keywords.  It's kind of slow when coloring an entire document, but once it's colored it updates fairly quickly -- I only scan the visible region of the editor when a change is made, unless it's a change to a block comment.

MyndFyre

Quote from: Andreas Strobl on October 29, 2003, 08:18 AM
I got a little problem, but first of all the code:

Well, the code itself works fine - it's reading the code out of the .txt file, creating the .dll within the memory and all's ok. But now if i change the code within the .txt and want to update and recreate the dll there's always remaining the old code. It only works if i close the app and start it again. Can someone give me a little hint how to get it done?

Unfortunately, no.  There is no way to unload an assembly from memory within an AppDomain until the AppDomain is terminated, i.e., the program is closed.  It's a shortcoming of the .NET environment.

Something you may consider, though, which I have done with my .NET apps, is to use methods called RegisterEvents and UnregisterEvents().  Any events that you want to handle are hooked by the plugin (these events are contained by another class, which I call the EventHost, an instance of which is passed into the plugin's constructor).  When you're done with the plugin - that is, wish to finish it off - you just call the UnregisterEvents method.

Here's the interface for it:


Public Interface IPlugin
   ' It is illegal to declare this in the constructor or as a shared method
   ' because of OOP, but you get the idea:
   Shared Function GetInstance(ByVal EH as EventHost) As IPlugin
   Sub RegisterEvents()
   Sub UnregisterEvents()
   Event PluginMessage As PluginEventHandler
End Interface


Hope that helps.

--Rob
QuoteEvery generation of humans believed it had all the answers it needed, except for a few mysteries they assumed would be solved at any moment. And they all believed their ancestors were simplistic and deluded. What are the odds that you are the first generation of humans who will understand reality?

After 3 years, it's on the horizon.  The new JinxBot, and BN#, the managed Battle.net Client library.

Quote from: chyea on January 16, 2009, 05:05 PM
You've just located global warming.