Click here to Skip to main content
15,896,111 members
Articles / Programming Languages / C#

VSEDebug - VS.NET Debugging Enhancement

Rate me:
Please Sign up or sign in to vote.
4.92/5 (37 votes)
25 Apr 20049 min read 170.1K   2.2K   58  
VSEDebug is a VS.NET debugger add-in that adds the ability to debug complex types in simpler form.
Imports System.IO
Imports System.Text
Imports System.Reflection
Imports System.Collections

Public Class VsaScriptHost
    ' Engine to be used in the class
    Private myEngine As Microsoft.Vsa.IVsaEngine
    ' Items for the engine
    Private myItems As Microsoft.Vsa.IVsaItems
    ' Code Item that stores the script
    Private myScript As Microsoft.Vsa.IVsaCodeItem
    ' The implementation of the VSASite used for call backs
    Private mySite As VsaSite
    ' temporary Src string 
    Private tempSrc As String
    ' VSA reference Item for holding the system.dll reference
    Private systemRef As Microsoft.Vsa.IVsaReferenceItem
    ' temporary reference used in the AddReference method
    Private tempRef As Microsoft.Vsa.IVsaReferenceItem
    ' String that contains any imports statements needed for the addobject
    Private ImportsScript As String
    ' Boolean for determining debugging or not
    Private debugValue As Boolean
    ' Boolean determining whether the engine has been compiled
    Private IsCompiled As Boolean
    Dim myPE As Byte()
    Dim myPDB As Byte()
    Dim tempModules(0) As String

    Private languageValue As String
    Public ReadOnly Property CompiledState() As Byte()
        Get
            Try
                myEngine.SaveCompiledState(myPE, myPDB)
            Catch e As System.Exception

            End Try
            Return myPE
        End Get
    End Property
    ' The language of the engine being used
    Public ReadOnly Property Language() As String
        Get
            Return languageValue
        End Get
    End Property
    ' The script code
    Public Property scriptSrc() As String
        Get
            ' Add the imports to the beginning of the script
            Return myScript.SourceText
        End Get
        Set(ByVal Value As String)
            myScript.SourceText = Value
        End Set
    End Property
    ' Collection of Procedures in the engine
    Public ReadOnly Property Procedures() As MethodInfo()
        Get
            ' Check to see if the engine is running
            ' If it's not run it so we can get the modules
            If Not myEngine.IsRunning Then
                Me.Run()
            End If
            ' Return the procedures in the module
            Dim fullName As String
            Dim modType As Type
            Dim methods As MethodInfo()
            ' Create the fullname of the namespace that containts the method
            fullName = myEngine.RootNamespace & "." & myEngine.RootNamespace
            ' Get the type from the assembly
            modType = myEngine.Assembly.GetType(fullName, True, True)
            ' Get the methods from the module
            methods = modType.GetMethods(BindingFlags.Static Or BindingFlags.Public)
            ' Return the methods
            Return methods
        End Get
    End Property
    Public ReadOnly Property Modules() As String()
        Get
            ' *** HACK ***
            ' It's a demo after all
            Try
                tempModules(0) = "scriptcode"
            Catch e As Exception

            End Try

            Return tempModules
        End Get
    End Property
    Public Property Debug() As Boolean
        Get
            ' Return the value of the debug flag
            Return debugValue
        End Get
        Set(ByVal Value As Boolean)
            debugValue = Value
        End Set
    End Property
    Public ReadOnly Property CompiledAssembly() As System.Reflection.Assembly
        Get
            Return myEngine.Assembly
        End Get
    End Property
    Public Sub New(ByVal scriptlanguage As String, ByVal Moniker As String, ByVal [NameSpace] As String)
        Try
            ' Store the langauge
            Me.languageValue = scriptlanguage
            ' Creat the Script Engine based on the language
            createEngine()
            ' Set the moniker to be something relatively unique
            myEngine.RootMoniker = Moniker
            ' Create a new instance of the VSA Site
            myEngine.Site = New VsaSite()
            ' Get the instance of the site 
            mySite = myEngine.Site
            ' Initialize the engine
            myEngine.InitNew()
            ' Set the rootnamespace
            myEngine.RootNamespace = [NameSpace]
            ' Set the engine name
            myEngine.Name = [NameSpace]

        Catch e As Microsoft.Vsa.VsaException
        End Try

        ' Get the items collection from the engine
        myItems = myEngine.Items
        ' Create a blank codeitem
        If Me.Language <> "JScript.NET" Then
            myScript = myItems.CreateItem("scriptcode", Microsoft.Vsa.VsaItemType.Code, Microsoft.Vsa.VsaItemFlag.Module)
        Else
            myScript = myItems.CreateItem("scriptcode", Microsoft.Vsa.VsaItemType.Code, Microsoft.Vsa.VsaItemFlag.None)
        End If
        ' Create a reference to system
        Me.AddReference("System", "System.dll")
        ' Setup debugging
        Me.setupDebug(Debug)
        ' Add an inports to system
        Me.setupImports("System")

        IsCompiled = False

    End Sub
    Public Sub AddCode(ByVal Code As String)
        ' Need to get the source text to put the code inside the module/class
        tempSrc = Me.scriptSrc
        If Me.Language <> "JScript.NET" Then
            Me.scriptSrc = tempSrc.Insert(tempSrc.LastIndexOf("End Module"), Code & vbCrLf)
        Else
            Me.scriptSrc += Code & vbCrLf
        End If
    End Sub
    Public Sub AddObject(ByVal Name As String, ByVal Type As String, ByRef Instance As System.Object, ByVal AssemblyName As String, Optional ByVal Events As Boolean = True)
        ' Add an eventsource to the engine
        myScript.AddEventSource(Name, Type)
        ' Add the instance to the sites hashtable
        mySite.AddEvent(Name, Type, Instance, True)
        ' JScript.NET Beta 2 has a bug whereby adding an event source actually
        ' adds an entry to the item list so adding "Ref" to the Name ensure that
        ' theres no naming collisions
        Me.AddReference(Name & "Ref", AssemblyName)
        ' Make sure the reference gets imported
        ' Use split to get the type from the beginning of the Type String
        Me.setupImports(Type.Split(".")(0))
    End Sub
    Public Sub AddReference(ByVal Name As String, ByVal AssemblyName As String)
        Try
            ' Create a reference to the object
            tempRef = myItems.CreateItem(Name, Microsoft.Vsa.VsaItemType.Reference, Microsoft.Vsa.VsaItemFlag.None)
            ' Set the assemblyname
            tempRef.AssemblyName = AssemblyName
        Catch e As Microsoft.Vsa.VsaException
            Throw New Exception("Couldn't add Assembly")
        End Try
    End Sub
    Public Sub Compile()
        ' Check to see if the engine is running
        If myEngine.IsRunning Then
            ' If it is reset the engine
            myEngine.Reset()
        End If
        Try
            If myEngine.Compile() Then
                Me.Run()
            Else
                Throw New Exception("Error in compilation")
            End If
        Catch e As Microsoft.Vsa.VsaException

        End Try
    End Sub
    Public Function Invoke(ByVal ModuleName As String, ByVal MethodName As String, ByVal Arguments As Object()) As Object
        Dim FullName As String
        Dim ModType As Type
        Dim method As MethodInfo
        Dim evidencecontrol As New System.Security.Permissions.SecurityPermission(System.Security.Permissions.SecurityPermissionFlag.ControlEvidence)
        evidencecontrol.Assert()
        If Not myEngine.IsRunning Then
            Throw New Exception("Engine isn't running!")
            Exit Function
        End If
        Dim evidencecol As IEnumerator
        evidencecol = myEngine.Assembly.Evidence.GetEnumerator()

        ' Create the fullname of the namespace that containts the method
        FullName = myEngine.RootNamespace & "." & ModuleName
        Try
            ' Get the type from the assembly
            ModType = myEngine.Assembly.GetType(FullName, True, True)
        Catch e As Microsoft.Vsa.VsaException
            Throw New Exception("Unable to get assembly named " & FullName)
        End Try
        ' Get the method from the type
        method = ModType.GetMethod(MethodName)
        ' Check to see if we can find the method
        If Nothing Is method Then
            ' Can't find the method so throw an exception
            Throw New Exception("method not found")
        Else
            Try
                ' Call the method and return any value
                Return method.Invoke(Nothing, Arguments)
            Catch e As Exception
                MsgBox(e.ToString)
            End Try
        End If
    End Function
    Public Sub Run()
        Try
            myEngine.Run()
        Catch e As Microsoft.Vsa.VsaException
            Throw New Exception("Unable to run the engine")
        End Try
    End Sub
    Private Sub createEngine()
        Try

            Select Case Language
                Case "VB", "Visual Basic"
                    myEngine = New Microsoft.VisualBasic.Vsa.VsaEngine()
                Case "JScript", "JScript.NET"
                    myEngine = New Microsoft.JScript.Vsa.VsaEngine()
                Case Else
                    Throw New Exception("Unknown Engine")
            End Select
        Catch e As Exception
        End Try
    End Sub
    Private Sub setupImports(ByVal Type As String)
        ' Should use CodeDOM here really
        ' That will be in the next installment
        If Language = "VB" Then
            ImportsScript = "imports"
        Else
            ImportsScript = "import"
        End If
        ImportsScript += " " & Type
        ImportsScript += vbCrLf
        ' Add the imports to the beginnging of the script
        Me.scriptSrc = ImportsScript & Me.scriptSrc
    End Sub
    Private Sub setupDebug(ByVal state As Boolean)
        If state Then
            ' Write out the temporary file
            Dim fs As FileStream
            Dim FilePath As String = System.Environment.GetFolderPath(System.Environment.SpecialFolder.LocalApplicationData) & "\scriptpad\script.vb"
            Dim DirectoryName As String = Path.GetDirectoryName(FilePath)

            If Not (Directory.Exists(DirectoryName)) Then
                Directory.CreateDirectory(DirectoryName)
            End If
            fs = New FileStream(FilePath, FileMode.Create, FileAccess.Write, FileShare.None)
            Dim writer As New StreamWriter(fs, New UnicodeEncoding())
            writer.Write(Me.scriptSrc)
            writer.Close()
            fs.Close()

            Me.scriptSrc = "#ExternalSource(" & FilePath & ",1)" & Me.scriptSrc
            Me.scriptSrc += "#End ExternalSource"
        Else

        End If
    End Sub

