Imports HSCF.Communication.Scs.Communication.EndPoints.Tcp
Imports HSCF.Communication.ScsServices.Client
Imports HSCF.Communication.Scs.Communication
Imports System.Reflection
Imports System.Configuration
Imports System.Convert
Imports System.Xml
Imports Microsoft.CodeAnalysis.CSharp
Imports Microsoft.CodeAnalysis.VisualBasic
Imports Microsoft.CodeAnalysis
Imports tenScripting4.My
Imports HomeSeer.PluginSdk
Imports HSCore
Imports System.Runtime.Serialization
''
'' tenScripting4 Changes
''
'' Version 4.22300
''     Includes HS 4.2.23.0 Libraries
''
'' Version 4.2224          4/27/2025
''     Includes HS 4.2.22.4 Libraries
''     Removed Reference to System.Diagnostics from the VBscripts Project for compatibility with HS environment
''     Added Browse button for specifying the location of the HS script folder
''     Updated Connection Dialog information
''     Added VB code snippet for a new script without parameters
''
'' Version 4.2201      8/19/2024
''     Removed \obj folders from distribution     
''
'' Version 4.2200
''     Includes HS 4.2.20.0 libraries
''
'' Version 4.2193
''     Updated tenGlobalMethods
''           New Method: DeviceDim
''     HS3 documentation website moved
''
''     Downgraded C# compilation to the version 3.0 language specification to better match HS4
''
'' Version 4.2192
''     Updated tenGlobalMethods
''           DeviceOn, DeviceOff: Improved search for StatusControls, optional parameter UseControlLabel
''           RestoreDeviceStates: Added optional parameter to clear the saved states
''           RemoveDeviceStates:  New function to remove saved Device states
''
'' Version 4.2191
''     Updated tenGlobalMethods:  
''           Updated Functions:   DeviceOn, DeviceOff, ToggleDevice, ToggleDeviceOnOff
''           New Functions:  IsOff, AreAllOff, SaveDeviceStates, RestoreDeviceStates, GetRefsInEitherList
''
'' Version 4.2190   12/11/2023
''
''     Includes HS4 4.2.19.0 Libraries
''
''     Enhanced shutdown logic
''
''     tenGlobalMethods version changed back to 4.218
''
''     Help links updated
''
''     Additional error checking
''
''     Removed links to deprecated tenHsEvents
''
'' Version 4.218     3/12/2023
''
''     Includes HS4 4.2.18 Libraries
''
''     All tenWare links now https
''
''     tenGlobalMethods.GetFeatureRefByFullname optional parameter to search with just Feature NAME
''
'' Version 4.16  1/20/2023
''
''     New Logos
''
''     Includes HS4 4.2.16 Libraries
''
'' Version 4.12
''
''     tenGlobalMethods.GetFeatureRefByFullname wasn't returning Device Devref if Featurename blank
''
''     Log HS Version
''
''     Include HS4 4.2.11.0 Libraries (including HSCore.dll)
''
'' Version 4.11  distributed 1/10/2022
''
''     Includes HS4 4.2.7.0 Libraries
''
''     Increased allowed difference in timestamps for exported files (without warning)
''
''     Fixed version checking to handle 4.2.x.x
''
''
'' Version 4.10  distributed 3/27/2021
''
''     Update tenRunScript to support parameters of single string or array of strings
''
''     Added script tenRunScriptButton for realtime testing of DeviceButton scripts
''
''     Additional debugging information
''
''     Corrected name of the debug file
''
''     Save selected File and Script for next execution
''
'' Version 4.8      distributed 3/2/2021
''
''     Warning about copying tenGlobalMethods.dll if the reference is added
''
'' Version 4.7
''
''     tenGlobalMethods  GetRefsByCategoryName and GetCategoriesByRef updated to check for invalid Refs in a Category
''
''     Checks for HS Version 4.1.14 or greater.  If so:
''          Do not replace hs4 with hs
''          Do not check for missing PluginSDK reference 
''
'' Version 4.6
''
''     Added a Reference to System.Data.SQLite.dll to the VBscripts and CSscripts projects and includes in Libraries
''
''     Includes HS4 Version 4.1.12.0 libraries
''
'' Version 4.5
''
''     Replaced Parms checkbox with dropdown
''
''     Eliminated Registration Failed log message
''
''     Replaced Run tenScriptAid button with Open HS Log button
''
''     Auto size main form
''
''     Updated New Script snippet
''
''     New facility to create Global Methods
''
''     Moved all DLLs to tenScripting4/Libraries,  eliminated Nuget dependencies
''
'' Version 4.4   1/27/2021
''
''     No longer remove commas from parms before running script
''
''     Removed Debug Log processing
''
''     Fixed problem with improperly registering plugin with HS4
''
'' Version 4.3
''
''     Instead of inserting "Dim hs4 as object = hs",  replace all "hs4." with "hs."
''     
''     Enhancements to logging
''
''     Warning msg when Non-HS parms passed (HsTouch)
''
''     Updated Snippets
''
'' Version 4.2
''
''     Fixed dialog references from HS3 to HS4
''
''     Turned on    Option Implicit   and   Option Strict  in VBscripts
''
''     Added back the compiled files to the distribution to reduce confusion (but increase distribution size)
''
''     Reduced connection attempts from 3 to 2
''
''     Open Export Dialog centered on screen
''
''     Fixed problem with incorrect ScriptingReference insertion
''
'' Version 4.1   8/9/2020
''
''     Initial BETA release
''
Public Class tenScripting
    Public Shared hs As HomeSeerAPI.IHSApplication
    Dim WithEvents clientCallback As HSCF.Communication.ScsServices.Client.IScsServiceClient(Of IAppCallbackAPI)
    Public WithEvents HS4Client As HSCF.Communication.ScsServices.Client.IScsServiceClient(Of HomeSeer.PluginSdk.IHsController)
    Public WithEvents HS3Client As HSCF.Communication.ScsServices.Client.IScsServiceClient(Of HomeSeerAPI.IHSApplication)
    Friend HS3Host As HomeSeerAPI.IHSApplication
    Friend HS4Host As HomeSeer.PluginSdk.IHsController
    Private host As HomeSeer.PluginSdk.IHsController
    Public plugin As HSPI
    Friend ScriptTable As ArrayList
    Friend DebugLogProccess As Process
    Friend LogRecordReceived As Boolean = False
    Friend isShutdown As Boolean = False
    Private Sub frmMain_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
        StartupComplete = False
        tmrStartup.Start()   'will fire timer to complete initialization
    End Sub
    Private Sub client_Disconnected(ByVal sender As Object, ByVal e As System.EventArgs) Handles HS4Client.Disconnected
        isShutdown = True
        Console.WriteLine("client_Disconnected:  tenScripting has been disconnected from HS4")
    End Sub
    Private Sub Wait(ByVal secs As Integer)
        Threading.Thread.Sleep(secs * 1000)
    End Sub
    Private Sub tmrStartup_Tick(sender As System.Object, e As System.EventArgs) Handles tmrStartup.Tick
        Dim Config As System.Configuration.Configuration
        Dim ConfigFilePath As String
        Dim TerminatingForm As frmTerminating
        Dim p As String
        Dim VBscriptsInit As New VBscripts.VBinit
        Dim NewVersion As String
        tmrStartup.Stop()
        ''
        '' Handle All Program Initialization in Timer Event, After frmMain has loaded
        ''
        '' Do some initialization stuff before attempting connection
        MyLog("tenScripting Version " & Version() & " Starting", False, Logging.ELogType.Info)
        '' Upgrade Settings from Last Release if this is a New Release
        If My.Settings.UpgradeSettings Then
            My.Settings.Upgrade()
            My.Settings.UpgradeSettings = False
            My.Settings.Save()
            MyLog("New Version Detected.  Settings copied from prior version.", False, Logging.ELogType.Info)
        End If
        '' Open Debug File
        Try
            DebugFile = System.Windows.Forms.Application.UserAppDataPath & "\tenScripting4DEBUG.txt"
            DebugWriter = New System.IO.StreamWriter(DebugFile)
        Catch ex As Exception
            MyLog("Error creating Debug File", False, Logging.ELogType.Error)
            MyLog("  Ex: " & ex.Message, False, Logging.ELogType.Error)
        End Try
        '' Init some Main form items
        lstLog.Top = cboFiles.Top - 5
        lstLog.Height = 170
        lstLog.Show()
        lstLog.BringToFront()
        Me.Text = Me.Text & "  v" & Version()
        Me.Top = My.Settings.FormTop
        Me.Left = My.Settings.FormLeft
        theMainForm = Me
        Me.lblDeviceName.Text = ""
        cboParameters.SelectedIndex = My.Settings.ParameterType   'display type of run parameters
        If My.Settings.ParameterType = 1 Then
            lblParmWarning.Hide()
        Else
            lblParmWarning.Show()
        End If
        '' Check for Newer Version
        btnNewVersion.Hide()
        If My.Settings.AutoUpdates Then
            NewVersion = CheckForProgramUpdates()
        End If
        ''
        '' Now, let's see if we can connect
        ''
        MyLog(IFACE_NAME & " starting...", True)
        AboutTenScripting010ToolStripMenuItem.Text = "tenScripting Version: " & Version()
        plugin = New HSPI
        plugin.MainForm = Me
        HsConnected = False
        ConnectToHs()   'this will create remote copies of both hs and hs4
        If Not HsConnected Then
            frmConnection.ShowDialog()
            End
        End If
        ''  Check if HS4 Version is  greater than 4.1.13  (hs4 and PluginSDK issues fixed)
        MyLog("HS version: " & hs4.Version)
        VersionGreaterThan_4_1_13 = CheckIfVersionGreaterThan_4_1_13()
        If VersionGreaterThan_4_1_13 Then
            MyLog("HomeSeer version 4.1.14 or greater, hs4 and PluginSDK enhancements operational", False, Logging.ELogType.Info)
        Else
            MyLog("HomeSeer version 4.1.13 or earlier, hs4 and PluginSDK enhancements NOT operational", False, Logging.ELogType.Info)
        End If
        '' See if we can find tenScriptAid location
        ToolsMnuTenScriptAid.Enabled = False
        p = ""
        Try
            If System.IO.File.Exists(SavedLocation) Then
                p = System.IO.File.ReadAllText(SavedLocation, System.Text.Encoding.ASCII)
                If System.IO.File.Exists(p) Then
                    ToolsMnuTenScriptAid.Enabled = True
                End If
            End If
            MyLog("Found tenScriptAid at: " & p)
        Catch Ex As Exception
            MyLog("Error Retrieving tenScriptAid Location from File", False, Logging.ELogType.Error)
            MyLog("Ex: " & Ex.Message, False, Logging.ELogType.Error)
        End Try
        MyLog("Debug File: " & DebugFile, False, Logging.ELogType.Info)
        '' Get Location of Settings File 
        Try
            Config = System.Configuration.ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.PerUserRoamingAndLocal)
            ConfigFilePath = Config.FilePath
            MyLog("tenScripting4 Configuration Settings stored in folder:", False, Logging.ELogType.Info)
            MyLog("___" & ConfigFilePath, False, Logging.ELogType.Info)
        Catch ex As Exception
            '' Error getting config file location
            MyLog("Error getting location of PerUserRoamingAndLocal config folder", False, Logging.ELogType.Error)
            MyLog("  EX: " & ex.Message, False, Logging.ELogType.Error)
        End Try
        ''
        '' Connected, Finish tenScripting Initialization
        ''
        '' Initialize VBscripts and CSscripts Projects
        VBscriptsInit.SetHsObject(hs, hs4)   'pass hs objects to VBscripts Project Classes
        CSscripts.CSinit.hsobject = hs   'pass hs object to CSscripts
        CSscripts.CSinit.hs4object = hs4   'pass hs4 object to CSscripts
        '' Gather information about scripts
        MyLog("Getting Scripts", True)
        Exports.Clear()                                 'clear target list of scripts
        GetVbScripts()        ' Find all Script.vb files in the VB Project Folder and parse for Classes and Methods
        GetCsScripts()        ' Find all Script.cs files in the CS Project Folder and parse for Classes and Methods
        '' Select File from last execution
        If Me.cboFiles.Items.Count > 0 Then
            '' Determine File Selection
            Me.cboFiles.SelectedIndex = 0
            MyLog("Setting File Selection from last run, initially first file entry", True, Logging.ELogType.Info)
            MyLog("My.Settings.LastFile: " & My.Settings.LastFile, True)
            For i = 0 To Me.cboFiles.Items.Count - 1
                If Me.cboFiles.Items(i).ToString = My.Settings.LastFile Then
                    Me.cboFiles.SelectedIndex = i
                    MyLog("Setting File Selection to: " & My.Settings.LastFile & " which is CBO index of " & i.ToString, True)
                    Exit For
                End If
            Next
        End If
        Me.cboFiles.Refresh()
        ProjectFiles.Clear()
        GetVbProjectFiles()   ' Find all of the VB files that will be compiled by Visual Studio   (for error checking)
        GetCsProjectFiles()   ' Find all of the CS files that will be compiled by Visual Studio   (for error checking)
        Me.MenuStrip1.Visible = True
        MyLog("Homeseer Connection Successful", False, Logging.ELogType.Info)
        Me.lblConnected.Text = "Connected"
        Me.picHS.Visible = True
        Me.Refresh()
        Me.btnRunSubMain.Enabled = True
        If Not VersionGreaterThan_4_1_13 Then
            If My.Settings.CheckScriptingReferences Then
                CheckScriptingReferences()   'check to see if a reference to PluginSDK is defined in HS4
            Else
                MyLog("Check for Scripting References bypassed by user selection in Scripting References Dialog", False, Logging.ELogType.Info)
            End If
        End If
        StartupComplete = True
        MyLog("tenScripting Initialization Complete", True)
        lstLog.Hide()
        btnOpenClose.Text = "Open"
        ''
        '' Wait for tenScripting to Finish
        ''
        Console.WriteLine("Waiting For tenScripting To Exit")
        Do
            Threading.Thread.Sleep(10)
            Application.DoEvents()
        Loop While HS4Client.CommunicationState = HSCF.Communication.Scs.Communication.CommunicationStates.Connected And Not isShutdown
        Console.WriteLine("isShutDown now True Or disconnected from HS4, complete termination Of tenScripting")
        TerminatingForm = New frmTerminating
        TerminatingForm.Show()
        TerminatingForm.Refresh()
        Application.DoEvents()
        If isShutdown Then Console.WriteLine("isShutDown is True, Exiting")
        If HS4Client.CommunicationState = HSCF.Communication.Scs.Communication.CommunicationStates.Disconnected Then Console.WriteLine("Disconnected from HS4, Exiting")
        ' Disconnect from server for good here
        Wait(1)
        Console.WriteLine("HS3 State= " & HS3Client.CommunicationState.ToString)
        Console.WriteLine("HS4 State= " & HS4Client.CommunicationState.ToString)
        Console.WriteLine("Disconnecting from HS4")
        If HS3Client.CommunicationState = HSCF.Communication.Scs.Communication.CommunicationStates.Connected Then
            HS3Client.Disconnect()
        End If
        If HS4Client.CommunicationState = HSCF.Communication.Scs.Communication.CommunicationStates.Connected Then
            HS4Client.Disconnect()
        End If
        Console.WriteLine("Waiting for both to disconnect")
        Do
            Threading.Thread.Sleep(10)
            Application.DoEvents()
        Loop While HS4Client.CommunicationState = HSCF.Communication.Scs.Communication.CommunicationStates.Connected Or HS3Client.CommunicationState = HSCF.Communication.Scs.Communication.CommunicationStates.Connected
        Console.WriteLine("Now Disconnected from HS")
        Console.WriteLine("HS3 State= " & HS3Client.CommunicationState.ToString)
        Console.WriteLine("HS4 State= " & HS4Client.CommunicationState.ToString)
        plugin = Nothing
        HS4Client.Dispose()
        HS3Client.Dispose()
        HS4Client = Nothing
        HS3Client = Nothing
        HS3Host = Nothing
        HS4Host = Nothing
        hs = Nothing
        hs4 = Nothing
        Console.WriteLine("Now terminating tenscripting4.exe")
        TerminatingForm.Close()
        Me.Close()
    End Sub
    Friend Function CheckIfVersionGreaterThan_4_1_13() As Boolean
        ''
        '' Check if HS4 version has fixed the hs4 and PluginSDK issues
        ''
        Dim s1 As String, ss1 As String()
        s1 = hs4.Version()
        If s1.Length < 5 Then
            MyLog("HS4 Version invalid:  " & s1, False, Logging.ELogType.Error)
            Return False
        End If
        ss1 = s1.Split(Convert.ToChar("."))
        If ss1.Length < 3 Then
            '' Invalid HS4 Version
            MyLog("HS4 Version invalid: " & s1, False, Logging.ELogType.Error)
            Return False
        End If
        '' Digit 1
        If CDbl(ss1(0)) <> 4 Then
            MyLog("HS4 Version invalid, Not Version 4.x.x: " & s1, False, Logging.ELogType.Error)
            Return False
        End If
        '' Digit 2
        Select Case CDbl(ss1(1))
            Case < 1
                Return False
            Case > 1
                Return True
            Case Else
                '' Digit 3
                Select Case CDbl(ss1(2))
                    Case > 13
                        Return True
                    Case Else
                        Return False
                End Select
        End Select
    End Function
    Friend Sub ConnectToHs()
        Dim i As Integer
        Dim HS3Result, HS4Result As Boolean
        '' Connect to HomeSeer
        HsConnected = False
        MyLog("Attempting to connect to:  " & My.Settings.HsComputer, True)
        lblConnected.Text = "Connecting"
        Me.Refresh()
        '' Connect First to HS3 framework
        For i = 1 To 2
            HS3Result = ConnectToHS3()
            If HS3Result Then Exit For
        Next
        If HS3Result = False Then
            '' Could not Connect to HS4 for HS3 object
            MyLog("Could not connect to HS4 and obtain HS3 hs object", False, Logging.ELogType.Error)
            Exit Sub
        Else
            '' Successfully obtained HS3 object, now try to get HS4 object
            If ApiVersion < 4 Then
                MyLog("Successfully Retrieved hs Object, but the HS Server is NOT HS4.  ApiVersion= " & ApiVersion.ToString, False, Logging.ELogType.Error)
                MsgBox("Successfully connected to HS Server, but Version " & ApiVersion.ToString & vbCrLf & vbCrLf & "Specify an IP Address of an HS4 system or use tenScripting3",, "tenScripting4")
                Exit Sub
            End If
            For i = 1 To 3
                HS4Result = ConnectToHS4()
                If HS4Result Then Exit For
            Next
            If HS4Result = False Then
                '' Could not Connect to HS4 for HS4 object
                MyLog("Could not connect to HS4 and obtain hs4 object", False, Logging.ELogType.Error)
                Exit Sub
            End If
        End If
        If IsNothing(hs) Or IsNothing(hs4) Or Not HS3Result Or Not HS4Result Then
            '' Connection failed, terminate
            MyLog("Could not Connect.  ", False, Logging.ELogType.Error)
            Exit Sub
        Else
            '' Connected Successfully
            MyLog("HS4 connection successful", True)
            MyLog("HS version: " & hs.Version, True)
            HsConnected = True
            lblConnected.Text = ""
        End If
    End Sub
    Private Function ConnectToHS3() As Boolean
        ''
        '' Connect to HS3/HS4 and Retrieve HS3 (hs) Object
        ''
        Dim sIP As String = My.Settings.HsComputer
        Try
            HS3Client = ScsServiceClientBuilder.CreateClient(Of HomeSeerAPI.IHSApplication)(New ScsTcpEndPoint(sIP, 10400))
        Catch ex As Exception
            MyLog("Exception creating HS3 Client=" & ex.Message, False, Logging.ELogType.Error)
            Return False
        End Try
        If HS3Client Is Nothing Then
            MyLog("Could not create HS3Client", False, Logging.ELogType.Error)
            Return False
        End If
        Try
            HS3Client.Connect()
        Catch ex As Exception
            MyLog("Exception connecting to HS3Client=" & ex.Message, False, Logging.ELogType.Error)
            Return False
        End Try
        If Not (HS3Client.CommunicationState = CommunicationStates.Connected) Then
            MyLog("Failed to connect to HS3Client, State=" & HS3Client.CommunicationState.ToString, False, Logging.ELogType.Error)
            Return False
        End If
        Try
            HS3Host = HS3Client.ServiceProxy
            hs = HS3Host
            ApiVersion = hs.APIVersion
        Catch ex As Exception
            MyLog("Exception retrieving hs object=" & ex.Message, False, Logging.ELogType.Error)
            Return False
        End Try
        If hs Is Nothing Then Return False
        MyLog("Successfully obtained hs object from either HS3 or HS4", True)
        Return True
    End Function
    Private Function ConnectToHS4() As Boolean
        ''
        '' Connect to HS4 and Retrieve HS4 (hs4) Object
        ''
        Dim sIP As String = My.Settings.HsComputer
        Try
            HS4Client = ScsServiceClientBuilder.CreateClient(Of IHsController)(New ScsTcpEndPoint(sIP, 10400), plugin)
        Catch ex As Exception
            MyLog("Exception creating hs4Client=" & ex.Message, False, Logging.ELogType.Error)
            Return False
        End Try
        If HS4Client Is Nothing Then
            MyLog("Creating HS4Client failed", False, Logging.ELogType.Error)
            Return False
        End If
        Try
            HS4Client.Connect()
        Catch ex As Exception
            MyLog("Exception connecting to HS4=" & ex.Message, False, Logging.ELogType.Error)
            Return False
        End Try
        If Not (HS4Client.CommunicationState = CommunicationStates.Connected) Then
            MyLog("Failed to connect to HS4Client, State=" & HS4Client.CommunicationState.ToString, False, Logging.ELogType.Error)
            Return False
        End If
        Try
            HS4Host = HS4Client.ServiceProxy
            hs4 = HS4Host
            Try
                ApiVersion = hs4.APIVersion
            Catch ex As Exception
                MyLog("Could not get ApiVersion using hs4 object, connection failed", False, Logging.ELogType.Error)
                Return False
            End Try
        Catch ex As Exception
            MyLog("Exception retrieving hs4 object=" & ex.Message, False, Logging.ELogType.Error)
            Return False
        End Try
        If hs4 Is Nothing Then Return False
        MyLog("Successfully obtained hs4 object from HS4", True)
        Return True
    End Function
    Private Sub CheckScriptingReferences()
        ''
        '' Check to see if HS4 has a scripting reference defined for the Plugin SDK dll
        ''
        ''   [Settings]  ScriptingReferences=PluginSdk;bin\homeseer\PluginSdk.dll
        ''
        '' Check to see if the PluginSDK reference is already defined
        Dim CurrentSetting As String
        ScriptingReferenceDefined = False
        CurrentSetting = hs4.GetINISetting("Settings", "ScriptingReferences", "")   'get current setting
        If CurrentSetting.Length < 2 Then
            '' No Entry Found
            ScriptingReferenceDefined = False
        Else
            '' Entry Found
            If CurrentSetting.ToUpper.Contains("PLUGINSDK") Then
                '' Needed reference is already there
                ScriptingReferenceDefined = True
            Else
                ScriptingReferenceDefined = False
            End If
        End If
        If ScriptingReferenceDefined Then Exit Sub   'already defined, we are finished
        '' Not defined, open form to query user what they want to do
        MyLog("No ScriptingReference for PluginSDK.  Opening dialog", True)
        OpenScriptingReferenceForm()
    End Sub
    Private Sub OpenScriptingReferenceForm()
        Dim ScriptReferenceform As frmScriptingReference
        Dim CurrentSetting As String
        CurrentSetting = hs4.GetINISetting("Settings", "ScriptingReferences", "")   'get current setting
        ScriptReferenceform = New frmScriptingReference
        ScriptReferenceform.txtCurrentScriptingReference.Text = CurrentSetting
        ScriptReferenceform.txtCurrentScriptingReference.Select(ScriptReferenceform.txtCurrentScriptingReference.Text.Length, 0)
        If VersionGreaterThan_4_1_13 Then
            '' PluginSDK already fixed
            ScriptReferenceform.chkCheckAtStartup.Hide()
            ScriptReferenceform.btnPluginSDK.Hide()
        Else
            '' PluginSDK reference necessary
            ScriptReferenceform.chkCheckAtStartup.Show()
            ScriptReferenceform.btnPluginSDK.Show()
        End If
        ScriptReferenceform.ShowDialog()
        ScriptReferenceform.Dispose()
        ScriptReferenceform = Nothing
    End Sub
    Private Sub GetCsScripts()
        ''
        ''  Parse Source Code from CS Scripts Project for Classes and Methods
        ''
        Dim anAssembly As Assembly
        Dim modules() As System.Reflection.Module, aModule As [Module]
        Dim methodinfos() As MethodInfo
        Dim types() As Type
        Dim sd As ScriptData
        Dim DI As IO.DirectoryInfo, FIs() As IO.FileInfo, FI As IO.FileInfo
        Dim ed, p As String, i As Integer
        Dim Excludes() As String = {"VBGLOBALS.VB", "CSGLOBALS.CS"}
        '' Get all of the CS Files, Classes, Methods from the CS Project Files
        ed = My.Application.Info.DirectoryPath          'executable directory
        i = ed.IndexOf("bin")                           'offset to project sub directory
        p = ed.Substring(0, i - 14) & "CSscripts\"      'path to CSscripts project sub directory
        DI = New IO.DirectoryInfo(p)
        FIs = DI.GetFiles
        For Each FI In FIs
            If FI.Extension.ToUpper = ".CS" Then
                i = Array.IndexOf(Excludes, FI.Name.ToUpper)
                If Array.IndexOf(Excludes, FI.Name.ToUpper) = -1 Then
                    Me.cboFiles.Items.Add(FI.Name)
                    MyLog("Getting Classes for: " & FI.FullName, True)
                    GetCsClasses(FI.FullName)
                End If
            End If
        Next
        '' Get all of the CS Methods Loaded into Memory
        anAssembly = Assembly.GetAssembly(GetType(CSscripts.CSinit))
        modules = anAssembly.GetLoadedModules()
        aModule = modules(0)
        types = aModule.GetTypes()
        For Each t As Type In types
            methodinfos = t.GetMethods
            For Each m As MethodInfo In methodinfos
                If Scripts.ContainsKey(t.Name & "." & m.Name) Then
                    sd = Scripts(t.Name & "." & m.Name)
                    sd.oType = t    '''''''' Save the Class Type for execution
                    MyLog("Loaded Method " & sd.ClassName.ToUpper & "." & sd.MethodName.ToUpper, True)
                End If
            Next
        Next
    End Sub
    Private Sub GetVbScripts()
        ''
        ''  Parse Source Code from VB Scripts Project for Classes and Methods
        ''
        Dim anAssembly As Assembly
        Dim modules() As System.Reflection.Module, aModule As [Module]
        Dim methodinfos() As MethodInfo
        Dim types() As Type
        Dim sd As ScriptData
        Dim DI As IO.DirectoryInfo, FIs() As IO.FileInfo, FI As IO.FileInfo
        Dim ed, p As String, i As Integer
        Dim Excludes() As String = {"VBGLOBALS.VB", "CSGLOBALS.CS"}
        '' Get all of the VB Files, Classes, Methods from the VB Project Files
        ed = My.Application.Info.DirectoryPath          'executable directory
        i = ed.IndexOf("bin")                           'offset to project sub directory
        p = ed.Substring(0, i - 14) & "VBscripts\"      'path to VBscripts project sub directory
        DI = New IO.DirectoryInfo(p)
        FIs = DI.GetFiles
        For Each FI In FIs
            If FI.Extension.ToUpper = ".VB" Then
                i = Array.IndexOf(Excludes, FI.Name.ToUpper)
                If Array.IndexOf(Excludes, FI.Name.ToUpper) = -1 Then
                    Me.cboFiles.Items.Add(FI.Name)
                    MyLog("Getting Classes for: " & FI.FullName, True)
                    GetVbClasses(FI.FullName)
                End If
            End If
        Next
        '' Get all of the VB Methods Loaded into Memory
        anAssembly = Assembly.GetAssembly(GetType(VBscripts.VBinit))
        modules = anAssembly.GetLoadedModules()
        aModule = modules(0)
        types = aModule.GetTypes()
        For Each t As Type In types
            methodinfos = t.GetMethods
            For Each m As MethodInfo In methodinfos
                If Scripts.ContainsKey(t.Name & "." & m.Name) Then
                    sd = Scripts(t.Name & "." & m.Name)
                    sd.oType = t    '''''''' Save the Class Type for execution
                    MyLog("Loaded Method " & sd.ClassName.ToUpper & "." & sd.MethodName.ToUpper, True)
                End If
            Next
        Next
    End Sub
    Friend Sub GetVbProjectFiles()
        Dim sr As IO.StreamReader
        Dim fn, s1, s2, s3 As String, i1, i2 As Integer
        '' Open the VBscripts Project File
        s1 = My.Application.Info.DirectoryPath.Substring(0, My.Application.Info.DirectoryPath.IndexOf("bin") - 14)                          'path to project sub directory
        fn = s1 & "VBscripts\VBscripts.vbproj"
        sr = IO.File.OpenText(fn)
        '' Find all Compile Entries
        Do While Not sr.EndOfStream
            s1 = sr.ReadLine
            If s1.Trim.ToUpper.Contains("<COMPILE INCLUDE=") Then
                '' Found Entry, strip name and add to list
                i1 = s1.IndexOf("""")
                s2 = s1.Substring(i1 + 1, s1.Length - i1 - 1)
                i2 = s2.IndexOf("""")
                s3 = s2.Substring(0, i2)
                ProjectFiles.Add(s3.ToUpper, s3.ToUpper)
            End If
        Loop
    End Sub
    Friend Sub GetCsProjectFiles()
        Dim sr As IO.StreamReader
        Dim fn, s1, s2, s3 As String, i1, i2 As Integer
        '' Open the CSscripts Project File
        s1 = My.Application.Info.DirectoryPath.Substring(0, My.Application.Info.DirectoryPath.IndexOf("bin") - 14)                          'path to project sub directory
        fn = s1 & "CSscripts\CSscripts.csproj"
        sr = IO.File.OpenText(fn)
        '' Find all Compile Entries
        Do While Not sr.EndOfStream
            s1 = sr.ReadLine
            If s1.Trim.ToUpper.Contains("<COMPILE INCLUDE=") Then
                '' Found Entry, strip name and add to list
                i1 = s1.IndexOf("""")
                s2 = s1.Substring(i1 + 1, s1.Length - i1 - 1)
                i2 = s2.IndexOf("""")
                s3 = s2.Substring(0, i2)
                ProjectFiles.Add(s3.ToUpper, s3.ToUpper)
            End If
        Loop
    End Sub
    Friend Function CheckForProgramUpdates() As String
        '' Go to Web Page to see if this program has a newer version available
        Dim ret As String = ""
        theMainForm.btnNewVersion.Hide()
        Try
            Dim NewerVersion() As String = GetCurrentVersion(IFACE_NAME)
            Dim ThisVersion As String = Version()
            If CDbl(NewerVersion(0)) > CDbl(ThisVersion) Then
                '' There is a newer version
                theMainForm.btnNewVersion.Text = "Version " & NewerVersion(0).Trim & " is Available"
                theMainForm.btnNewVersion.Show()
                ret = NewerVersion(0).Trim
            End If
        Catch ex As Exception
            MyLog("Error comparing program version to current version", False, Logging.ELogType.Error)
            MyLog("  ex: " & ex.Message, False, Logging.ELogType.Error)
            Return ""
        End Try
        Return ret
    End Function
    Friend Sub GoToWebForUpdates(ProgramName As String)
        Dim theURL As String
        theURL = GetCurrentVersion(ProgramName)(1)
        Process.Start(theURL)
    End Sub
    Function StringToHex(ByVal text As String) As String
        Dim hex As String = ""
        For i As Integer = 0 To text.Length - 1
            hex &= Asc(text.Substring(i, 1)).ToString.ToUpper & " "
        Next
        Return hex
    End Function
    Friend Sub GetCsClasses(ByVal fn As String)
        ''
        '' Parse a CS source file, extracting Classes and Methods
        ''
        Dim ClassStatements As New Specialized.StringCollection
        Dim ClassName As String = ""
        Dim MethodName As String
        Dim Imps As New Specialized.StringCollection
        Dim theFN As String
        Dim theSource As String
        Dim tree As CSharpSyntaxTree
        Dim RootNode As CSharpSyntaxNode
        Dim Nodes, Nodes2 As IEnumerable(Of Microsoft.CodeAnalysis.SyntaxNode)
        Dim Tokens, Tokens2 As IEnumerable(Of Microsoft.CodeAnalysis.SyntaxToken)
        Dim s1, s2, s3, s4, s5, s6 As String
        Dim i1, i2, i3, i4 As Integer
        Dim aClassDefinition As CSharpSyntaxNode
        Dim sd As ScriptData
        Dim FoundPublicKeyword As Boolean = False
        Dim ClassStatementStart As Integer
        Dim OpenBraceStart, CloseBraceStart As Integer
        '' Get Script file
        theSource = My.Computer.FileSystem.ReadAllText(fn)
        '' Parse source into a Syntax Tree
        tree = CType(CSharpSyntaxTree.ParseText(theSource), Microsoft.CodeAnalysis.CSharp.CSharpSyntaxTree)
        RootNode = tree.GetRoot()
        Nodes = RootNode.ChildNodes()
        '' Find all Class Definitions and USING statements
        For Each n As CSharpSyntaxNode In Nodes
            s1 = n.Kind.ToString
            Select Case s1.ToUpper.Trim
                Case "CLASSDECLARATION"
                    ClassStatementStart = n.Span.Start
                    '' Save the Class Name
                    Tokens = n.ChildTokens()   'get components of the Class Statement
                    For Each t As Microsoft.CodeAnalysis.SyntaxToken In Tokens
                        '' loop thru looking for Class Name
                        s2 = CType(t.RawKind, CSharp.SyntaxKind).ToString
                        If s2.ToUpper.Trim = "IDENTIFIERTOKEN" Then
                            '' Found Class Name
                            ClassName = t.Text
                        End If
                        If s2.ToUpper.Trim = "OPENBRACETOKEN" Then
                            '' Found Open Brace
                            OpenBraceStart = t.Span.Start
                        End If
                        If s2.ToUpper.Trim = "CLOSEBRACETOKEN" Then
                            CloseBraceStart = t.Span.Start
                        End If
                    Next
                    '' Split Class Definition in to individual lines
                    aClassDefinition = n
                    s4 = aClassDefinition.ToString   'entire class definition
                    If Not VersionGreaterThan_4_1_13 Then
                        s4 = s4.Replace("hs4.", "hs.")   ' replace hs4 with hs
                        s4 = s4.Replace("(hs4", "(hs")   'replace hs4 with hs
                        s4 = s4.Replace(",hs4", ",hs")   'replace hs4 with hs
                    End If
                    '' Strip off CLASS and CLASS END statements
                    i3 = OpenBraceStart - ClassStatementStart
                    i4 = CloseBraceStart - i3 - ClassStatementStart - 3
                    s3 = s4.Substring(i3 + 3, i4)   'Script with CLASS wrapper removed
                    ClassStatements = New Specialized.StringCollection
                    i1 = 0   'start at beginning of string
                    Do
                        i2 = s3.IndexOf(vbCrLf, i1)   'find end of line
                        If i2 < 0 Then
                            Exit Do   'no more lines
                        End If
                        s4 = s3.Substring(i1, i2 - i1)   'isolate single line
                        ClassStatements.Add(s4)   'save a line
                        i1 = i2 + 2   'next line
                        If i1 > s3.Length - 1 Then
                            Exit Do   'end of lines
                        End If
                    Loop
                    '' Add any USING statements already found in the file to each Class (Script)
                    For Each s As String In Imps
                        '' Insert the saved USING statements
                        ClassStatements.Insert(0, s)
                    Next
                    '' Have accumulated the Class definition, add it to collection
                    Try
                        If Exports.ContainsKey(ClassName) Then
                            '' Class already saved, this is duplicate
                            theFN = "????"
                            For Each ScrData As ScriptData In Scripts.Values
                                If ScrData.ClassName = ClassName Then
                                    theFN = ScrData.Filename
                                    Exit For
                                End If
                            Next
                            MsgBox("Scanning all of your Script Files (.cs)" & vbCrLf & vbCrLf &
                                   "  Currently scanning file: " & fn & vbCrLf & vbCrLf & "  Found duplicate Script (Class): " & ClassName &
                                   vbCrLf & vbCrLf &
                                    "  This definition of " & ClassName & " will be ignored" &
                                   vbCrLf & vbCrLf & "The first defintion of " & ClassName & " was found in File: " & theFN, , "Found duplicate Script (Class)")
                        Else
                            '' New Class, add to list
                            Exports.Add(ClassName, ClassStatements)
                        End If
                    Catch ex As Exception
                        MyLog("Exception Processing Class: " & ClassName, False, Logging.ELogType.Error)
                        MyLog("Exception: " & ex.Message, False, Logging.ELogType.Error)
                        MyLog("Suspect you have defined the Class more than once", False, Logging.ELogType.Info)
                        MyLog("This could be duplicates in multiple files in the project directory, even if they are not defined in the project itself.", False, Logging.ELogType.Info)
                        MyLog("Script Processing Truncated for " & ClassName, False, Logging.ELogType.Info)
                        End
                    End Try
                    MyLog("--Found Class " & ClassName.ToUpper, True)
                    '' Now, get all of the methods in this class
                    Console.WriteLine("Getting Methods for: " & ClassName)
                    Nodes2 = aClassDefinition.ChildNodes
                    For Each n2 As CSharpSyntaxNode In Nodes2
                        s5 = n2.Kind.ToString.ToUpper
                        If s5 = "METHODDECLARATION" Then
                            '' Found a Method
                            '' Save the method Name
                            Tokens2 = n2.ChildTokens()   'get components of the method Statement
                            MethodName = ""
                            FoundPublicKeyword = False
                            For Each t As Microsoft.CodeAnalysis.SyntaxToken In Tokens2
                                '' loop thru looking for Method Name
                                s2 = CType(t.RawKind, CSharp.SyntaxKind).ToString
                                If s2.ToUpper.Trim = "IDENTIFIERTOKEN" Then
                                    '' Found it
                                    MethodName = t.Text
                                End If
                                If s2.ToUpper.Trim = "PUBLICKEYWORD" Then
                                    FoundPublicKeyword = True
                                End If
                            Next
                            MyLog("----Found Sub " & MethodName.ToUpper & " in " & ClassName, True)
                            If FoundPublicKeyword Then
                                '' Method is PUBLIC so save it
                                sd = New ScriptData(fn, ClassName, MethodName, Me.GetType)
                                Try
                                    Scripts.Add(sd.ClassName & "." & sd.MethodName, sd)
                                Catch ex As Exception
                                    MyLog("Exception Processing Method: " & sd.ClassName & "." & sd.MethodName, False, Logging.ELogType.Error)
                                    MyLog("   Exception: " & ex.Message, False, Logging.ELogType.Error)
                                    MyLog("Suspect you have defined the Class and/or Method more than once", False, Logging.ELogType.Info)
                                    MyLog("This could be duplicates in multiple files in the project directory, even if they are not defined in the project itself.", False, Logging.ELogType.Info)
                                    MyLog("Script Processing Truncated for " & sd.ClassName & "." & sd.MethodName, False, Logging.ELogType.Error)
                                End Try
                            Else
                                MyLog("------Not declared PUBLIC, so method " & MethodName & " skipped", True)
                            End If
                        End If
                    Next
                Case "USINGDIRECTIVE"
                    '' Collect using statements to be added to each individual script
                    s6 = n.ToFullString
                    s6 = s6.Substring(0, s6.Length - 2)
                    Imps.Add(s6)   'save using statements
            End Select
        Next
    End Sub
    Friend Sub GetVbClasses(ByVal fn As String)
        ''
        '' Parse a VB source file, extracting Classes and Methods
        ''
        Dim ClassStatements As New Specialized.StringCollection
        Dim ClassName As String = ""
        Dim MethodName As String
        Dim Imps As New Specialized.StringCollection
        Dim theFN As String
        Dim theSource As String
        Dim tree As VisualBasicSyntaxTree
        Dim TreeNode As VisualBasicSyntaxNode
        Dim Nodes2, Nodes4 As IEnumerable(Of Microsoft.CodeAnalysis.SyntaxNode)
        Dim Tokens2 As IEnumerable(Of Microsoft.CodeAnalysis.SyntaxToken)
        Dim s2, s3, s4, s5, s7 As String
        Dim i1, i2, i3 As Integer
        Dim aClassDefinition As VisualBasicSyntaxNode
        Dim sd As ScriptData
        Dim FoundPublicKeyword As Boolean = False
        Dim ClassNodes, ImportsNodes, ClassStatementNodes As List(Of VisualBasicSyntaxNode)
        Dim ClassNodeStart, ClassStatementStart, ClassStatementLength As Integer
        Dim EndClassStatementStart, EndClassStatementLength As Integer
        Dim EndClassNodes As List(Of VisualBasicSyntaxNode)
        Dim IdentifierTokens As List(Of SyntaxToken)
        '' Get Script file
        theSource = My.Computer.FileSystem.ReadAllText(fn)
        '' Parse source in to a Syntax Tree
        tree = CType(VisualBasicSyntaxTree.ParseText(theSource), Microsoft.CodeAnalysis.VisualBasic.VisualBasicSyntaxTree)
        TreeNode = tree.GetRoot()
        '' Get Import Statements
        ImportsNodes = GetChildNodes(TreeNode, "ImportsStatement")
        Imps.Clear()
        For Each anImportsNode As SyntaxNode In ImportsNodes
            s2 = anImportsNode.ToFullString   'get complete Imports statement
            s2 = s2.Substring(0, s2.Length - 2)   'drop VbCrLf
            Imps.Add(s2)   'save Imports statements
        Next
        '' Get ClassBlocks
        ClassNodes = GetChildNodes(TreeNode, "ClassBlock")
        For Each aClassNode As VisualBasicSyntaxNode In ClassNodes
            ClassNodeStart = aClassNode.Span.Start
            '' Get the Class End Statement
            EndClassNodes = GetChildNodes(aClassNode, "EndClassStatement")
            EndClassStatementStart = EndClassNodes(0).Span.Start
            EndClassStatementLength = EndClassNodes(0).Span.Length
            '' Get the Class Statement
            ClassStatementNodes = GetChildNodes(aClassNode, "ClassStatement")
            ClassStatementStart = ClassStatementNodes(0).Span.Start
            ClassStatementLength = ClassStatementNodes(0).Span.Length
            '' Get the Class Name
            IdentifierTokens = GetChildTokens(ClassStatementNodes(0), "IdentifierToken")
            For Each t As Microsoft.CodeAnalysis.SyntaxToken In IdentifierTokens
                '' loop thru looking for Class Name
                s2 = CType(t.RawKind, VisualBasic.SyntaxKind).ToString
                If s2.ToUpper.Trim = "IDENTIFIERTOKEN" Then
                    '' Found it
                    ClassName = t.Text   'save the class name
                    Exit For
                End If
            Next
            '' Split Class Definition in to individual lines
            aClassDefinition = aClassNode
            s4 = aClassDefinition.ToString   ' Full Class definition from xxx.vb File
            If Not VersionGreaterThan_4_1_13 Then
                s4 = s4.Replace("hs4.", "hs.")   ' replace hs4 with hs
                s4 = s4.Replace("(hs4", "(hs")   'replace hs4 with hs
                s4 = s4.Replace(",hs4", ",hs")   'replace hs4 with hs
            End If
            '' Strip off CLASS and CLASS END statements
            i3 = ClassStatementStart - ClassNodeStart   'Start of CLASS statement
            s4 = s4.Substring(i3 + ClassStatementLength + 2)   'strip off Class stetement
            s4 = s4.Substring(0, s4.Length - EndClassStatementLength)
            s3 = s4  'entire class definition, without CLASS and END CLASS
            ClassStatements = New Specialized.StringCollection
            i1 = 0   'start at beginning of string
            Do
                i2 = s3.IndexOf(vbCrLf, i1)   'find end of line
                If i2 < 0 Then
                    Exit Do   'no more lines
                End If
                s4 = s3.Substring(i1, i2 - i1)   'isolate single line
                ClassStatements.Add(s4)   'save a line
                i1 = i2 + 2   'next line
                If i1 > s3.Length - 1 Then
                    Exit Do   'end of lines
                End If
            Loop
            '' Add any IMPORTS statements already found in the file to each Class (Script)
            For Each s As String In Imps
                '' Insert the saved USING statements
                ClassStatements.Insert(0, s)
            Next
            '' Have accumulated the Class definition, add it to collection
            Try
                If Exports.ContainsKey(ClassName) Then
                    '' Class already saved, this is duplicate
                    theFN = "????"
                    For Each ScrData As ScriptData In Scripts.Values
                        If ScrData.ClassName = ClassName Then
                            theFN = ScrData.Filename
                            Exit For
                        End If
                    Next
                    MsgBox("Scanning all of your Script Files (.vb)" & vbCrLf & vbCrLf &
                                   "  Currently scanning file: " & fn & vbCrLf & vbCrLf & "  Found duplicate Script (Class): " & ClassName &
                                   vbCrLf & vbCrLf &
                                    "  This definition of " & ClassName & " will be ignored" &
                                   vbCrLf & vbCrLf & "The first defintion of " & ClassName & " was found in File: " & theFN, , "Found duplicate Script (Class)")
                Else
                    '' New Class, add to list
                    Exports.Add(ClassName, ClassStatements)
                End If
            Catch ex As Exception
                MyLog("Exception Processing Class: " & ClassName, False, Logging.ELogType.Error)
                MyLog("Exception: " & ex.Message, False, Logging.ELogType.Error)
                MyLog("Suspect you have defined the Class more than once", False, Logging.ELogType.Info)
                MyLog("This could be duplicates in multiple files in the project directory, even if they are not defined in the project itself.", False, Logging.ELogType.Info)
                MyLog("Script Processing Truncated for " & ClassName, False, Logging.ELogType.Info)
                End
            End Try
            MyLog("--Found Class " & ClassName.ToUpper, True)
            '' Now, get all of the methods in this class
            Console.WriteLine("Getting Methods for: " & ClassName)
            Nodes2 = aClassDefinition.ChildNodes
            For Each n2 As VisualBasicSyntaxNode In Nodes2
                s5 = n2.Kind.ToString.ToUpper
                If s5 = "SUBBLOCK" Then
                    '' Found a Method, get the SUB Statement
                    Nodes4 = n2.ChildNodes
                    For Each nn2 As VisualBasicSyntaxNode In Nodes4
                        s7 = nn2.Kind.ToString.ToUpper
                        If s7 = "SUBSTATEMENT" Then
                            '' Now get the Method name
                            Tokens2 = nn2.ChildTokens()   'get components of the method Statement
                            MethodName = ""
                            FoundPublicKeyword = False
                            For Each t As Microsoft.CodeAnalysis.SyntaxToken In Tokens2
                                '' loop thru looking for Method Name
                                s2 = CType(t.RawKind, VisualBasic.SyntaxKind).ToString
                                If s2.ToUpper.Trim = "IDENTIFIERTOKEN" Then
                                    '' Found it
                                    MethodName = t.Text
                                End If
                                If s2.ToUpper.Trim = "PUBLICKEYWORD" Then
                                    FoundPublicKeyword = True
                                End If
                            Next
                            MyLog("----Found Sub " & MethodName.ToUpper & " in " & ClassName, True)
                            If FoundPublicKeyword Then
                                '' Method is PUBLIC so save it
                                sd = New ScriptData(fn, ClassName, MethodName, Me.GetType)
                                Try
                                    Scripts.Add(sd.ClassName & "." & sd.MethodName, sd)
                                Catch ex As Exception
                                    MyLog("Exception Processing Method: " & sd.ClassName & "." & sd.MethodName, False, Logging.ELogType.Error)
                                    MyLog("   Exception: " & ex.Message, False, Logging.ELogType.Error)
                                    MyLog("Suspect you have defined the Class and/or Method more than once", False, Logging.ELogType.Info)
                                    MyLog("This could be duplicates in multiple files in the project directory, even if they are not defined in the project itself.", False, Logging.ELogType.Info)
                                    MyLog("Script Processing Truncated for " & sd.ClassName & "." & sd.MethodName, False, Logging.ELogType.Info)
                                End Try
                            Else
                                MyLog("------Not declared PUBLIC, so method " & MethodName & " skipped", True)
                            End If
                        End If
                    Next
                End If
            Next
        Next
    End Sub
    Friend Function GetChildNodes(ParentNode As VisualBasicSyntaxNode, Kind As String) As List(Of VisualBasicSyntaxNode)
        ''
        '' Get Child Syntax Nodes of a specified Kind
        ''
        Dim Nodes As IEnumerable(Of Microsoft.CodeAnalysis.SyntaxNode)
        Dim ReturnNodes As New List(Of VisualBasicSyntaxNode)
        Nodes = ParentNode.ChildNodes 'get the child nodes
        '' Find matching nodes
        ReturnNodes.Clear()
        For Each n As VisualBasicSyntaxNode In Nodes
            If n.Kind.ToString.ToUpper = Kind.ToUpper Then
                ReturnNodes.Add(n)
            End If
        Next
        Return ReturnNodes
    End Function
    Friend Function GetChildTokens(ParentNode As VisualBasicSyntaxNode, Kind As String) As List(Of Microsoft.CodeAnalysis.SyntaxToken)
        ''
        '' Get Child Syntax Tokens of a specified Kind
        ''
        Dim Tokens As IEnumerable(Of Microsoft.CodeAnalysis.SyntaxToken)
        Dim ReturnTokens As New List(Of Microsoft.CodeAnalysis.SyntaxToken)
        Dim s1 As String
        Tokens = ParentNode.ChildTokens 'get the child tokens
        '' Find matching tokens
        ReturnTokens.Clear()
        For Each t As SyntaxToken In Tokens
            s1 = CType(t.RawKind, VisualBasic.SyntaxKind).ToString
            If s1.ToUpper = Kind.ToUpper Then
                ReturnTokens.Add(t)
            End If
        Next
        Return ReturnTokens
    End Function
    Friend Sub DeleteDebugLog()
        Dim dir As String
        dir = My.Settings.DebugLogPath
        If dir.Substring(dir.Length - 1, 1) <> "\" Then dir = dir & "\"
        If IO.Directory.Exists(dir) Then
            '' Found Directory
            Try
                If IO.File.Exists(dir & "Debug_Composite.Log") Then
                    IO.File.Delete(dir & "Debug_Composite.Log")
                    MyLog("Deleted: " & dir & "Debug_Composite.Log", True)
                End If
            Catch ex As Exception
                MyLog("Exception Trying to Delete Debug Log: " & dir & "Debug_Composite.Log", False, Logging.ELogType.Error)
                MyLog("... " & ex.Message, False, Logging.ELogType.Error)
            End Try
        Else
            '' Directory Not Found
            MyLog("Debug Log Directory Not Found: " & dir, False, Logging.ELogType.Error)
        End If
    End Sub
    Private Sub SetRunButtonText()
        Dim s, p As String
        '' Get Script name
        If Me.cboMethods.Items.Count > 0 Then
            s = Me.cboClasses.Items(Me.cboClasses.SelectedIndex).ToString & "." & Me.cboMethods.Items(Me.cboMethods.SelectedIndex).ToString
        Else
            s = ""
        End If
        '' Get parms
        p = """" & Me.txtParms.Text & """"
        Me.btnRunSubMain.Text = s & "(" & p & ")"
    End Sub
    Private Sub btnRunSubMain_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnRunSubMain.Click
        Dim s, p As String
        Dim ss(0) As Object
        Dim sss() As String
        '' Make sure that all selection have been made before trying to Run
        If cboFiles.SelectedIndex < 0 Or cboClasses.SelectedIndex < 0 Or cboMethods.SelectedIndex < 0 Then
            MsgBox("You must select a File, Class, and Method",, "tenScripting")
            MyLog("One of the CBOs have a SelectedIndex < 0", False, Logging.ELogType.Error)
            Exit Sub
        End If
        '' Check that the File that is to be run has been included in the Project File
        s = Me.cboFiles.Items(Me.cboFiles.SelectedIndex).ToString
        If Not ProjectFiles.Keys.Contains(s.ToUpper) Then
            '' VB/CS file was in the project folder, but not in the Project File.  Cannot run it
            MsgBox("You cannot Run " & s & vbCrLf & vbCrLf & "It was not included in the Project and was not compiled" & vbCrLf & vbCrLf & "Add it to the Project using VS Menu item Project/Add Existing Item...",, "tenScripting")
            MyLog(s & " cannot be run because it is not included in the project", False, Logging.ELogType.Error)
            Exit Sub
        End If
        '' Save the Selection Boxes
        My.Settings.LastFile = Me.cboFiles.Items(Me.cboFiles.SelectedIndex).ToString
        My.Settings.LastClass = Me.cboClasses.Items(Me.cboClasses.SelectedIndex).ToString
        My.Settings.LastMethod = Me.cboMethods.Items(Me.cboMethods.SelectedIndex).ToString
        My.Settings.Save()
        MyLog("Saving CBO Values:" & My.Settings.LastFile & "." & My.Settings.LastClass & "." & My.Settings.LastMethod, True, Logging.ELogType.Info)
        '' Save the Parms for this Script
        s = Me.cboClasses.Items(Me.cboClasses.SelectedIndex).ToString & "." & Me.cboMethods.Items(Me.cboMethods.SelectedIndex).ToString
        '''' Remove any existing entry
        For i As Integer = 0 To My.Settings.Parms.Count - 1
            p = My.Settings.Parms(i)
            If s.Length + 1 <= p.Length Then
                If p.Substring(0, s.Length + 1).ToUpper = s.ToUpper & "=" Then
                    My.Settings.Parms.RemoveAt(i)
                    Exit For
                End If
            End If
        Next i
        '''' Now save the current parm
        My.Settings.Parms.Add(s.ToUpper & "=" & Me.txtParms.Text.ToString)
        My.Settings.Save()
        '' Get the Parms
        s = Me.txtParms.Text.ToString
        If My.Settings.ParameterType = 1 Then
            '' Process as HS parms: Only single parm
            ss(0) = s
        Else
            '' Process as normal parms (HsTouch for Example): Parms separated by ","
            sss = s.Split(ToChar(","))
            ss(0) = sss
        End If
        '' Run the Script
        MyLog("Running Script " & Me.cboClasses.Items(Me.cboClasses.SelectedIndex).ToString, True, Logging.ELogType.Info)
        RunScript(Me.cboClasses.Items(Me.cboClasses.SelectedIndex).ToString, Me.cboMethods.Items(Me.cboMethods.SelectedIndex).ToString, ss)
        Me.lblScriptRunning.Visible = False
        btnExportThisScript.Show()
    End Sub
    Friend Sub RunScript(ByVal pClass As String, ByVal pMethod As String, ByVal pParms() As Object)
        Dim anObj As Object, t As Type
        Dim s As String
        Dim sd As ScriptData
        If pMethod.ToUpper = "MAIN" And pMethod <> "Main" Then
            MyLog("Warning:  Method name= " & pMethod & "   HS will only find 'Main' as a default method", False, Logging.ELogType.Info)
            MsgBox("Warning:  Method name= " & pMethod & "   HS will only find 'Main' as a default method", , "tenScripting")
        End If
        '' Hide some buttons
        btnExportThisScript.Hide()
        Me.lblScriptRunning.Visible = True
        Me.lblScriptRunning.Refresh()
        '' Create instance of class containing script to run
        s = pClass & "." & pMethod
        If Not Scripts.Keys.Contains(s) Then
            MsgBox("Attempt to run a script that is not defined to tenScripting: " & s,, "tenScripting")
            Exit Sub
        End If
        sd = Scripts(s)
        t = sd.oType
        anObj = Activator.CreateInstance(t)
        '' Log we are now running a script
        MyLog("****************************** Debug Started for " & sd.ClassName & "." & sd.MethodName, False, Logging.ELogType.Info)
        '' Run the Script
        Try
            t.InvokeMember(sd.MethodName, BindingFlags.InvokeMethod Or BindingFlags.Instance Or
                BindingFlags.Public Or BindingFlags.IgnoreCase,
                Nothing, anObj, pParms, Nothing, Nothing, Nothing)
        Catch ex As Exception
            MyLog(">>> Exception", False, Logging.ELogType.Error)
            MyLog(">>> " & ex.Message, False, Logging.ELogType.Error)
            If Not IsNothing(ex.InnerException) Then
                MyLog(">>>>> " & ex.InnerException.Message, False, Logging.ELogType.Error)
                MyLog(">>>>> " & ex.InnerException.StackTrace, False, Logging.ELogType.Error)
            End If
            Beep()
            MsgBox("Execution Error in " & sd.ClassName & "." & sd.MethodName & ", see tenScripting Log")
            '' Open the LOG display
            btnOpenClose.Text = "Close"
            lstLog.Show()
            lstLog.BringToFront()
        Finally
        End Try
        MyLog("****************************** Debug Ended for " & sd.ClassName & "." & sd.MethodName, False, Logging.ELogType.Info)
    End Sub
    Private Sub txtParms_TextChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles txtParms.TextChanged
        SetRunButtonText()
    End Sub
    Private Sub ExittenScripting()
        '' Save the Selection Boxes
        My.Settings.LastFile = Me.cboFiles.Items(Me.cboFiles.SelectedIndex).ToString
        My.Settings.LastClass = Me.cboClasses.Items(Me.cboClasses.SelectedIndex).ToString
        My.Settings.LastMethod = Me.cboMethods.Items(Me.cboMethods.SelectedIndex).ToString
        My.Settings.Save()
        '' Turn OFF HS Debug Logging
        Try
            My.Settings.FormLeft = Me.Left
            My.Settings.FormTop = Me.Top
            My.Settings.Save()
            MyLog("tenScripting Closing", True)
            isShutdown = True
        Catch ex As Exception
        End Try
        Console.WriteLine("ExittenScripting set isShutdown=True")
    End Sub
    Private Sub ExportScriptsToolStripMenuItem_Click_1(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ExportScriptsToolStripMenuItem.Click
        '' Display the Script Export Form
        FastExport = False
        For Each s As String In Me.cboFiles.Items
            ExportForm.cboFiles.Items.Add(s)
        Next
        ExportForm.cboFiles.SelectedIndex = theMainForm.cboFiles.SelectedIndex
        ExportForm.ShowDialog()
        ExportForm.cboFiles.Items.Clear()
    End Sub
    Private Sub DonationToCysticFibrosisFoundationToolStripMenuItem_Click(ByVal sender As System.Object, ByVal e As System.EventArgs)
        Dim p As String
        p = "https://www.tenholder.net/CharityWare/"
        Process.Start(p)
    End Sub
    Function Version() As String
        With _
       System.Diagnostics.FileVersionInfo.GetVersionInfo(System.Reflection.Assembly.GetExecutingAssembly.Location)
            Return .FileMajorPart & "." & .FileMinorPart
        End With
    End Function
    Private Sub CFFToolStripMenuItem_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles CFFToolStripMenuItem.Click
        Dim p As String
        p = "https://www.tenholder.net/tenWare2/CharityWare.aspx"
        Process.Start(p)
    End Sub
    Private Sub ConnectionToolStripMenuItem_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ConnectionToolStripMenuItem.Click
        Dim ConnectForm As frmConnection
        ConnectForm = New frmConnection
        ConnectForm.ShowDialog()
        ConnectForm = Nothing
    End Sub
    Private Sub cboScripts_SelectedIndexChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles cboMethods.SelectedIndexChanged
        Dim s As String
        '' Get selected Script
        s = Me.cboClasses.Items(Me.cboClasses.SelectedIndex).ToString & "." & Me.cboMethods.Items(Me.cboMethods.SelectedIndex).ToString
        Me.txtParms.Text = ""
        For Each p As String In My.Settings.Parms
            '' Check if Parms are stored for this Script
            If s.Length + 1 <= p.Length Then
                If p.Substring(0, s.Length + 1).ToUpper = s.ToUpper & "=" Then
                    '' Place Parms into control
                    Me.txtParms.Text = p.Substring(s.Length + 1)
                    Exit For
                End If
            End If
        Next
        SetRunButtonText()
    End Sub
    Private Sub cboFiles_SelectedIndexChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles cboFiles.SelectedIndexChanged
        Dim cFile, dFile As String, Found As Boolean
        cFile = Me.cboFiles.Items(Me.cboFiles.SelectedIndex).ToString.ToUpper
        Me.cboClasses.Items.Clear()
        For Each sd As ScriptData In Scripts.Values
            dFile = IO.Path.GetFileName(sd.Filename).ToUpper
            If dFile = cFile Then
                '' Only add if not there already (multiple methods for same class)
                Found = False
                For Each s As String In cboClasses.Items
                    If s = sd.ClassName Then
                        Found = True
                        Exit For
                    End If
                Next
                If Not Found Then Me.cboClasses.Items.Add(sd.ClassName)
            End If
        Next
        If Me.cboClasses.Items.Count > 0 Then
            '' Determine Class Selection
            Me.cboClasses.SelectedIndex = 0
            For i As Integer = 0 To Me.cboClasses.Items.Count - 1
                If Me.cboClasses.Items(i).ToString = My.Settings.LastClass Then
                    Me.cboClasses.SelectedIndex = i
                    Exit For
                End If
            Next
        End If
        Me.cboClasses.Refresh()
    End Sub
    Private Sub cboClasses_SelectedIndexChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles cboClasses.SelectedIndexChanged
        Dim cClass, dClass As String
        cClass = Me.cboClasses.Items(Me.cboClasses.SelectedIndex).ToString.ToUpper
        Me.cboMethods.Items.Clear()
        For Each sd As ScriptData In Scripts.Values
            dClass = IO.Path.GetFileName(sd.ClassName).ToUpper
            If dClass = cClass Then
                Me.cboMethods.Items.Add(sd.MethodName)
            End If
        Next
        If Me.cboMethods.Items.Count > 0 Then
            '' Determine Method Selection
            Me.cboMethods.SelectedIndex = 0
            For i As Integer = 0 To Me.cboMethods.Items.Count - 1
                If Me.cboMethods.Items(i).ToString = My.Settings.LastMethod Then
                    Me.cboMethods.SelectedIndex = i
                    Exit For
                End If
            Next
        End If
        Me.cboMethods.Refresh()
    End Sub
    Private Sub TenScriptingWebSiteToolStripMenuItem_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles TenScriptingWebSiteToolStripMenuItem.Click
        ''
        '' Display tenScripting Web Site in Browser
        ''
        Dim p As String

        p = "https://tenholder.net/tenWare2/tenScripting4/default.aspx"
        Process.Start(p)
    End Sub
    Private Sub HomeSeerHelpFileToolStripMenuItem_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles HomeSeerHelpFileToolStripMenuItem.Click
        ''
        '' Display HomeSeer Help File in Browser
        ''
        Dim p As String
        p = "https://help.homeseer.com/help/hs3/static/default.htm#.scripting"
        Process.Start(p)
    End Sub
    Private Sub HomeSeerSDKToolStripMenuItem_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles HomeSeerSDKToolStripMenuItem.Click
        ''
        '' Display HomeSeer SDK in Browser
        ''
        Dim p As String
        p = "https://homeseer.github.io/Plugin-SDK-Docs/api/HomeSeer.PluginSdk.IHsController.html?tabs=cs"
        Process.Start(p)
    End Sub
    Private Sub picHS_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles picHS.Click
        ''
        '' Display HomeSeer Status Page
        ''
        Dim p As String
        p = "http://" & My.Settings.HsComputer & ":" & hs.GetINISetting("Settings", "gWebSvrPort", "80")
        Process.Start(p)
    End Sub
    Private Sub btnDebugLogs_Click(ByVal sender As System.Object, ByVal e As System.EventArgs)
        ''
        '' Display HomeSeer Debug Log
        ''
        Dim dir As String
        dir = My.Settings.DebugLogPath
        If dir.Substring(dir.Length - 1, 1) <> "\" Then dir = dir & "\"
        If IO.File.Exists(dir & "Debug_Composite.Log") Then
            '' File Exists
            If Me.DebugLogProccess Is Nothing Then
                '' Notepad not already open
                Me.DebugLogProccess = Process.Start("Notepad.exe", dir & "Debug_Composite.Log")
            Else
                If Not Me.DebugLogProccess.HasExited Then
                    '' Notepad still running
                    Me.DebugLogProccess.Kill()
                    Me.DebugLogProccess = Nothing
                    Me.DebugLogProccess = Process.Start("Notepad.exe", dir & "Debug_Composite.Log")
                Else
                    Me.DebugLogProccess = Nothing
                    Me.DebugLogProccess = Process.Start("Notepad.exe", dir & "Debug_Composite.Log")
                End If
            End If
        Else
            '' File does not exist
            MyLog("Could not find Debug Log: " & dir & "Debug_Composite.Log", False, Logging.ELogType.Error)
        End If
    End Sub
    Friend Sub MyLog(ByVal t As String, Optional Debug As Boolean = False, Optional Level As Logging.ELogType = Logging.ELogType.Info)
        '' Debug:
        ''    False=  HS log, TS log, Debug File, Console
        ''    True= Debug File, Console
        If Debug Then
            '' Write to Debug File, Console
            ' Console
            Console.WriteLine(Format(Now, "hh:mm:ss") & " " & t)
            ' Debug File
            Try
                If DebugWriter IsNot Nothing Then
                    DebugWriter.WriteLine(Format(Now, "hh:mm:ss") & " " & t)
                    DebugWriter.Flush()
                End If
            Catch ex As Exception
                '' Ignore errors
            End Try
        Else
            '' Write to HS log, TS log, Debug File, Console
            ' TS log
            Me.lstLog.Items.Add(Format(Now, "hh:mm:ss") & " " & t)
            Me.lstLog.SelectedIndex = Me.lstLog.Items.Count - 1
            Me.lstLog.Refresh()
            lstLog.SelectedItems.Clear()
            btnOpenClose.ForeColor = Color.Red
            ' Console
            Console.WriteLine(Format(Now, "hh:mm:ss") & " " & t)
            ' HS log
            If hs4 IsNot Nothing Then
                hs4.WriteLog(Level, Format(Now, "hh:mm:ss") & " " & t, "tenScripting4")
            End If
            ' Debug File
            Try
                If DebugWriter IsNot Nothing Then
                    DebugWriter.WriteLine(Format(Now, "hh:mm:ss") & " " & t)
                    DebugWriter.Flush()
                End If
            Catch ex As Exception
                '' Ignore errors
            End Try
        End If
    End Sub
    Private Sub ImportScriptsToolStripMenuItem_Click(sender As System.Object, e As System.EventArgs) Handles ImportScriptsToolStripMenuItem.Click
        Dim ImportForm As frmScriptImport
        '' Display the Script Inport Form
        ImportForm = New frmScriptImport
        For Each s As String In Me.cboFiles.Items
            ImportForm.cboFiles.Items.Add(s)
        Next
        ImportForm.ShowDialog()
        ImportForm = Nothing
    End Sub
    Private Sub btnCopytenLog_Click(sender As System.Object, e As System.EventArgs)
        Dim s As String = " "
        For Each ss As String In lstLog.SelectedItems
            s = s & ss & vbCrLf
        Next
        Clipboard.SetText(s)
    End Sub
    Private Sub btnExit_Click(sender As System.Object, e As System.EventArgs) Handles btnExit.Click
        Me.ExittenScripting()
    End Sub
    Private Sub btnOpenClose_Click(sender As Object, e As EventArgs) Handles btnOpenClose.Click
        If btnOpenClose.Text = "Open" Then
            btnOpenClose.Text = "Close"
            lstLog.Show()
            lstLog.BringToFront()
        Else
            btnOpenClose.Text = "Open"
            lstLog.Hide()
        End If
        btnOpenClose.ForeColor = Color.Black
    End Sub
    Private Sub BtnNewVersion_Click(sender As Object, e As EventArgs) Handles btnNewVersion.Click
        '' Go to Download Page for new product version
        Dim theURL As String
        theURL = GetCurrentVersion("tenScripting4")(1)
        Process.Start(theURL)
    End Sub
    Private Function GetCurrentVersion(theProduct As String) As String()
        ''''
        Dim VersionsURL As String = "https://tenholder.net/tenWare2/ProductVersions.xml"
        Dim aDocument As New XmlDocument()
        Dim aNodeList As XmlNodeList
        Dim aNode As XmlNode
        Dim theCurrentVersion As String
        Dim theURL As String
        Dim Results(1) As String
        '''' (0) Current Version Number
        '''' (1) URL to download current version
        '' Get Version Information
        Results(0) = "0"
        Try
            aDocument.Load(VersionsURL)
        Catch ex As Exception
            MyLog("GetCurrentVersion Failed to retrieve " & VersionsURL, False, Logging.ELogType.Error)
            Return Results
        End Try
        '' Current Version
        aNodeList = aDocument.DocumentElement.SelectNodes("/Products/" & theProduct & "/CurrentVersion")
        If aNodeList.Count > 0 Then
            aNode = aNodeList.Item(0)
            theCurrentVersion = aNode.FirstChild.InnerText
            Results(0) = theCurrentVersion
        End If
        '' Download URL
        aNodeList = aDocument.DocumentElement.SelectNodes("/Products/" & theProduct & "/URL")
        If aNodeList.Count > 0 Then
            aNode = aNodeList.Item(0)
            theURL = aNode.FirstChild.InnerText
            Results(1) = theURL
        End If
        Return Results
    End Function
    Private Sub btnExportThisScript_Click(sender As Object, e As EventArgs) Handles btnExportThisScript.Click
        '' Display the Script Export Form, for just the default Script
        FastExport = True
        For Each s As String In Me.cboFiles.Items
            ExportForm.cboFiles.Items.Add(s)
        Next
        ExportForm.cboFiles.SelectedIndex = theMainForm.cboFiles.SelectedIndex
        ExportForm.ShowDialog()
        ExportForm.cboFiles.Items.Clear()
    End Sub
    Public Sub AutoScriptEvent(parms As String)
        ''
        ''  This Code is run when a HS script requests tenScripting to run a script via tenScripting
        ''
        ''    HS Event-->RunScript tenRunScript.vb-->Invokes HSPI.PluginFunction.AutoRunScript-->Invokes tenScripting.AutoScriptEvent (this code)
        ''
        ''  tenRunScript: Single Parm:  ScriptName|ScriptMethod|Your Script's Parameters
        ''
        ''    This code is run on the form's UI thread
        ''
        Dim ss() As String
        Dim ScriptName, ScriptMethod, Parameters As String
        Dim pParms(0) As Object
        MyLog("AutoRunScript Invoked with parms: " & parms, False, Logging.ELogType.Info)
        '' Extract Parameters
        ss = parms.Split(Convert.ToChar("|"))   'extract individual parameters
        If ss.Count < 2 Then
            MyLog("You must specify at least 2 parameters, ScriptName and ScriptMethod", False, Logging.ELogType.Error)
            MyLog("AutoScriptEvent Parms: " & parms.ToString, False, Logging.ELogType.Error)
            Exit Sub
        End If
        ScriptName = ss(0)
        ScriptMethod = ss(1)
        Parameters = ""   'target script parameters
        If ss.Count > 2 Then
            For i As Integer = 2 To ss.Count - 1
                Parameters = Parameters & ss(i) & "|"   'add in each parameters
            Next
            Parameters = Parameters.Substring(0, Parameters.Length - 1)   'strip out last |
        End If
        MyLog("AutoScriptEvent Script: " & ss(0) & ",       Method: " & ss(1), False, Logging.ELogType.Info)
        If ss.Count > 2 Then
            MyLog("__AutoScriptEvent Parms: " & Parameters, False, Logging.ELogType.Info)
        End If
        pParms(0) = Parameters
        RunScript(ScriptName, ScriptMethod, pParms)
        Me.lblScriptRunning.Visible = False
        btnExportThisScript.Show()
    End Sub
    Private Sub ToolsMnuScriptingReferences_Click(sender As Object, e As EventArgs) Handles ToolsMnuScriptingReferences.Click
        OpenScriptingReferenceForm()
    End Sub
    Private Sub ToolsMnuTenScriptAid_Click(sender As Object, e As EventArgs) Handles ToolsMnuTenScriptAid.Click
        RunTenscriptaid()
    End Sub
    Sub RunTenscriptaid()
        '' Run tenScriptAid Program
        Dim SavedLocation As String = My.Computer.FileSystem.SpecialDirectories.MyDocuments & "\tenScriptAid4Location.txt"
        Dim p As String
        '' Get Location of tenScriptAid.exe
        If Not System.IO.File.Exists(SavedLocation) Then
            '' File with saved location not found
            MsgBox("Could not find the saved location of tenScriptAid" & Environment.NewLine & Environment.NewLine & "Make sure that you have run tenScriptAid 4.1 or higher at least once",, "tenScripting4")
            Exit Sub
        End If
        p = System.IO.File.ReadAllText(SavedLocation, System.Text.Encoding.ASCII)
        If Not System.IO.File.Exists(p) Then
            MsgBox("Invalid saved location of tenScriptAid" & Environment.NewLine & Environment.NewLine & "Make sure that you have run tenScriptAid 1.25 or higher at least once",, "tenScripting4")
            Exit Sub
        End If
        Process.Start(p)        ''
    End Sub
    Private Sub ToolsMnuCheckForUpdates_Click(sender As Object, e As EventArgs) Handles ToolsMnuCheckForUpdates.Click
        '' Open Program Updates Dialog
        Dim theDialog As New frmUpdateProgram
        Dim NewVersion As String
        theDialog.chkAutoUpdates.Checked = My.Settings.AutoUpdates
        theDialog.ShowDialog()
        My.Settings.AutoUpdates = theDialog.chkAutoUpdates.Checked
        My.Settings.Save()
        theDialog.Dispose()
        theDialog = Nothing
        NewVersion = CheckForProgramUpdates()
    End Sub
    Private Sub cboParameters_SelectedIndexChanged(sender As Object, e As EventArgs) Handles cboParameters.SelectedIndexChanged
        If StartupComplete Then
            My.Settings.ParameterType = cboParameters.SelectedIndex
            My.Settings.Save()
        End If
        If My.Settings.ParameterType = 1 Then
            lblParmWarning.Hide()
        Else
            lblParmWarning.Show()
        End If
    End Sub
    Private Sub btnOpenHsLog_Click(sender As Object, e As EventArgs) Handles btnOpenHsLog.Click
        ''
        '' Display HomeSeer Log Page
        ''
        Dim p As String
        p = "http://" & My.Settings.HsComputer & ":" & hs.GetINISetting("Settings", "gWebSvrPort", "80") & "/log.html"
        Process.Start(p)
    End Sub
    Private Sub btnTenscriptaid_Click(sender As Object, e As EventArgs) Handles btnTenscriptaid.Click
        RunTenscriptaid()
    End Sub
End Class
Class ScriptData
    Dim _FileName As String
    Dim _ClassName As String
    Dim _MethodName As String
    Dim _oType As Type
    Dim _Parms As String
    Friend Sub New(ByVal FileName As String, ByVal ClassName As String, ByVal MethodName As String, ByVal oType As Type)
        _FileName = FileName
        _ClassName = ClassName
        _MethodName = MethodName
        _oType = oType
    End Sub
    Friend Property Parms() As String
        Get
            Return _Parms
        End Get
        Set(ByVal value As String)
            _Parms = value
        End Set
    End Property
    Friend ReadOnly Property Filename() As String
        Get
            Return _FileName
        End Get
    End Property
    Friend ReadOnly Property ClassName() As String
        Get
            Return _ClassName
        End Get
    End Property
    Friend ReadOnly Property MethodName() As String
        Get
            Return _MethodName
        End Get
    End Property
    Friend Property oType() As Type
        Get
            Return _oType
        End Get
        Set(ByVal value As Type)
            _oType = value
        End Set
    End Property
End Class

