diff --git a/GUIs.ZooFlow/ClassProfileFilter.vb b/GUIs.ZooFlow/ClassProfileFilter.vb deleted file mode 100644 index 49d7bccc..00000000 --- a/GUIs.ZooFlow/ClassProfileFilter.vb +++ /dev/null @@ -1,548 +0,0 @@ -Imports System.Text.RegularExpressions -Imports DigitalData.Modules.Language.Utils -Imports DigitalData.Modules.Logging -Imports DigitalData.Modules.Windows -Imports DigitalData.Modules.ZooFlow.Params - -Public Class ClassProfileFilter - Private _ProfileTable As DataTable - Private _ProcessTable As DataTable - Private _WindowTable As DataTable - Private _ControlTable As DataTable - Private _Profiles As List(Of ProfileData) - Private _DebugData As DebugData - Private _Logger As Logger - Private _Window As Window - - Private _TreeView As New TreeView - - ' TODO: Fill this Class!!!! :D - Class DebugData - Public ProcessMatch As List(Of String) - Public ClipboardMatch As List(Of String) - Public WindowMatch As List(Of String) - Public WindowRegexMatch As List(Of String) - End Class - - Public ReadOnly Property Profiles As List(Of ProfileData) - Get - Return _Profiles - End Get - End Property - - Public ReadOnly Property DebugTree As TreeView - Get - Return _TreeView - End Get - End Property - - - Public Sub New(LogConfig As LogConfig, ProfileDatatable As DataTable, ProcessTable As DataTable, WindowDatatable As DataTable, ControlDatatable As DataTable) - Try - _Logger = LogConfig.GetLogger() - _DebugData = New DebugData() - _ProfileTable = ProfileDatatable - _ProcessTable = ProcessTable - _WindowTable = WindowDatatable - _ControlTable = ControlDatatable - _Profiles = TransformProfiles() - _Window = New Window(LogConfig) - Catch ex As Exception - _Logger.Error(ex) - Throw ex - End Try - End Sub - - Public Function ToList() As List(Of ProfileData) - Return _Profiles - End Function - - Private Function FindNode(ByVal Node As TreeNode, SearchTerm As String) - Dim oNode As TreeNode - For Each oNode In Node.Nodes - If oNode.Text = SearchTerm Then - Return oNode - End If - Next - Return Node - End Function - - Private Function GetLowestNode(ByVal Node As TreeNode) As TreeNode - If Node.GetNodeCount(False) = 1 Then - Return GetLowestNode(Node.Nodes.Item(0)) - Else - Return Node - End If - End Function - - Public Function FilterProfilesByClipboardRegex(Profiles As List(Of ProfileData), ClipboardContents As String) As List(Of ProfileData) - Dim oFilteredProfiles As New List(Of ProfileData) - For Each oProfile In Profiles - _Logger.Debug("Current Profile: {0}", oProfile.Name) - - Try - Dim oRegex As New Regex(oProfile.Regex) - Dim oMatch = oRegex.Match(ClipboardContents) - If oMatch.Success Then - _Logger.Debug("FilterProfilesByClipboardRegex: Clipboard Regex Matched: {0}", ClipboardContents) - 'TODO: Add Debug Data - oFilteredProfiles.Add(oProfile) - oProfile.IsMatched = True - Dim oNode As New TreeNode($"Profile: {oProfile.Name}") - oNode.ImageIndex = 0 - Dim f = New Font("Tahoma", 9, FontStyle.Bold) - oNode.NodeFont = f - _TreeView.Nodes.Add(oNode) - Dim oSubnode As New TreeNode($"MATCH on Global Clipboard Regex: {oProfile.Regex}") - oSubnode.ImageIndex = 1 - oSubnode.Tag = oProfile.Name & "-REGEX" - oNode.Nodes.Add(oSubnode) - End If - Catch ex As Exception - _Logger.Warn("Regex '{0}' could not be processed for input '{1}'", oProfile.Regex, ClipboardContents) - _Logger.Error(ex) - End Try - Next - - Return oFilteredProfiles - End Function - Public Function FilterProfilesByProcess(Profiles As List(Of ProfileData), CurrentProcessName As String) As List(Of ProfileData) - Dim oFilteredProfiles As New List(Of ProfileData) - Try - For Each oProfile In Profiles - Dim oGuid = oProfile.Guid - - If oProfile.IsMatched = False Then - Continue For - End If - - - Dim oProcesses As New List(Of ProfileData.ProcessData) - For Each oProcessDef As ProfileData.ProcessData In oProfile.Processes - If oProcessDef.ProfileId <> oGuid Then - Continue For - End If - _Logger.Debug($"FilterProfilesByProcess: Checking Profile: {oProfile.Name} ...") - If oProcessDef.ProcessName.ToLower = CurrentProcessName.ToLower Then - _Logger.Debug($"Yes...Processname Matched: {oProcessDef.ProcessName}") - 'oProfile.MATCH_PROCESSNAME = $"Processname Matched: {oProfile.ProcessName}" - 'TODO: Add Debug Data - oFilteredProfiles.Add(oProfile) - oProfile.MatchedProcessID = oProcessDef.Guid - oProcessDef.IsMatched = True - oProcesses.Add(oProcessDef) - oProfile.IsMatched = True - oProfile.MatchedProcessID = oProcessDef.Guid - Dim oParentNode As TreeNode - Dim oExit = False - For Each oTreeNode As TreeNode In _TreeView.Nodes - For Each oNodes As TreeNode In oTreeNode.Nodes - If oExit = True Then Exit For - If oNodes.Tag = oProfile.Name & "-REGEX" Then - oParentNode = oNodes - oExit = True - Exit For - End If - Next - Next - - If Not IsNothing(oParentNode) Then - Dim oNode As New TreeNode($"MATCH on Process: {oProcessDef.ProcessName}") - oNode.ImageIndex = 4 - oNode.Tag = oProfile.Name & "-PROCESS" - oParentNode.Nodes.Add(oNode) - End If - End If - Next - If oFilteredProfiles.Count > 0 Then - oProfile.Processes = oProcesses - End If - Next - - Return oFilteredProfiles - Catch ex As Exception - _Logger.Warn("Unexpected error in FilterProfilesByProcess...") - _Logger.Error(ex) - End Try - - End Function - Public Function FilterWindowsByWindowTitleRegex(Profiles As List(Of ProfileData), WindowTitle As String) As List(Of ProfileData) - Dim oProfiles As New List(Of ProfileData) - - For Each oProfile As ProfileData In Profiles - _Logger.Debug("Checking WindowDefinition for profile: {0}...", oProfile.Name) - If oProfile.IsMatched = False Then Continue For - Dim oWindows As New List(Of ProfileData.WindowData) - - For Each oWindowDef As ProfileData.WindowData In oProfile.Windows - If oWindowDef.WindowProcessID <> oProfile.MatchedProcessID Then Continue For - Try - If oWindowDef.Regex = String.Empty Then - oProfile.MatchedWindowID = oWindowDef.Guid - oWindowDef.IsMatched = True - oWindows.Add(oWindowDef) - Exit For - End If - - Dim oRegex As New Regex(oWindowDef.Regex) - Dim oMatch = oRegex.Match(WindowTitle) - - If oMatch.Success Then - _Logger.Debug("MATCH on WindowTitle: {0}", WindowTitle) - 'TODO: Add Debug Data - oProfile.MatchedWindowID = oWindowDef.Guid - oWindowDef.IsMatched = True - oWindows.Add(oWindowDef) - Dim olowestNode As TreeNode = Node_Get_Lowest_Node(oProfile.Name & "-REGEX") - If Not IsNothing(olowestNode) Then - Dim oNode As New TreeNode($"MATCH on WindowTitle: [{WindowTitle}]") - oNode.ImageIndex = 3 - oNode.Tag = oProfile.Name & "-WINDOW" - olowestNode.Nodes.Add(oNode) - End If - Exit For - End If - Catch ex As Exception - _Logger.Warn("Regex '{0}' could not be processed for input '{1}'", oWindowDef.Regex, WindowTitle) - _Logger.Error(ex) - End Try - Next - - If oWindows.Count > 0 Then - oProfile.Windows = oWindows - oProfile.IsMatched = True - oProfiles.Add(oProfile) - End If - Next - - Return oProfiles - End Function - Public Function FilterWindowsByWindowClipboardRegex(Profiles As List(Of ProfileData), ClipboardContents As String) As List(Of ProfileData) - Dim oProfiles As New List(Of ProfileData) - - For Each oProfile As ProfileData In Profiles - _Logger.Debug("Current Profile: {0}", oProfile.Name) - - Dim oWindows As New List(Of ProfileData.WindowData) - - For Each w As ProfileData.WindowData In oProfile.Windows - Try - If w.Regex = String.Empty Then - oWindows.Add(w) - End If - - Dim oRegex As New Regex(w.Regex) - Dim oMatch = oRegex.Match(ClipboardContents) - - If oMatch.Success Then - _Logger.Debug("Window Clipboard Regex Matched: {0}", ClipboardContents) - Dim oResult As TreeNode - For Each oTreeNode In _TreeView.Nodes - If Not IsNothing(oResult) Then Exit For - If oTreeNode.Tag = oProfile.Name & "-REGEX" Then - oResult = oTreeNode - End If - - - Next - If Not IsNothing(oResult) Then - Dim oNode As New TreeNode($"MATCH on WINDOW Clipboard Regex: [{w.Regex}]") - oNode.ImageIndex = 2 - oNode.Tag = oProfile.Name & "-WINDOW_REGEX" - Dim olowestNode As TreeNode = GetLowestNode(oResult) - olowestNode.Nodes.Add(oNode) - End If - - oWindows.Add(w) - - - End If - Catch ex As Exception - _Logger.Warn("Regex '{0}' could not be processed for input '{1}'", w.Regex, ClipboardContents) - _Logger.Error(ex) - End Try - Next - - If oWindows.Count > 0 Then - oProfile.Windows = oWindows - oProfiles.Add(oProfile) - End If - Next - - Return oProfiles - End Function - - Public Function FilterProfilesByFocusedControl(Profiles As List(Of ProfileData), ClipboardContents As String, ControlFocusresult As String) As List(Of ProfileData) - Dim oWindow As Window.WindowInfo - Dim oFocusedControl As Window.WindowInfo - Dim oFocusedControlName As String = String.Empty - - Try - oWindow = _Window.GetWindowInfo() - oFocusedControl = _Window.GetFocusedControl(oWindow.hWnd) - - If oFocusedControl Is Nothing Then - _Logger.Info("Could not get FocusedControl in Window (Old method) {0}", oWindow.WindowTitle) - oFocusedControlName = String.Empty - Else - oFocusedControlName = oFocusedControl.ControlName - End If - Catch ex As Exception - _Logger.Warn("Error while getting Focused control (Old method)") - _Logger.Error(ex) - oFocusedControlName = String.Empty - End Try - - Dim oFilteredProfiles As New List(Of ProfileData) - - For Each oProfileMatchedSofar In Profiles - If oProfileMatchedSofar.IsMatched = False Then Continue For - - _Logger.Debug("Checking ControlDefiniotion on profile: {0}", oProfileMatchedSofar.Name) - If oProfileMatchedSofar.Controls.Count = 0 Then - oFilteredProfiles.Add(oProfileMatchedSofar) - - Dim oNode As New TreeNode($"No Controls configured!") - oNode.ImageIndex = 2 - oNode.ForeColor = Color.Blue - oNode.Tag = oProfileMatchedSofar.Name & "-NOCONTROLCONFIG" - Dim f = New Font("Tahoma", 10, FontStyle.Bold) - oNode.NodeFont = f - _TreeView.Nodes.Add(oNode) - Continue For - End If - - Dim oControls As New List(Of ProfileData.ControlData) - - For Each oControlDefinition In oProfileMatchedSofar.Controls - Try - If oControlDefinition.WindowId <> oProfileMatchedSofar.MatchedWindowID Then Continue For - _Logger.Debug($"Working on ControlDefinition: {oControlDefinition.Guid}-{oControlDefinition.ControlName}...") - If oControlDefinition.Regex = String.Empty Then - oProfileMatchedSofar.MatchedControlID = oControlDefinition.Guid - oControlDefinition.IsMatched = True - oControls.Add(oControlDefinition) - Exit For - End If - 'Dim oResult As TreeNode - 'For Each oTreeNode In CurrMatchTreeView.Nodes - ' oResult = NodeFind(oTreeNode, $"Global Clipboard Regex Matched [{oProfile.Regex}]") - 'Next - 'Dim oNode As TreeNode - Dim oNodeCaption As String - 'Dim oAddNode As Boolean = False - Dim oRegex As New Regex(oControlDefinition.Regex) - - Dim oFocusedControlResult As String = "" - - If oControlDefinition.AutomationId <> String.Empty And oControlDefinition.ControlName = String.Empty Then - _Logger.Debug($"AutomationID should be used...") - If Not IsNothing(ControlFocusresult) Then - If ControlFocusresult <> String.Empty Then - _Logger.Debug($"AutomationID will be used...") - oFocusedControlResult = ControlFocusresult - End If - End If - ElseIf oControlDefinition.AutomationId = String.Empty And oControlDefinition.ControlName <> String.Empty Then - _Logger.Debug($"ControlName should be used...") - If Not IsNothing(oFocusedControlName) Then - If oFocusedControlName <> String.Empty Then - _Logger.Debug($"ControlName will be used...") - oFocusedControlResult = oFocusedControlName - End If - End If - - End If - If oFocusedControlResult <> String.Empty Then - Dim oControlRegex As New Regex(oControlDefinition.Regex) - Dim oControlMatch = oRegex.Match(oFocusedControlResult) - - If oControlMatch.Success Then - _Logger.Debug($"MATCH on Focused Control [{oFocusedControlResult}] with Regex [{oControlDefinition.Regex}]") - oProfileMatchedSofar.IsMatched = True - oProfileMatchedSofar.MatchedControlID = oControlDefinition.Guid - oControlDefinition.IsMatched = True - oControls.Add(oControlDefinition) - Dim olowestNode As TreeNode = Node_Get_Lowest_Node(oProfileMatchedSofar.Name & "-REGEX") - If Not IsNothing(olowestNode) Then - Dim oNode As New TreeNode($"MATCH on Focused Control [{oFocusedControlResult}] with Regex [{oControlDefinition.Regex}]") - oNode.ImageIndex = 2 - oNode.Tag = oProfileMatchedSofar.Name & "-CONTROL" - olowestNode.Nodes.Add(oNode) - End If - Exit For - End If - End If - Catch ex As Exception - _Logger.Warn("Regex '{0}' could not be processed for input '{1}'", oControlDefinition.Regex, oFocusedControlName) - _Logger.Error(ex) - End Try - Next - - If oControls.Count > 0 Then - oProfileMatchedSofar.Controls = oControls - oFilteredProfiles.Add(oProfileMatchedSofar) - Else - Dim olowestNode As TreeNode = Node_Get_Lowest_Node(oProfileMatchedSofar.Name & "-REGEX") - If Not IsNothing(olowestNode) Then - Dim oNode As New TreeNode($"NO MATCHES on Focused Control, Please check the Config") - oNode.ImageIndex = 2 - oNode.Tag = oProfileMatchedSofar.Name & "-CONTROLNoMatch" - olowestNode.Nodes.Add(oNode) - End If - End If - Next - - Return oFilteredProfiles - End Function - Public Function FilterProfilesBySearchResults(Profiles As List(Of ProfileData)) As List(Of ProfileData) - Dim oProfiles As New List(Of ProfileData) - - For Each oProfile In Profiles - Dim oResultDocs As Integer = 0 - Dim oResultData As Integer = 0 - - Dim oPatterns As New ClassPatterns(My.LogConfig) - Dim oDataSearches As DataTable = My.Database.GetDatatable($"SELECT COUNT_COMMAND FROM TBCW_PROF_DATA_SEARCH WHERE ACTIVE = 1 AND PROFILE_ID = {oProfile.Guid}") - Dim oDocSearches As DataTable = My.Database.GetDatatable($"SELECT COUNT_COMMAND FROM TBCW_PROF_DOC_SEARCH WHERE ACTIVE = 1 AND PROFILE_ID = {oProfile.Guid}") - - For Each oRow As DataRow In oDataSearches.Rows - Dim oCountCommand = String.Empty - Try - oCountCommand = NotNull(oRow.Item("COUNT_COMMAND"), String.Empty) - - If oCountCommand = String.Empty Then - Continue For - End If - - oCountCommand = oPatterns.ReplaceAllValues(oCountCommand, My.Application.User) - oResultData += NotNull(Of Integer)(My.Database.GetScalarValue(oCountCommand), 0) - Catch ex As Exception - _Logger.Warn("Invalid SQL Query for Counting Data in Profile {0}: {1}", oProfile.Guid, oCountCommand) - End Try - Next - - For Each oRow As DataRow In oDocSearches.Rows - Dim oCountCommand = String.Empty - Try - oCountCommand = NotNull(oRow.Item("COUNT_COMMAND"), String.Empty) - - If oCountCommand = String.Empty Then - Continue For - End If - - oCountCommand = oPatterns.ReplaceAllValues(oCountCommand, My.Application.User) - oResultDocs += NotNull(Of Integer)(My.Database.GetScalarValue(oCountCommand), 0) - Catch ex As Exception - _Logger.Warn("Invalid SQL Query for Counting Data in Profile {0}: {1}", oProfile.Guid, oCountCommand) - End Try - Next - - If oResultData > 0 Or oResultDocs > 0 Then - oProfile.CountData = oResultData - oProfile.CountDocs = oResultDocs - oProfiles.Add(oProfile) - End If - Next - - Return oProfiles - End Function - - Private Function Node_Get_Lowest_Node(NodeTag As String) As TreeNode - Dim oExit = False - Dim oParentNode As TreeNode - For Each oTreeNode As TreeNode In _TreeView.Nodes - For Each oNodes As TreeNode In oTreeNode.Nodes - If oExit = True Then Exit For - If oNodes.Tag = NodeTag Then - oParentNode = oNodes - oExit = True - Exit For - End If - Next - Next - Dim olowestNode As TreeNode = GetLowestNode(oParentNode) - - Return olowestNode - End Function - Public Function ClearNotMatchedProfiles(Profiles As List(Of ProfileData)) As List(Of ProfileData) - Dim oFilteredProfiles As New List(Of ProfileData) - For Each oProfile In Profiles - If oProfile.IsMatched Then - oFilteredProfiles.Add(oProfile) - End If - Next - Return oFilteredProfiles - End Function - Private Function TransformProfiles() As List(Of ProfileData) - Dim oList As New List(Of ProfileData) - - For Each oRow As DataRow In _ProfileTable.Rows - Dim oProfileId = oRow.Item("GUID") - Dim oProcessList As List(Of ProfileData.ProcessData) = TransformProcesses(oProfileId, _ProcessTable) - Dim oWindowList As List(Of ProfileData.WindowData) = TransformWindows(oProfileId, _WindowTable) - Dim oControlList As List(Of ProfileData.ControlData) = TransformControls(oProfileId, _ControlTable) - - oList.Add(New ProfileData() With { - .Guid = oRow.Item("GUID"), - .Regex = NotNull(oRow.Item("REGEX_EXPRESSION"), String.Empty), - .Name = NotNull(oRow.Item("NAME"), String.Empty), - .Comment = NotNull(oRow.Item("COMMENT"), String.Empty), - .ProfileType = NotNull(oRow.Item("PROFILE_TYPE"), String.Empty), - .Processes = oProcessList, - .Windows = oWindowList, - .Controls = oControlList - }) - Next - - Return oList - End Function - Private Function TransformControls(ProfileId As Integer, ControlDatatable As DataTable) As List(Of ProfileData.ControlData) - Dim oControlList As New List(Of ProfileData.ControlData) - - For Each oRow As DataRow In ControlDatatable.Rows - If oRow.Item("PROFILE_ID") = ProfileId Then - oControlList.Add(New ProfileData.ControlData() With { - .Guid = oRow.Item("GUID"), - .Description = NotNull(oRow.Item("DESCRIPTION"), String.Empty), - .Regex = NotNull(oRow.Item("REGEX"), String.Empty), - .AutomationId = NotNull(oRow.Item("AUTOMATION_ID"), String.Empty), - .WindowId = oRow.Item("WINDOW_ID") - }) - End If - Next - - Return oControlList - End Function - Private Function TransformProcesses(ProfileId As Integer, ProcessDatatable As DataTable) As List(Of ProfileData.ProcessData) - Dim oProcessList As New List(Of ProfileData.ProcessData) - - For Each oRow As DataRow In ProcessDatatable.Rows - oProcessList.Add(New ProfileData.ProcessData() With { - .Guid = oRow.Item("GUID"), - .ProfileId = oRow.Item("PROFILE_ID"), - .ProcessName = NotNull(oRow.Item("PROC_NAME"), String.Empty) - }) - - Next - - Return oProcessList - End Function - Private Function TransformWindows(ProfileId As Integer, WindowDatatable As DataTable) As List(Of ProfileData.WindowData) - Dim oWindowList As New List(Of ProfileData.WindowData) - - For Each oRow As DataRow In WindowDatatable.Rows - oWindowList.Add(New ProfileData.WindowData() With { - .Guid = oRow.Item("GUID"), - .WindowProcessID = oRow.Item("PROCESS_ID"), - .Title = NotNull(oRow.Item("DESCRIPTION"), String.Empty), - .Regex = NotNull(oRow.Item("REGEX"), String.Empty), - .Sequence = NotNull(oRow.Item("SEQUENCE"), 0) - }) - Next - - Return oWindowList - End Function - - -End Class diff --git a/GUIs.ZooFlow/Queries/ClassClipboardWatcherQueries.vb b/GUIs.ZooFlow/Queries/ClassClipboardWatcherQueries.vb index 3077888a..530df86b 100644 --- a/GUIs.ZooFlow/Queries/ClassClipboardWatcherQueries.vb +++ b/GUIs.ZooFlow/Queries/ClassClipboardWatcherQueries.vb @@ -1,10 +1,26 @@ Public Class ClassClipboardWatcherQueries + Private Function ProfileWhereClause(UserId As Integer) As String + Return $"T1.USER_ID = {UserId} OR GROUP_ID IN (SELECT DISTINCT GUID FROM TBDD_GROUPS WHERE GUID IN (SELECT GROUP_ID FROM TBDD_GROUPS_USER WHERE USER_ID = {UserId}))" + End Function + Public Function VWCW_USER_PROFILE(UserId As Integer) As String - Return $"SELECT DISTINCT GUID, NAME, REGEX_EXPRESSION, COMMENT, PROC_NAME, PROFILE_TYPE FROM VWCW_USER_PROFILE WHERE USER_ID = {UserId} OR GROUP_ID IN (SELECT DISTINCT GUID FROM TBDD_GROUPS WHERE GUID IN (SELECT GROUP_ID FROM TBDD_GROUPS_USER WHERE USER_ID = {UserId}))" + Dim oWhereClause = ProfileWhereClause(UserId) + Return $"SELECT DISTINCT GUID, NAME,REGEX_EXPRESSION,COMMENT,PROC_NAME,PROFILE_TYPE FROM VWCW_USER_PROFILE T1 WHERE {oWhereClause}" + End Function + + Public Function VWCW_PROFILE_REL_WINDOW(UserId As Integer) As String + Dim oWhereClause = ProfileWhereClause(UserId) + Return $"SELECT DISTINCT T.* FROM VWCW_PROFILE_REL_WINDOW T, VWCW_USER_PROFILE T1 WHERE T.PROFILE_ID = T1.GUID AND ({oWhereClause})" + End Function + + Public Function VWCW_PROFILE_REL_CONTROL(UserId As Integer) As String + Dim oWhereClause = ProfileWhereClause(UserId) + Return $"SELECT DISTINCT T.* FROM VWCW_PROFILE_REL_CONTROL T, VWCW_USER_PROFILE T1 WHERE T.PROFILE_ID = T1.GUID AND ({oWhereClause})" End Function Public Function TBCW_PROFILE_PROCESS(UserId As Integer) As String - Return $"SELECT T.* FROM TBCW_PROFILE_PROCESS T, VWCW_USER_PROFILE T1 WHERE T.PROFILE_ID = T1.GUID AND T1.USER_ID = {UserId}" + Dim oWhereClause = ProfileWhereClause(UserId) + Return $"SELECT DISTINCT T.GUID, T.PROFILE_ID,T.PROC_NAME FROM TBCW_PROFILE_PROCESS T, VWCW_USER_PROFILE T1 WHERE T.PROFILE_ID = T1.GUID AND ({oWhereClause})" End Function Public Function TBCW_PROF_DATA_SEARCH(ProfileId As Integer) As String @@ -15,11 +31,4 @@ Return $"SELECT COUNT_COMMAND FROM TBCW_PROF_DOC_SEARCH WHERE ACTIVE = 1 AND PROFILE_ID = {ProfileId}" End Function - Public Function VWCW_PROFILE_REL_WINDOW(UserId As Integer) As String - Return $"SELECT * FROM VWCW_PROFILE_REL_WINDOW WHERE USER_ID = {UserId}" - End Function - - Public Function VWCW_PROFILE_REL_CONTROL(UserId As Integer) As String - Return $"SELECT * FROM VWCW_PROFILE_REL_CONTROL WHERE USER_ID = {UserId}" - End Function End Class