The following class module (CVsa.cls) shows how to generate Visual Studio Analyzer events using ISystemDebugEventFire. In Visual Basic, the ISystemDebugEventFire interface is exposed in the MSVSA Automatable Inproc Event Creator type library. You must include a reference to this type library and to the MSVSA Automatable Event Source Installer type library. To do so, click Project, then click References to display the References dialog box. Select both of the following references and click OK.
In order to use the CVsa class module, you need to create a Visual Basic project, add a new class module, copy the following code, and paste it into the class module. This class also depends on a global module (Vsa.bas) that contains constant definitions; the listing for Vsa.bas follows the listing for Cvsa. Finally, you need a form to exercise the sample code; a listing for a sample form follows the listing for Vsa.bas.
All code listed here is sample code. In order to modify this code for your own use in a production environment, you need to add error handling.
CVsa.cls
Option Explicit
'These assignments allow you to create the ESI (Event Source Installer)
'and the IEC (InProc Event Creator) objects so that you can begin a VSA
'session and fire VSA events. You will need to select the following
'type libraries in the References dialog box.
' MSVSA Automatable Event Source Installer 1.0 Type Library
' MSVSA Automatable Inproc Event Creator 1.0 Type Library
Public ESI As MSVSAEventSourceInstaller
Public IEC As MSVSAInprocEventCreator
'This allows the application to fire stock events as the VSA Debug Event
'Source, which is installed and registered automatically. You can fire
'VSA system-defined (stock) events from a component by using this event
'source.
Private EventSourceGUID As String
Private Const DATA_EventSourceGUID = DEBUG_EVENT_SOURCE_USER
'These variables define the event parameters and values
Dim Keys(1) As String
Dim Values(1) As String
Dim lCount As Long
Dim lFlags As Long
Public Sub InitMVSA()
Dim bReg As Boolean
Dim bIsActive As Boolean
'Before beginning a VSA session, you need to choose an event source
'GUID. This example uses the GUID for the VSA Debug Event Source.
EventSourceGUID = DATA_EventSourceGUID
Set ESI = New MSVSAEventSourceInstaller
'Now you begin a VSA session. You only need to do this once during
'execution. First you test to see if the event source is registered.
'It should be.
ESI.IsSourceRegistered EventSourceGUID, bReg
If (bReg) Then
Debug.Print ("OK: EventSource registered.")
Else
Debug.Print ("Error: EventSource NOT registered.")
End If
'You no longer need the ESI object. Time to delete it.
Set ESI = Nothing
'Now you need the IEC object to create a session and fire events.
Set IEC = New MSVSAInprocEventCreator
'Now you actually begin the VSA session
IEC.BeginSession EventSourceGUID, "VBFire"
'This is to check that the session is active and ready to accept
'events. You would want to change the IF statement to correctly handle
'the failure case.
IEC.IsActive bIsActive
If (bIsActive) Then
Debug.Print ("OK: VSA Session is active.")
Else
Debug.Print ("Error: VSA Session is not active.")
End If
End Sub
Public Sub closeMVSA()
Dim bIsActive As Boolean
'Now that you are finished, it is time to end the VSA session
IEC.EndSession
'You can check to make sure that the session shut down correctly
IEC.IsActive bIsActive
If (bIsActive) Then
Debug.Print ("OK: VSA Session is ended.")
Else
Debug.Print ("Error: VSA Session is still active.")
End If
'You no longer need the IEC object. Time to delete it.
Set IEC = Nothing
End Sub
Public Sub fire(e As String)
'This is one of the functions that fires the VSA events. This function
'fires the events with default source information and no other info.
'First you need to initialize the array that you will use to pass
'data. Since you are not passing any data this time, the array will be
'one element; that is, an empty string.
Const MAXVALUE = 1
Dim Keys(1 To MAXVALUE) As Variant, Values(1 To MAXVALUE) As Variant
Keys(1) = ""
Values(1) = ""
lCount = MAXVALUE
'The cVSAEventDefaultSource flag causes source information to be
'stamped into the event by the LEC.
lFlags = cVSAEventDefaultSource
Debug.Print "Firing :" + e
'This is the statement that fires the events.
IEC.FireEvent e, Keys, Values, lCount, lFlags
End Sub
Public Sub fire2(e As String)
'This is another function that fires the VSA events. This function
'fires the events with default parameter information and other info
'as well.
'First you need to initialize the array that you will use to pass
'data. Since you are passing some data, you will need an array of as
'many elements as you are passing.
Const MAXVALUE = 5
Dim Keys(1 To MAXVALUE) As Variant, Values(1 To MAXVALUE) As Variant
lCount = MAXVALUE
'Using the cVSAEventDefaultSource or CVSAEventDefaultTarget
'flags allow the IEC and LEC to stamp all default data into the event.
'Use the cVSAEventDefaultSource flag for Call/Return events from the
'caller.
'Use the cVSAEventdefaultTarget flag for the Enter/Leave events from
'the callee.
lFlags = cVSAEventDefaultSource
Keys(1) = PARAM_Arguments 'Arguments you may want to know were
'passed
Keys(2) = PARAM_ReturnValue 'ReturnValue of the corresponding event
Keys(3) = PARAM_Exception 'Exception of the corresponding event
'The following are custom fields that are being added to the stock
'events. The string in the Keys argument is used as the field name.
Keys(4) = "Custom Text Parameter"
Keys(5) = "Custom Value Parameter"
Values(1) = "Arg1 = 2, Arg2 = 5" 'Sample arguments
Values(2) = "Return Value = 25" 'Sample Return value
Values(3) = "Oops: Out of Memory!" 'Sample Exception data
'The following are values for the custom fields that were defined
'above.
'Note that all values are passed as strings.
Values(4) = "Frank Codeslinger's Age"
Values(5) = "42"
Debug.Print "Firing :" + e
'This is the statement that fires the events.
IEC.FireEvent e, Keys, Values, lCount, lFlags
End Sub
Public Sub CallReturn()
'This function demonstrates the use of the CorrelationID parameter.
'Events should use CorrelationID to help VSA create the call tree that
'is used in the VSA views. This function fires the Call and Return
'events with the correct default information. The Call event is fired
'before the call to the CallReturn subroutine and the Return event
'upon return from CallReturn.
'Normally, the EnterLeave subroutine would be in another component
'being called by the CallReturn subroutine. This example shows these
'calls in proc in order to simplify the sample code.
'First you need to initialize the array that you will use to pass
'data. Since you are passing some data, you will need an array of as
'many elements as you are passing.
Const MAXVALUE = 1
Dim Keys(1 To MAXVALUE) As Variant, Values(1 To MAXVALUE) As Variant
lCount = MAXVALUE
'Using the cVSAEventDefaultSource or CVSAEventDefaultTarget
'flags allow the IEC and LEC to stamp all default data into the event.
'Use the cVSAEventDefaultSource flag for Call/Return events from the
'caller.
'Use the cVSAEventdefaultTarget flag for the Enter/Leave events from
'the callee.
lFlags = cVSAEventDefaultSource
'The CorrelationID needs to be the same value for pairs of the
'Call/Enter/Leave/Return events. In this case, the Call/Return pair
'has the same CorrelationID value.
Keys(1) = PARAM_CorrelationID
Values(1) = "11111111"
Debug.Print "Firing CALL event"
'First, fire the CALL event
IEC.FireEvent DEBUG_EVENT_CALL, Keys, Values, lCount, lFlags
'Now call into the EnterLeave subroutine
EnterLeave
Debug.Print "Firing RETURN event"
'Having returned from EnterLeave, fire the RETURN event
'You need to reset the following values
lFlags = cVSAEventDefaultSource
Keys(1) = PARAM_CorrelationID
Values(1) = "11111111"
IEC.FireEvent DEBUG_EVENT_RETURN, Keys, Values, lCount, lFlags
End Sub
Public Sub EnterLeave()
'This function demonstrates the use of the CorrelationID parameter.
'Events should use CorrelationID to help VSA create the call tree that
'is used in the VSA views. This function fires the Enter and Leave
'events with the correct default information. The Enter event is fired
'after entering the EnterLeave subroutine and before performing the
'functions of the subroutine.
'The Leave event is fired just prior to returning to the calling
'subroutine.
'Normally, the EnterLeave subroutine would be in another component
'being called by the CallReturn subroutine. This example shows these
'calls in proc in order to simplify the sample code.
'First you need to initialize the array that you will use to pass
'data. Since you are passing some data, you will need an array of as
'many elements as you are passing.
Const MAXVALUE = 1
Dim Keys(1 To MAXVALUE) As Variant, Values(1 To MAXVALUE) As Variant
lCount = MAXVALUE
'Using the cVSAEventDefaultSource or CVSAEventDefaultTarget
'flags allow the IEC and LEC to stamp all default data into the event.
'Use the cVSAEventDefaultSource flag for Call/Return events from the
'caller.
'Use the cVSAEventdefaultTarget flag for the Enter/Leave events from
'the callee.
lFlags = cVSAEventDefaultTarget
'The CorrelationID needs to be the same value for pairs of the
'Call/Enter/Leave/Return events. In this case, the Enter/Leave pair
'has the same CorrelationID value.
Keys(1) = PARAM_CorrelationID
Values(1) = "22222222"
Debug.Print "Firing ENTER event"
'First fire the ENTER event
IEC.FireEvent DEBUG_EVENT_ENTER, Keys, Values, lCount, lFlags
'Now do some processing in the EnterLeave subroutine
MsgBox "Welcome to Subroutine EnterLeave!", vbOKOnly, _
"Helpful Message"
Debug.Print "Firing LEAVE event"
'Preparing to leave EnterLeave, fire the LEAVE event
IEC.FireEvent DEBUG_EVENT_LEAVE_NORMAL, Keys, Values, lCount, lFlags
End Sub
The following code (Vsa.bas) contains constant definitions for use with the preceding class module. To use this code, add a new module to the Visual Basic project you created for the class module, copy the following code, and paste it into the new module.
Vsa.bas:
Option Explicit
'These are the definitions of the VSA Event field names.
'They are used in the Key array when passing data. The
'difference between default and non default parameters is
'that the IEC and LEC provide information in these parameters
'if the cVSAEventDefaultSource and the cVSAEventDefaultTarget
'flags are specified in the FireEvent call
' Default Parameters
Public Const PARAM_SourceMachine = "SourceMachine"
Public Const PARAM_SourceProcessID = "SourceProcessId"
Public Const PARAM_SourceThread = "SourceThread"
Public Const PARAM_SourceComponent = "SourceComponent"
Public Const PARAM_SourceSession = "SourceSession"
Public Const PARAM_TargetMachine = "TargetMachine"
Public Const PARAM_TargetProcessID = "TargetProcessId"
Public Const PARAM_TargetThread = "TargetThread"
Public Const PARAM_TargetComponent = "TargetComponent"
Public Const PARAM_TargetSession = "TargetSession"
Public Const PARAM_SecurityIdentity = "SecurityIdentity"
Public Const PARAM_CausalityID = "CausalityID"
Public Const PARAM_SourceProcessName = "SourceProcessName"
Public Const PARAM_TargetProcessName = "TargetProcessName"
' Non Default Parameters
Public Const PARAM_SourceHandle = "SourceHandle"
Public Const PARAM_TargetHandle = "TargetHandle"
Public Const PARAM_Arguments = "Arguments"
Public Const PARAM_ReturnValue = "ReturnValue"
Public Const PARAM_Exception = "Exception"
Public Const PARAM_CorrelationID = "CorrelationID"
'the null guid
Public Const GUID_NULL = "{00000000-0000-0000-0000-000000000000}"
'The 'user' event source, which is autoregistered for all stock events
Public Const DEBUG_EVENT_SOURCE_USER = _
"{6C736D00-BCBF-11D0-8A23-00AA00B58E10}"
'These are the definitions of the stock events that are available in VSA
'These are defined in detail in the MSDN documentation
Public Const DEBUG_EVENT_CALL = "{6C736D61-BCBF-11D0-8A23-00AA00B58E10}"
Public Const DEBUG_EVENT_RETURN = _
"{6C736D62-BCBF-11D0-8A23-00AA00B58E10}"
Public Const DEBUG_EVENT_COMPONENT_START = _
"{6C736D63-BCBF-11D0-8A23-00AA00B58E10}"
Public Const DEBUG_EVENT_COMPONENT_STOP = _
"{6C736D64-BCBF-11D0-8A23-00AA00B58E10}"
Public Const DEBUG_EVENT_CALL_DATA = _
"{6C736D65-BCBF-11D0-8A23-00AA00B58E10}"
Public Const DEBUG_EVENT_ENTER = "{6C736D66-BCBF-11D0-8A23-00AA00B58E10}"
Public Const DEBUG_EVENT_ENTER_DATA = _
"{6C736D67-BCBF-11D0-8A23-00AA00B58E10}"
Public Const DEBUG_EVENT_LEAVE_NORMAL = _
"{6C736D68-BCBF-11D0-8A23-00AA00B58E10}"
Public Const DEBUG_EVENT_LEAVE_EXCEPTION = _
"{6C736D69-BCBF-11D0-8A23-00AA00B58E10}"
Public Const DEBUG_EVENT_LEAVE_DATA = _
"{6C736D6A-BCBF-11D0-8A23-00AA00B58E10}"
Public Const DEBUG_EVENT_RETURN_DATA = _
"{6C736D6B-BCBF-11D0-8A23-00AA00B58E10}"
Public Const DEBUG_EVENT_RETURN_NORMAL = _
"{6C736D6C-BCBF-11D0-8A23-00AA00B58E10}"
Public Const DEBUG_EVENT_RETURN_EXCEPTION = _
"{6C736D6D-BCBF-11D0-8A23-00AA00B58E10}"
Public Const DEBUG_EVENT_QUERY_SEND = _
"{6C736D6E-BCBF-11D0-8A23-00AA00B58E10}"
Public Const DEBUG_EVENT_QUERY_ENTER = _
"{6C736D6F-BCBF-11D0-8A23-00AA00B58E10}"
Public Const DEBUG_EVENT_QUERY_LEAVE = _
"{6C736D70-BCBF-11D0-8A23-00AA00B58E10}"
Public Const DEBUG_EVENT_QUERY_RESULT = _
"{6C736D71-BCBF-11D0-8A23-00AA00B58E10}"
Public Const DEBUG_EVENT_TRANSACTION_START = _
"{6C736D72-BCBF-11D0-8A23-00AA00B58E10}"
Public Const DEBUG_EVENT_TRANSACTION_COMMIT = _
"{6C736D73-BCBF-11D0-8A23-00AA00B58E10}"
Public Const DEBUG_EVENT_TRANSACTION_ROLLBACK = _
"{6C736D74-BCBF-11D0-8A23-00AA00B58E10}"
You need a simple form to exercise the sample code. The following listing (vsaform.frm) shows code for such a form. The only controls needed are three command buttons named FireVSAEvents, FireVSACustomFields, and CELRSample.
Vsaform.frm:
Public vsa As CVista
Private Sub FireEvents()
'Fires stock events with default source parameter info
vsa.fire DEBUG_EVENT_CALL
vsa.fire DEBUG_EVENT_RETURN
vsa.fire DEBUG_EVENT_COMPONENT_START
vsa.fire DEBUG_EVENT_COMPONENT_STOP
vsa.fire DEBUG_EVENT_CALL_DATA
vsa.fire DEBUG_EVENT_ENTER
vsa.fire DEBUG_EVENT_ENTER_DATA
vsa.fire DEBUG_EVENT_LEAVE_NORMAL
vsa.fire DEBUG_EVENT_LEAVE_EXCEPTION
vsa.fire DEBUG_EVENT_LEAVE_DATA
vsa.fire DEBUG_EVENT_RETURN_DATA
vsa.fire DEBUG_EVENT_RETURN_NORMAL
vsa.fire DEBUG_EVENT_RETURN_EXCEPTION
vsa.fire DEBUG_EVENT_QUERY_SEND
vsa.fire DEBUG_EVENT_QUERY_ENTER
vsa.fire DEBUG_EVENT_QUERY_LEAVE
vsa.fire DEBUG_EVENT_QUERY_RESULT
vsa.fire DEBUG_EVENT_TRANSACTION_START
vsa.fire DEBUG_EVENT_TRANSACTION_COMMIT
vsa.fire DEBUG_EVENT_TRANSACTION_ROLLBACK
End Sub
Private Sub FireEvents2()
'Fires stock events with default parameter info
'and other standard and custom info as well
vsa.fire2 DEBUG_EVENT_CALL
vsa.fire2 DEBUG_EVENT_RETURN
vsa.fire2 DEBUG_EVENT_COMPONENT_START
vsa.fire2 DEBUG_EVENT_COMPONENT_STOP
vsa.fire2 DEBUG_EVENT_CALL_DATA
vsa.fire2 DEBUG_EVENT_ENTER
vsa.fire2 DEBUG_EVENT_ENTER_DATA
vsa.fire2 DEBUG_EVENT_LEAVE_NORMAL
vsa.fire2 DEBUG_EVENT_LEAVE_EXCEPTION
vsa.fire2 DEBUG_EVENT_LEAVE_DATA
vsa.fire2 DEBUG_EVENT_RETURN_DATA
vsa.fire2 DEBUG_EVENT_RETURN_NORMAL
vsa.fire2 DEBUG_EVENT_RETURN_EXCEPTION
vsa.fire2 DEBUG_EVENT_QUERY_SEND
vsa.fire2 DEBUG_EVENT_QUERY_ENTER
vsa.fire2 DEBUG_EVENT_QUERY_LEAVE
vsa.fire2 DEBUG_EVENT_QUERY_RESULT
vsa.fire2 DEBUG_EVENT_TRANSACTION_START
vsa.fire2 DEBUG_EVENT_TRANSACTION_COMMIT
vsa.fire2 DEBUG_EVENT_TRANSACTION_ROLLBACK
End Sub
Private Sub CELRSample_Click()
vsa.CallReturn
End Sub
Private Sub FireVSACustomFields_Click()
FireEvents2
End Sub
Private Sub FireVSAEvents_Click()
FireEvents
End Sub
Private Sub Form_Load()
Set vsa = New CVista
vsa.InitMVSA
End Sub
Private Sub Form_Unload(cancel As Integer)
vsa.closeMVSA
Set vsa = Nothing
End Sub