End Class

' Simple implementation of a VSA Site for use by the VSAScriptHost Class
Public Class VsaSite
    Implements Microsoft.Vsa.IVsaSite
    ' Hashtable to store the instances of the objects being added to the engine
    Private eventInstances As New Hashtable()
    Public Function AddEvent(ByVal Name As String, ByVal type As String, ByRef Instance As Object, ByVal Events As Boolean)
        Try
            eventInstances.Add(Name, Instance)
        Catch e As Exception
            MsgBox("Couldn't add event instance to the hashtable")
        End Try
    End Function

    Public Sub GetCompiledState(ByRef pe() As Byte, ByRef debugInfo() As Byte) Implements Microsoft.Vsa.IVsaSite.GetCompiledState

    End Sub

    Public Function GetEventSourceInstance(ByVal itemName As String, ByVal eventSourceName As String) As Object Implements Microsoft.Vsa.IVsaSite.GetEventSourceInstance
        Try
            Return eventInstances(eventSourceName)
        Catch e As Exception
            Throw New Exception("couldn't find the instance")
        End Try
    End Function

    Public Function GetGlobalInstance(ByVal [name] As String) As Object Implements Microsoft.Vsa.IVsaSite.GetGlobalInstance

    End Function

    Public Sub Notify(ByVal notify As String, ByVal info As Object) Implements Microsoft.Vsa.IVsaSite.Notify

    End Sub

    Public Function OnCompilerError(ByVal [error] As Microsoft.Vsa.IVsaError) As Boolean Implements Microsoft.Vsa.IVsaSite.OnCompilerError
        ' Provide a simple dialog with the compile error message
        MsgBox([error].Description & "on line " & [error].Line, MsgBoxStyle.Exclamation, "Compile Error")
    End Function
End Class

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
Web Developer
United States United States
I'm a student at the University of Florida studying computer engineering.

You may find additional information about vsedebug at http://vsedebug.sourceforge.net

Comments and Discussions