426 lines
19 KiB
VB.net
426 lines
19 KiB
VB.net
Imports System.ComponentModel
|
|
Imports System.Globalization
|
|
Imports DLLLicenseManager
|
|
Imports DigitalData.Modules.Logging
|
|
Imports DigitalData.Modules.Config
|
|
Imports System.Threading
|
|
Imports DigitalData.Modules.EDMI.API
|
|
Imports DigitalData.Modules.EDMI.API.EDMIServiceReference
|
|
|
|
Public Class ClassInit
|
|
Public _lizenzManager As ClassLicenseManager
|
|
Private DataASorDB As ClassDataASorDB
|
|
Public Sub New()
|
|
End Sub
|
|
|
|
<STAThread()>
|
|
Public Sub InitLogger()
|
|
LOGCONFIG = New LogConfig(LogConfig.PathType.CustomPath,
|
|
Application.LocalUserAppDataPath & "\Log",
|
|
Nothing,
|
|
My.Application.Info.CompanyName,
|
|
My.Application.Info.ProductName)
|
|
LOGGER = LOGCONFIG.GetLogger("ProcessManager")
|
|
|
|
LOGGER.Info("## ProcessManager started - {0}", Now)
|
|
Try
|
|
Dim directory As New IO.DirectoryInfo(Application.LocalUserAppDataPath & "\Log")
|
|
|
|
For Each file As IO.FileInfo In directory.GetFiles
|
|
If (Now - file.CreationTime).Days > 29 Then
|
|
file.Delete()
|
|
Else
|
|
Exit For
|
|
End If
|
|
|
|
|
|
Next
|
|
Catch ex As Exception
|
|
|
|
End Try
|
|
End Sub
|
|
|
|
<STAThread()>
|
|
Public Sub InitUserConfig()
|
|
Try
|
|
DataASorDB = New ClassDataASorDB
|
|
Dim oUserAppDataPath As String = Application.UserAppDataPath
|
|
Dim oLegacyAppDataPath As String = Application.UserAppDataPath
|
|
Dim oCommonAppDataPath = Application.CommonAppDataPath
|
|
Dim oStartupPath = Application.StartupPath
|
|
Dim oConfigPrefix As String = My.Settings.UserConfig_Prefix
|
|
|
|
' If prefix is configured, use it to create a subfolder in app data and migrate existing data
|
|
If oConfigPrefix.Length > 0 Then
|
|
oUserAppDataPath = IO.Path.Combine(Application.UserAppDataPath, oConfigPrefix)
|
|
|
|
Dim oConfigUtils As New ConfigUtils(LOGCONFIG)
|
|
|
|
If oConfigUtils.TestMigrationNeeded(oUserAppDataPath) Then
|
|
LOGCONFIG.Debug = True
|
|
oConfigUtils.MigrateConfig(oLegacyAppDataPath, oUserAppDataPath)
|
|
LOGCONFIG.Debug = False
|
|
End If
|
|
End If
|
|
|
|
' If AppConfig from Startup Path should be forced, rewrite the common app data path
|
|
If My.Settings.UseAppConfigConString = True Then
|
|
' UserAppDataPath = StartupPath
|
|
oCommonAppDataPath = oStartupPath
|
|
End If
|
|
|
|
CONFIG = New ConfigManager(Of ClassConfig)(LOGCONFIG, oUserAppDataPath, oCommonAppDataPath, oStartupPath)
|
|
LOGGER.Info("Config loaded")
|
|
|
|
If CONFIG.Config.ConnectionStringTest <> String.Empty And CONFIG.Config.TestMode = True Then
|
|
LOGGER.Debug("Test Connection String loaded")
|
|
CONNECTION_STRING = DecryptConnectionString(CONFIG.Config.ConnectionStringTest)
|
|
Else
|
|
LOGGER.Debug("Connection String loaded")
|
|
CONNECTION_STRING = DecryptConnectionString(CONFIG.Config.ConnectionString)
|
|
End If
|
|
|
|
If CONFIG.Config.ConnectionStringAppServer <> String.Empty Then
|
|
LOGGER.Debug("ConnectionStringAppServer will be used")
|
|
CONNECTION_STRING_APP_SERVER = DecryptConnectionString(CONFIG.Config.ConnectionStringAppServer)
|
|
CONNECTION_STRING_READ = CONNECTION_STRING_APP_SERVER
|
|
Else
|
|
CONNECTION_STRING_READ = CONNECTION_STRING
|
|
End If
|
|
|
|
If CONFIG.Config.EDMIAppServer <> String.Empty Then
|
|
|
|
|
|
Try
|
|
Dim oSplit() = CONFIG.Config.EDMIAppServer.ToString.Split(";")
|
|
Dim oAppServer = oSplit(0)
|
|
Dim oAppServerPort = 9000
|
|
If oSplit.Length = 2 Then
|
|
oAppServerPort = oSplit(1)
|
|
End If
|
|
_Client = New Client(LOGCONFIG, oAppServer, oAppServerPort)
|
|
If Not IsNothing(_Client) Then
|
|
If _Client.Connect() Then
|
|
EDMIAppServerActive = True
|
|
LOGGER.Info($"EDMIAppServer [{oAppServer}] is active!")
|
|
End If
|
|
End If
|
|
Catch ex As Exception
|
|
LOGGER.Warn($"Could not initialize the AppServer: {ex.Message}")
|
|
End Try
|
|
|
|
End If
|
|
|
|
INDEX_DMS_ERSTELLT = CONFIG.Config.IndexDmsErstellt
|
|
INDEX_DMS_ERSTELLT_ZEIT = CONFIG.Config.IndexDmsErstelltZeit
|
|
|
|
USER_MANAGER_PATH = CONFIG.Config.UserManagerPath
|
|
|
|
LOG_ERRORS_ONLY = CONFIG.Config.LogErrorsOnly
|
|
LOGCONFIG.Debug = Not LOG_ERRORS_ONLY
|
|
TEST_MODE = CONFIG.Config.TestMode
|
|
Catch ex As Exception
|
|
LOGGER.Error(ex)
|
|
End Try
|
|
|
|
|
|
'Settings_Load()
|
|
End Sub
|
|
|
|
Private Function DecryptConnectionString(EncryptedConnectionString As String) As String
|
|
Dim oBuilder As New SqlClient.SqlConnectionStringBuilder With {
|
|
.ConnectionString = EncryptedConnectionString
|
|
}
|
|
|
|
If oBuilder.ConnectionString.Contains("Password=") Then
|
|
Dim oPlaintextPassword As String
|
|
Dim oDecryptor As New ClassEncryption("!35452didalog=")
|
|
|
|
Try
|
|
oPlaintextPassword = oDecryptor.DecryptData(oBuilder.Password)
|
|
Catch ex As Exception
|
|
LOGGER.Error(ex)
|
|
LOGGER.Debug("Password {0} could not be decrypted. Assuming plaintext password.")
|
|
oPlaintextPassword = oBuilder.Password
|
|
End Try
|
|
Return EncryptedConnectionString.Replace(oBuilder.Password, oPlaintextPassword)
|
|
Else
|
|
Return EncryptedConnectionString
|
|
End If
|
|
End Function
|
|
|
|
<STAThread()>
|
|
Public Function InitDatabase()
|
|
Dim dbResult As Boolean
|
|
|
|
If CONNECTION_STRING <> String.Empty Then
|
|
dbResult = ClassDatabase.Init()
|
|
Else
|
|
MsgBox("No Databaseconnection configured. (First Start or Appdata not accessible)" & vbNewLine & "Basic-Config will be loaded.", MsgBoxStyle.Information)
|
|
ERROR_STATE = "NO DB-CONNECTION"
|
|
frmKonfig.ShowDialog()
|
|
dbResult = ClassDatabase.Init()
|
|
End If
|
|
If CONNECTION_STRING_APP_SERVER <> String.Empty Then
|
|
If ClassDatabase.Init(CONNECTION_STRING_APP_SERVER) = False Then
|
|
MsgBox("ApplicationServer can not be reached! Check Your configuration.", MsgBoxStyle.Information)
|
|
If dbResult = True Then
|
|
CONNECTION_STRING_READ = CONNECTION_STRING
|
|
End If
|
|
End If
|
|
End If
|
|
|
|
|
|
|
|
If dbResult = False Then
|
|
ERROR_STATE = "FAILED DBCONNECTION"
|
|
MsgBox("Error in init database. (Connection failed) More information in the logfile.", MsgBoxStyle.Critical)
|
|
Return False
|
|
Else
|
|
Return True
|
|
End If
|
|
End Function
|
|
|
|
<STAThread()>
|
|
Sub Refresh_Licence()
|
|
Dim oStopWatch As New RefreshHelper.SW("Refresh_Licence")
|
|
Try
|
|
Me._lizenzManager = New ClassLicenseManager("#DigitalData35452!#", "")
|
|
Dim lic As String = BASEDATA_DT_CONFIG.Rows(0).Item("LIZENZEN")
|
|
Dim licString = Me._lizenzManager.DecodeLicenseKey(lic)
|
|
Dim split() = licString.ToString.Split("#")
|
|
|
|
If lic <> "" Then
|
|
LICENSE_COUNT = split(0)
|
|
Else
|
|
LICENSE_COUNT = 0
|
|
End If
|
|
|
|
If LICENSE_VALID = False Then
|
|
MsgBox("Your license has expired!" & vbNewLine & "Last valid date: " & split(1) & vbNewLine & "Please contact Your sysadmin", MsgBoxStyle.Exclamation)
|
|
LICENSE_EXPIRED = True
|
|
LICENSE_COUNT = 0
|
|
End If
|
|
LOGGER.Debug("license initialized....")
|
|
|
|
LICENSE_PROFILES = split(2)
|
|
Catch ex As Exception
|
|
LOGGER.Error(ex)
|
|
LOGGER.Info("Unexpected error in Refresh license: " & ex.Message, True)
|
|
MsgBox(ex.Message, MsgBoxStyle.Exclamation, "Fehler bei Licensemanager:")
|
|
End Try
|
|
oStopWatch.Done()
|
|
End Sub
|
|
<STAThread()>
|
|
Public Sub InitUserLogin(Optional pUSRNAME As String = "")
|
|
Dim oStopWatch As New RefreshHelper.SW("InitUserLogin")
|
|
Dim oSQL As String
|
|
Try
|
|
If pUSRNAME <> String.Empty Then
|
|
USER_USERNAME = pUSRNAME
|
|
Else
|
|
USER_USERNAME = Environment.UserName
|
|
End If
|
|
|
|
Try
|
|
Dim oSQLSW As New RefreshHelper.SW("VWDD_USER_CLIENT")
|
|
oSQL = $"SELECT * FROM VWDD_USER_CLIENT WHERE UPPER(USERNAME) = UPPER('{USER_USERNAME}')"
|
|
|
|
DT_CLIENT_USER = DataASorDB.GetDatatable("DD_ECM", oSQL, "VWDD_USER_CLIENT", $"USERNAME like '{USER_USERNAME}'")
|
|
oSQLSW.Done()
|
|
|
|
If DT_CLIENT_USER.Rows.Count > 1 Then
|
|
frmClientLogin.ShowDialog()
|
|
ElseIf DT_CLIENT_USER.Rows.Count = 1 Then
|
|
CLIENT_SELECTED = DT_CLIENT_USER.Rows(0).Item("CLIENT_ID")
|
|
Else
|
|
ERROR_STATE = "NO CLIENT"
|
|
Dim oDT As DataTable = ClassAllgemeineFunktionen.GUI_LANGUAGE_INFO("No Client relation")
|
|
MsgBox(oDT.Rows(0).Item("STRING1") & vbNewLine & oDT.Rows(0).Item("STRING2") & vbNewLine & vbNewLine & oSQL, MsgBoxStyle.Exclamation)
|
|
Exit Sub
|
|
End If
|
|
Catch ex As Exception
|
|
LOGGER.Error(ex)
|
|
LOGGER.Info("Unexpected error in checking CLIENT: " & ex.Message)
|
|
CLIENT_SELECTED = 1
|
|
End Try
|
|
|
|
LOGGER.Debug("Username: " & USER_USERNAME)
|
|
Dim oFnct As New RefreshHelper.SW("FNDD_CHECK_USER_MODULE")
|
|
oSQL = String.Format("SELECT * FROM [dbo].[FNDD_CHECK_USER_MODULE] ('{0}','PM',{1})", USER_USERNAME, CLIENT_SELECTED)
|
|
Dim DT_CHECKUSER_MODULE As DataTable
|
|
DT_CHECKUSER_MODULE = DataASorDB.GetDatatable("DD_ECM", oSQL, "TBDD_USER_MODULE", $"USERNAME = '{USER_USERNAME.ToLower}' AND MODULE_SHORT = 'PM'")
|
|
oFnct.Done()
|
|
If DT_CHECKUSER_MODULE.Rows.Count = 0 Then
|
|
LOGGER.Info("DT_CHECKUSER_MODULE.Rows.Count = 0", True)
|
|
ERROR_STATE = "NO USER"
|
|
MsgBox("Sorry - Something went wrong in getting Your rights." & vbNewLine & "Please contact the system administrator!", MsgBoxStyle.Exclamation)
|
|
Exit Sub
|
|
End If
|
|
|
|
|
|
If DT_CHECKUSER_MODULE.Rows.Count = 1 Then
|
|
If DT_CHECKUSER_MODULE.Rows(0).Item("USER_ID") <> 0 Then
|
|
USER_EXISTS = True
|
|
Else
|
|
USER_EXISTS = False
|
|
End If
|
|
|
|
USER_ID = DT_CHECKUSER_MODULE.Rows(0).Item("USER_ID")
|
|
USER_SURNAME = IIf(IsDBNull(DT_CHECKUSER_MODULE.Rows(0).Item("USER_SURNAME")), "", DT_CHECKUSER_MODULE.Rows(0).Item("USER_SURNAME"))
|
|
USER_PRENAME = IIf(IsDBNull(DT_CHECKUSER_MODULE.Rows(0).Item("USER_PRENAME")), "", DT_CHECKUSER_MODULE.Rows(0).Item("USER_PRENAME"))
|
|
USER_SHORTNAME = IIf(IsDBNull(DT_CHECKUSER_MODULE.Rows(0).Item("USER_SHORTNAME")), "", DT_CHECKUSER_MODULE.Rows(0).Item("USER_SHORTNAME"))
|
|
USER_EMAIL = IIf(IsDBNull(DT_CHECKUSER_MODULE.Rows(0).Item("USER_EMAIL")), "", DT_CHECKUSER_MODULE.Rows(0).Item("USER_EMAIL"))
|
|
USER_LANGUAGE = DT_CHECKUSER_MODULE.Rows(0).Item("USER_LANGUAGE")
|
|
|
|
USER_IN_MODULE = DT_CHECKUSER_MODULE.Rows(0).Item("MODULE_ACCESS")
|
|
USER_IS_ADMIN = DT_CHECKUSER_MODULE.Rows(0).Item("IS_ADMIN")
|
|
USER_RIGHT_FILE_DELETE = IIf(IsDBNull(DT_CHECKUSER_MODULE.Rows(0).Item("USER_RIGHT_FILE_DEL")), False, DT_CHECKUSER_MODULE.Rows(0).Item("USER_RIGHT_FILE_DEL"))
|
|
USER_DATE_FORMAT = DT_CHECKUSER_MODULE.Rows(0).Item("USER_DATE_FORMAT")
|
|
USERCOUNT_LOGGED_IN = DT_CHECKUSER_MODULE.Rows(0).Item("USERCOUNT_LOGGED_IN")
|
|
|
|
ClassParamRefresh.Refresh_Params(DT_CHECKUSER_MODULE)
|
|
FINALINDICES = New ClassFinalIndex()
|
|
FINALINDICES.init()
|
|
If IDB_ACTIVE = True Then
|
|
IDBData = New ClassIDBData()
|
|
End If
|
|
|
|
Try
|
|
USER_RIGHT_VIEW_ONLY = DT_CHECKUSER_MODULE.Rows(0).Item("USER_RIGHT2")
|
|
Catch ex As Exception
|
|
USER_RIGHT_VIEW_ONLY = False
|
|
End Try
|
|
Try
|
|
USER_RIGHT3 = DT_CHECKUSER_MODULE.Rows(0).Item("USER_RIGHT3")
|
|
Catch ex As Exception
|
|
USER_RIGHT3 = False
|
|
End Try
|
|
Try
|
|
USER_RIGHT4 = DT_CHECKUSER_MODULE.Rows(0).Item("USER_RIGHT4")
|
|
Catch ex As Exception
|
|
USER_RIGHT4 = False
|
|
End Try
|
|
LOGGER.Debug("User exists....")
|
|
'Am System anmelden
|
|
Refresh_Licence()
|
|
'Check_User_Exists_in_PMGroups()
|
|
'Dim Culture = CultureInfo.CreateSpecificCulture("en-US")
|
|
'' The following line provides localization for the application's user interface.
|
|
'Thread.CurrentThread.CurrentUICulture = Culture
|
|
'' The following line provides localization for data formats.
|
|
'Thread.CurrentThread.CurrentCulture = Culture
|
|
'' Set this culture as the default culture for all threads in this application.
|
|
'' Note: The following properties are supported in the .NET Framework 4.5+
|
|
'CultureInfo.DefaultThreadCurrentCulture = Culture
|
|
'CultureInfo.DefaultThreadCurrentUICulture = Culture
|
|
|
|
|
|
If ClassAllgemeineFunktionen.LoginOut("LOGIN") = True Then
|
|
USERCOUNT_LOGGED_IN += 1
|
|
End If
|
|
LOGGER.Debug("Count Users logged in: " & USERCOUNT_LOGGED_IN.ToString)
|
|
If LICENSE_COUNT < USERCOUNT_LOGGED_IN And LICENSE_EXPIRED = False Then
|
|
MsgBox("Die Anzahl der aktuell angemeldeten User (" & USERCOUNT_LOGGED_IN.ToString & ") überschreitet die Anzahl der aktuellen Lizenzen!" & vbNewLine & "Anzahl der Lizenzen: " & LICENSE_COUNT.ToString & vbNewLine & "Bitte setzen Sie sich mit dem Systembetreuer in Verbindung!", MsgBoxStyle.Critical, "Achtung:")
|
|
LOGGER.Info("Die Anzahl der aktuell angemeldeten User (" & USERCOUNT_LOGGED_IN.ToString & ") überschreitet die Anzahl der Lizenzen (" & LICENSE_COUNT & ") für Process Manager!")
|
|
If USER_IS_ADMIN = False Then
|
|
ClassAllgemeineFunktionen.LoginOut("LOGOUT")
|
|
ERROR_STATE = "START INCOMPLETE"
|
|
End If
|
|
End If
|
|
'Alles OK bis hierhin...nun die FolderwatchKonfig laden
|
|
LOGGER.Debug("Init Userlogin successfull completed....")
|
|
End If
|
|
Catch ex As Exception
|
|
LOGGER.Error(ex)
|
|
LOGGER.Info("Unexpected Error in InitUserLogin: " & ex.Message, True)
|
|
ERROR_STATE = "START INCOMPLETE"
|
|
End Try
|
|
oStopWatch.Done()
|
|
End Sub
|
|
<STAThread()>
|
|
Public Sub InitBasics()
|
|
Try
|
|
Dim oStopWatch As New RefreshHelper.SW("InitBasics")
|
|
Dim oSql = String.Format("select * from TBPM_KONFIGURATION WHERE GUID = 1")
|
|
BASEDATA_DT_CONFIG = DataASorDB.GetDatatable("DD_ECM", oSql, "TBPM_KONFIGURATION", $"GUID = 1")
|
|
|
|
Settings_LoadBasicConfig()
|
|
|
|
oSql = "select * from TBDD_CONNECTION WHERE AKTIV = 1"
|
|
BASEDATA_DT_TBDD_CONNECTION = DataASorDB.GetDatatable("DD_ECM", oSql, "TBDD_CONNECTION", "")
|
|
|
|
oSql = "Select * FROM TBDD_3RD_PARTY_MODULES WHERE ACTIVE = 1"
|
|
Dim oTBDD_3RD_PARTY_MODULES As DataTable
|
|
oTBDD_3RD_PARTY_MODULES = DataASorDB.GetDatatable("DD_ECM", oSql, "TBDD_3RD_PARTY_MODULES", "")
|
|
|
|
For Each oROW As DataRow In oTBDD_3RD_PARTY_MODULES.Rows
|
|
If oROW.Item("NAME") = "GDPICTURE" Then
|
|
GDPICTURE_LICENSE = oROW.Item("LICENSE")
|
|
End If
|
|
Next
|
|
oSql = "SELECT * FROM TBDD_GUI_LANGUAGE_PHRASE WHERE MODULE IN ('PM','All Modules')"
|
|
BASEDATA_DT_GUI_LANGUAGE_PHRASES = DataASorDB.GetDatatable("DD_ECM", oSql, "TBDD_GUI_LANGUAGE_PHRASE", "")
|
|
|
|
oSql = "select * from TBPM_PROFILE_SEARCH where TYPE = 'DOC' AND ACTIVE = 1 ORDER BY PROFILE_ID,TAB_INDEX"
|
|
BASEDATA_DT_PROFILES_SEARCHES_DOC = DataASorDB.GetDatatable("DD_ECM", oSql, "TBPM_PROFILE_SEARCH", "TYPE = 'DOC'", "PROFILE_ID,TAB_INDEX")
|
|
BASEDATA_DT_PROFILE_SEARCHES_DOC = BASEDATA_DT_PROFILES_SEARCHES_DOC.Clone()
|
|
|
|
oSql = "SELECT * FROM TBPM_MAIN_VIEW_GROUPS WHERE ACTIVE = 1"
|
|
BASEDATA_DTGRID_GROUPS = DataASorDB.GetDatatable("DD_ECM", oSql, "TBPM_MAIN_VIEW_GROUPS", "")
|
|
BASEDATA_DT_CHARTS = DataASorDB.GetDatatable("DD_ECM", oSql, "TBPM_CHART", "")
|
|
oStopWatch.Done()
|
|
Catch ex As Exception
|
|
LOGGER.Error(ex)
|
|
LOGGER.Info("Unexpected Error in InitBasics: " & ex.Message, True)
|
|
ERROR_STATE = "Basics not initialized"
|
|
End Try
|
|
End Sub
|
|
<STAThread()>
|
|
Public Sub InitBasics2()
|
|
Try
|
|
Dim oStopWatch As New RefreshHelper.SW("InitBasics2")
|
|
Dim oSql = String.Format("SELECT * FROM VWPM_PROFILE_USER WHERE USER_ID = {0}", USER_ID)
|
|
BASEDATA_DT_VW_PROFILE_USER = DataASorDB.GetDatatable("DD_ECM", oSql, "VWPM_PROFILE_USER", $"USER_ID = {USER_ID}")
|
|
|
|
If BASEDATA_DT_VW_PROFILE_USER.Rows.Count = 0 Then
|
|
LOGGER.Warn($"no profiles for user: '{USER_USERNAME}' configured - Check SQL [{oSql}]!", False)
|
|
End If
|
|
|
|
|
|
oStopWatch.Done()
|
|
Catch ex As Exception
|
|
LOGGER.Error(ex)
|
|
LOGGER.Info("Unexpected Error in InitBasics2: " & ex.Message, True)
|
|
ERROR_STATE = "Basics2 not initialized"
|
|
End Try
|
|
End Sub
|
|
<STAThread()>
|
|
Private Function Settings_LoadBasicConfig()
|
|
Try
|
|
Dim oSql As String = "select * from tbdd_Modules where SHORT_NAME = 'PM'"
|
|
Dim oDTtbdd_Modules As DataTable
|
|
oDTtbdd_Modules = DataASorDB.GetDatatable("DD_ECM", oSql, "tbdd_Modules", $" SHORT_NAME = 'PM'")
|
|
If oDTtbdd_Modules.Rows.Count = 1 Then
|
|
Try
|
|
VERSION_DELIMITER = oDTtbdd_Modules.Rows(0).Item("VERSION_DELIMITER")
|
|
FILE_DELIMITER = oDTtbdd_Modules.Rows(0).Item("FILE_DELIMITER")
|
|
LICENSE_VALID = oDTtbdd_Modules.Rows(0).Item("LICENSE_VALID")
|
|
WMSESSION_STARTSTOP_STARTUP = oDTtbdd_Modules.Rows(0).Item("WMSESSION_STARTSTOP_STARTUP")
|
|
Catch ex As Exception
|
|
LOGGER.Error(ex)
|
|
LOGGER.Info("Unexpected Error in Settings_LoadBasicConfig: " & ex.Message, True)
|
|
End Try
|
|
Else
|
|
Return False
|
|
End If
|
|
Catch ex As Exception
|
|
LOGGER.Error(ex)
|
|
MsgBox("Error in Settings_LoadBasicConfig" & vbNewLine & ex.Message, MsgBoxStyle.Critical)
|
|
Return False
|
|
End Try
|
|
Return True
|
|
End Function
|
|
|
|
End Class
|