409 lines
20 KiB
VB.net
409 lines
20 KiB
VB.net
Imports System.Data.SqlClient
|
||
Imports System.IO
|
||
Imports System.Xml
|
||
|
||
Public NotInheritable Class RCVerarbeitung
|
||
|
||
Inherits MarshalByRefObject
|
||
Implements EDKB07Verarbeitung.EDKB07Verarbeitung.IEDKB07
|
||
|
||
|
||
Dim part As Integer = -1
|
||
|
||
Public Sub GetDocBLPDF(ByVal DruckjobID As Integer) Implements EDKB07Verarbeitung.EDKB07Verarbeitung.IEDKB07.GetDocBLPDF
|
||
''RGL 29.1.08 Zusätzlicher Textlog für jeden einzelnen Schritt
|
||
'Globals.LogFileName = CStr(DruckjobID)
|
||
|
||
Dim filetimestamp As String = Format(Now, "yyyyMMddHHmmss")
|
||
' Globals.WriteTxtLog("Start Klasse RCVerarbeitung, Methode GetDocBLPDF, Remotaufruf ist erfolgt, schreibe Journaleintrag Start")
|
||
Dim log As New clsLog
|
||
log.InsertJournale("EDKB07: Start Remotingaufruf " & CType(Now, String) & " DruckjobID: " & DruckjobID, clsLog.Enum_InfoTyp.Keine)
|
||
|
||
'20071002 RGL Workaround
|
||
' Globals.WriteTxtLog("Aufruf Word und Distiller vorbereiten (Workaround)")
|
||
PrepareWordandDistiller()
|
||
|
||
Dim userid As String = ""
|
||
Dim timestamp As String = ""
|
||
Dim erstelltam As Date
|
||
' Globals.WriteTxtLog("Vorbereitung SQL Verbindung")
|
||
Dim SqlConn As New SqlConnection
|
||
SqlConn.ConnectionString = Globals.sConnectionString
|
||
Dim SqlCmd As New SqlCommand
|
||
Dim DR As SqlDataReader
|
||
'Daten zu Druckjob aus DB lesen
|
||
SqlCmd.CommandText = "SP_EDEX_BL_GET_DRUCK_Parameter"
|
||
SqlCmd.CommandType = CommandType.StoredProcedure
|
||
SqlCmd.Parameters.AddWithValue("@ID", DruckjobID)
|
||
SqlCmd.Parameters.AddWithValue("@filetimestamp", filetimestamp)
|
||
SqlCmd.Connection = SqlConn
|
||
' Globals.WriteTxtLog("Vor SP_EDEX_BL_GET_DRUCK_Parameter")
|
||
Try
|
||
SqlConn.Open()
|
||
' Globals.WriteTxtLog("SQL Verbindung geöffnet")
|
||
DR = SqlCmd.ExecuteReader()
|
||
' Globals.WriteTxtLog("SP_EDEX_BL_GET_DRUCK_Parameter ausgeführt")
|
||
While DR.Read
|
||
userid = DR.Item("userid")
|
||
userid = UCase(userid)
|
||
' Globals.WriteTxtLog("Resultat erhalten, UserID = " & userid)
|
||
erstelltam = DR.Item("erstellt_am")
|
||
End While
|
||
SqlConn.Close()
|
||
' Globals.WriteTxtLog("SQL Verbindung geschlossen")
|
||
SqlCmd.Parameters.Clear()
|
||
'Timestamp für den Dateinamen zusammenstellen
|
||
timestamp = filetimestamp
|
||
Catch ex As Exception
|
||
log.InsertJournale("EDKB07: Fehler beim Auslesen von UserID und Erstelltam-Datum " & CType(Now, String) & " Error: " & ex.Message & " DruckjobID: " & DruckjobID, clsLog.Enum_InfoTyp.Warnung)
|
||
End Try
|
||
' Globals.WriteTxtLog("Auslesen UserID und Erstellam-Datum fertig")
|
||
|
||
If Not Globals.UseTestMode Then
|
||
' Globals.WriteTxtLog("Nicht im Testmodus")
|
||
Dim anzdok As Integer = 0
|
||
Try
|
||
' Globals.WriteTxtLog("Vor CreatePrintjob")
|
||
anzdok = Create_Printjob(DruckjobID, timestamp, userid)
|
||
|
||
If anzdok > 0 Then
|
||
'log.InsertJournale("EDKB07: Parameterfile per DTO an Cold übergeben " & CType(Now, String) & " DruckjobID: " & DruckjobID, clsLog.Enum_InfoTyp.Keine)
|
||
' Globals.WriteTxtLog("Paramaterfile wurde an Cold übergeben")
|
||
Else
|
||
'log.InsertJournale("EDKB07: Parameterfile nicht an COLD übermittelt - keine Daten " & CType(Now, String) & " DruckjobID: " & DruckjobID, clsLog.Enum_InfoTyp.Keine)
|
||
' Globals.WriteTxtLog("Paramaterfile wurde NICHT an Cold übergeben da keine Daten gefunden")
|
||
End If
|
||
|
||
' Status setzen
|
||
' Globals.WriteTxtLog("Start Status setzen")
|
||
SqlCmd.CommandText = "SP_EDEX_BL_UPDATE_DRUCK_StatusByID"
|
||
SqlCmd.CommandType = CommandType.StoredProcedure
|
||
SqlCmd.Parameters.AddWithValue("@Status", 1)
|
||
SqlCmd.Parameters.AddWithValue("@ID", DruckjobID)
|
||
SqlCmd.Parameters.AddWithValue("@AnzParts", part)
|
||
SqlCmd.Connection = SqlConn
|
||
' Globals.WriteTxtLog("SQL Verbindung wird geöffnet")
|
||
SqlConn.Open()
|
||
' Globals.WriteTxtLog("SQL Verbindung ist geöffnet")
|
||
SqlCmd.ExecuteNonQuery()
|
||
' Globals.WriteTxtLog("SP_EDEX_BL_UPDATE_DRUCK_StatusByID wurde ausgeführt, Status=1, Druckjob=" & DruckjobID & ", Anzahl Teile=" & part)
|
||
SqlConn.Close()
|
||
' Globals.WriteTxtLog("SQL Verbindung ist geschlossen")
|
||
SqlCmd.Parameters.Clear()
|
||
Catch ex As Exception
|
||
' Globals.WriteTxtLog("Fehler in Klasse RCVerarbeitung, Methode GetDocBLPDF, catch erreicht")
|
||
log.InsertJournale("EDKB07: Fehler bei Übergabe des Parameterfiles an Cold " & CType(Now, String) & " Error: " & ex.Message & " DruckjobID: " & DruckjobID, clsLog.Enum_InfoTyp.Warnung)
|
||
'Status auf 'abvereckt' (3) ändern
|
||
'Globals.WriteTxtLog("vor Status auf 3 ändern")
|
||
SqlCmd.CommandText = "SP_EDEX_BL_UPDATE_DRUCK_StatusByID"
|
||
SqlCmd.CommandType = CommandType.StoredProcedure
|
||
SqlCmd.Parameters.AddWithValue("@Status", 3)
|
||
SqlCmd.Parameters.AddWithValue("@ID", DruckjobID)
|
||
SqlCmd.Parameters.AddWithValue("@AnzParts", part)
|
||
SqlCmd.Connection = SqlConn
|
||
' Globals.WriteTxtLog("SQL Verbindung wird geöffnet")
|
||
SqlConn.Open()
|
||
' Globals.WriteTxtLog("SQL Verbindung ist geöffnet")
|
||
SqlCmd.ExecuteNonQuery()
|
||
' Globals.WriteTxtLog("SP_EDEX_BL_UPDATE_DRUCK_StatusByID ausgeführt")
|
||
SqlConn.Close()
|
||
' Globals.WriteTxtLog("SQL Verbindung ist geschlossen")
|
||
SqlCmd.Parameters.Clear()
|
||
End Try
|
||
Else
|
||
' Globals.WriteTxtLog("Testmodus")
|
||
Dim owriter As System.IO.StreamWriter
|
||
' Globals.WriteTxtLog("Schreibe Information für Cold an andere Stelle: " & Globals.TestParamFilePath)
|
||
owriter = File.CreateText(Globals.TestParamFilePath & "\" & userid & "00" & timestamp & ".txt")
|
||
owriter.WriteLine("Test BL-Dokumentanforderung")
|
||
owriter.Close()
|
||
' Globals.WriteTxtLog("Ende Testmodus")
|
||
End If
|
||
' Globals.WriteTxtLog("Ende Methode GetDocBLPDF")
|
||
End Sub
|
||
|
||
Private Function Create_Printjob(ByVal druckjobid As Integer, ByVal timestamp As String, ByVal userid As String) As Integer
|
||
' Globals.WriteTxtLog("Start Methode Create_Printjob")
|
||
Dim log As New clsLog
|
||
Dim data As New DataTable
|
||
Dim Partno As String = ""
|
||
|
||
data = get_dokumente(druckjobid)
|
||
Dim anzdok As Integer = data.Rows.Count
|
||
Dim snrpar00 As String = ""
|
||
Dim c As Integer = 0
|
||
|
||
Dim i As Integer
|
||
Dim NewFile As Boolean = True
|
||
Dim owriter As System.IO.StreamWriter = Nothing
|
||
Try
|
||
|
||
For i = 0 To data.Rows.Count - 1
|
||
If NewFile Then
|
||
NewFile = False
|
||
part = part + 1
|
||
Partno = LTrim(Str(part))
|
||
While Len(Partno) < 2
|
||
Partno = "0" + Partno
|
||
End While
|
||
'Je nachdem ob das System im Testmodus läuft, das Parameterfile im entsprechenden Pfad ablegen
|
||
If Globals.UseTestMode Then
|
||
owriter = File.CreateText(Globals.TestParamFilePath & "\" & userid & Partno & timestamp & ".123")
|
||
Else
|
||
owriter = File.CreateText(Globals.ParamFileOutputPath & "\" & userid & Partno & timestamp & ".123")
|
||
End If
|
||
End If
|
||
Try
|
||
snrpar00 = data.Rows(i).Item("nrpar00")
|
||
Catch ex As Exception
|
||
m_log.Log("RCVerarbeitung:Create_Printjob:" + ex.Message + ex.StackTrace, Common.Common.JournalEntryType.Warning)
|
||
End Try
|
||
|
||
''''NOVA!!
|
||
'While Len(snrpar00) < 9
|
||
'snrpar00 = "0" + snrpar00
|
||
'End While
|
||
|
||
If data.Rows(i).Item("Typ") = 3 Then
|
||
'HOST ALT
|
||
If Len(snrpar00) > 8 Then
|
||
snrpar00 = "'" + snrpar00 + "'"
|
||
owriter.WriteLine(Globals.DruckjobParameter & " [-o Dok" & Format(i, "D5") & ".pdf] [-i where NRPAR00 = " & snrpar00 & " and NRDOK00 = '" & data.Rows(i).Item("dokumentid") & "']")
|
||
Else
|
||
'HOST NEU
|
||
snrpar00 = "'" + snrpar00 + "'"
|
||
owriter.WriteLine(Globals.DruckjobParameterAVQ & " [-o Dok" & Format(i, "D5") & ".pdf] [-i where BPKEYNRINHAB = " & snrpar00 & " and MAILINGID = '" & data.Rows(i).Item("dokumentid") & "']")
|
||
End If
|
||
|
||
Else
|
||
snrpar00 = "'" + snrpar00 + "'"
|
||
owriter.WriteLine(Globals.DruckjobParameter & " [-o Dok" & Format(i, "D5") & ".pdf] [-i where NRPAR00 = " & snrpar00 & " and NRDOC00 = '" & data.Rows(i).Item("dokumentid") & "']")
|
||
End If
|
||
c = c + 1
|
||
If c = Globals.DokPerPackage Then
|
||
If part > 0 Then insert_part(druckjobid, part, c)
|
||
c = 0
|
||
NewFile = True
|
||
owriter.Close()
|
||
'send_file(userid, timestamp, Partno, druckjobid)
|
||
End If
|
||
Next
|
||
owriter.Close()
|
||
If NewFile = False Then
|
||
If part > 0 Then insert_part(druckjobid, part, c)
|
||
'send_file(userid, timestamp, Partno, druckjobid)
|
||
data.Dispose()
|
||
End If
|
||
Catch ex As Exception
|
||
log.InsertJournale("EDKB07: Fehler bei Create_Printjob " & CType(Now, String) & " Error: " & ex.Message & " DruckjobID: " & druckjobid, clsLog.Enum_InfoTyp.Warnung)
|
||
Finally
|
||
Try
|
||
Dim partRename As Integer
|
||
partRename = part
|
||
|
||
While partRename >= 0
|
||
Partno = LTrim(Str(partRename))
|
||
While Len(Partno) < 2
|
||
Partno = "0" + Partno
|
||
End While
|
||
If Globals.UseTestMode Then
|
||
Rename(Globals.TestParamFilePath & "\" & userid & Partno & timestamp & ".123", Globals.TestParamFilePath & "\" & userid & Partno & timestamp & ".txt")
|
||
Else
|
||
Rename(Globals.ParamFileOutputPath & "\" & userid & Partno & timestamp & ".123", Globals.TestParamFilePath & "\" & userid & Partno & timestamp & ".txt")
|
||
End If
|
||
partRename = partRename - 1
|
||
End While
|
||
|
||
Catch ex As Exception
|
||
m_log.Log("EDKB07: Fehler beim umbenennen " & CType(Now, String) & " Error: " & ex.Message & " DruckjobID: " & druckjobid, clsLog.Enum_InfoTyp.Warnung)
|
||
End Try
|
||
|
||
End Try
|
||
|
||
|
||
Return anzdok
|
||
End Function
|
||
|
||
'Private Sub send_file(ByVal userid As String, ByVal timestamp As String, ByVal partno As String, ByVal druckjobid As Integer)
|
||
' Dim log As New clsLog
|
||
' If Not Globals.UseTestMode Then
|
||
' Try
|
||
' Dim owriter As System.IO.StreamWriter
|
||
|
||
' owriter = File.CreateText(Globals.CMDFilePath & "\" & userid & partno & timestamp & ".cmd")
|
||
' Dim cmd1 As String
|
||
' cmd1 = Globals.CMDFile1Content.Replace("xfilenamex", userid & partno & timestamp & ".txt")
|
||
' owriter.WriteLine(cmd1)
|
||
' ' cmd2 = Globals.CMDFile2Content.Replace("xfilenamex", userid & timestamp & ".txt")
|
||
' ' owriter.WriteLine(cmd2)
|
||
' owriter.Close()
|
||
' owriter = Nothing
|
||
' Dim i As Integer
|
||
' i = Shell(Globals.CMDFilePath & "\" & userid & partno & timestamp & ".cmd", AppWinStyle.NormalFocus, True, 120000)
|
||
' Threading.Thread.Sleep(3000)
|
||
' 'File.Delete(Globals.CMDFilePath & "\" & userid & timestamp & ".cmd")
|
||
' log.InsertJournale("EDKB07: Parameterfile per DTO an Cold übergeben " & CType(Now, String) & " DruckjobID: " & druckjobid, clsLog.Enum_InfoTyp.Keine)
|
||
' Catch ex As Exception
|
||
' log.InsertJournale("EDKB07: Fehler bei Übergabe des Parameterfiles an Cold " & CType(Now, String) & " Error: " & ex.Message & " DruckjobID: " & druckjobid, clsLog.Enum_InfoTyp.Warnung)
|
||
' End Try
|
||
' End If
|
||
'End Sub
|
||
|
||
Private Function insert_part(ByVal druckjobid As Integer, ByVal part As Integer, ByVal anzdok As Integer) As DataTable
|
||
Dim scmCmdToExecute As SqlCommand = New SqlCommand
|
||
scmCmdToExecute.CommandText = "dbo.sp_edex_bl_insert_druckjobpart"
|
||
scmCmdToExecute.CommandType = CommandType.StoredProcedure
|
||
Dim dtToReturn As DataTable = New DataTable
|
||
Dim sdaAdapter As SqlDataAdapter = New SqlDataAdapter(scmCmdToExecute)
|
||
scmCmdToExecute.Parameters.Add(New SqlParameter("@druckjobid", SqlDbType.Int, 4, ParameterDirection.Input, True, 10, 0, "", DataRowVersion.Proposed, druckjobid))
|
||
scmCmdToExecute.Parameters.Add(New SqlParameter("@partno", SqlDbType.Int, 4, ParameterDirection.Input, True, 10, 0, "", DataRowVersion.Proposed, part))
|
||
scmCmdToExecute.Parameters.Add(New SqlParameter("@anzahl_dokumente", SqlDbType.Int, 4, ParameterDirection.Input, True, 10, 0, "", DataRowVersion.Proposed, anzdok))
|
||
scmCmdToExecute.Connection = Globals.conn_edoka.scoDBConnection
|
||
Globals.conn_edoka.OpenConnection()
|
||
Try
|
||
sdaAdapter.Fill(dtToReturn)
|
||
Return dtToReturn
|
||
Catch ex As Exception
|
||
' // some error occured. Bubble it to caller and encapsulate Exception object
|
||
Throw New Exception("Dokumenterstellung::Generic_Select::" & scmCmdToExecute.CommandText & "::Error occured." & ex.Message, ex)
|
||
Finally
|
||
scmCmdToExecute.Dispose()
|
||
sdaAdapter.Dispose()
|
||
Globals.conn_edoka.CloseConnection(True)
|
||
End Try
|
||
End Function
|
||
|
||
Private Function get_dokumente(ByVal druckjobid As Integer) As DataTable
|
||
Dim scmCmdToExecute As SqlCommand = New SqlCommand
|
||
scmCmdToExecute.CommandText = "dbo.SP_EDEX_BL_GET_DRUCK_Dokumente"
|
||
scmCmdToExecute.CommandType = CommandType.StoredProcedure
|
||
Dim dtToReturn As DataTable = New DataTable
|
||
Dim sdaAdapter As SqlDataAdapter = New SqlDataAdapter(scmCmdToExecute)
|
||
scmCmdToExecute.Parameters.Add(New SqlParameter("@id", SqlDbType.Int, 4, ParameterDirection.Input, True, 10, 0, "", DataRowVersion.Proposed, druckjobid))
|
||
scmCmdToExecute.Connection = Globals.conn_edoka.scoDBConnection
|
||
Globals.conn_edoka.OpenConnection()
|
||
Try
|
||
sdaAdapter.Fill(dtToReturn)
|
||
Return dtToReturn
|
||
Catch ex As Exception
|
||
' // some error occured. Bubble it to caller and encapsulate Exception object
|
||
Throw New Exception("Dokumenterstellung::Generic_Select::" & scmCmdToExecute.CommandText & "::Error occured." & ex.Message, ex)
|
||
Finally
|
||
scmCmdToExecute.Dispose()
|
||
sdaAdapter.Dispose()
|
||
Globals.conn_edoka.CloseConnection(True)
|
||
End Try
|
||
End Function
|
||
|
||
Public Sub PrintJobF(ByVal alnr As Integer, ByVal partno As Integer) Implements EDKB07Verarbeitung.EDKB07Verarbeitung.IEDKB07.PrintJobF
|
||
Print_Docs(alnr, partno)
|
||
End Sub
|
||
|
||
Public Sub PrepareWordandDistiller()
|
||
If Globals.Office2010 = True Then Exit Sub
|
||
'20071002 RGL
|
||
Dim log As New clsLog
|
||
Dim proc As System.Diagnostics.Process
|
||
Dim plist() As Process
|
||
Dim counter1 As Integer = 0
|
||
|
||
'1. Suche ob bereits ein anderer EDKB07 Prozess läuft.
|
||
plist = Process.GetProcessesByName(Globals.OwnName)
|
||
For Each proc In plist
|
||
counter1 = counter1 + 1
|
||
If counter1 > 1 Then
|
||
Exit Sub
|
||
End If
|
||
Next
|
||
|
||
'2. Suche nach allen Word – Instanzen die länger als X Minuten laufen, diese werden beendet.
|
||
plist = Process.GetProcessesByName(Globals.ProcessToKill)
|
||
For Each proc In plist
|
||
Try
|
||
If (proc.StartTime < (DateAdd(DateInterval.Minute, -CInt(Globals.ProcessIdleTime), Now()))) Then
|
||
log.InsertJournale("EDKB07: Beenden Prozess: " + CStr(proc.ProcessName), clsLog.Enum_InfoTyp.Keine)
|
||
proc.Kill()
|
||
End If
|
||
Catch ex As Exception
|
||
log.InsertJournale("EDKB07: Fehler beim Killen von Programminstanz", clsLog.Enum_InfoTyp.Keine)
|
||
End Try
|
||
Next
|
||
|
||
'3. Prüfen ob andere Batches laufen, die den Distiller brauchen (EDKB09)
|
||
' - Suche nach Prozessname
|
||
If Trim(Globals.OtherBatch1) <> "" Then
|
||
plist = Process.GetProcessesByName(Globals.OtherBatch1)
|
||
For Each proc In plist
|
||
Exit Sub
|
||
Next
|
||
End If
|
||
If Trim(Globals.OtherBatch2) <> "" Then
|
||
plist = Process.GetProcessesByName(Globals.OtherBatch2)
|
||
For Each proc In plist
|
||
Exit Sub
|
||
Next
|
||
End If
|
||
If Trim(Globals.OtherBatch3) <> "" Then
|
||
plist = Process.GetProcessesByName(Globals.OtherBatch3)
|
||
For Each proc In plist
|
||
Exit Sub
|
||
Next
|
||
End If
|
||
'20071002 Distiller neu Starten
|
||
If Trim(Globals.NameDistiller) <> "" Then
|
||
plist = Process.GetProcessesByName(Globals.NameDistiller)
|
||
For Each proc In plist
|
||
Try
|
||
log.InsertJournale("EDKB07: Distiller Close", clsLog.Enum_InfoTyp.Information)
|
||
proc.Close() 'Variante1 mit CLOSE
|
||
Threading.Thread.Sleep(2000)
|
||
Catch ex As Exception
|
||
log.InsertJournale("EDKB07: Fehler beim Regulären Beenden der Distiller Instanz", clsLog.Enum_InfoTyp.Keine)
|
||
End Try
|
||
Next
|
||
End If
|
||
If Trim(Globals.NameDistiller) <> "" Then
|
||
plist = Process.GetProcessesByName(Globals.NameDistiller)
|
||
For Each proc In plist
|
||
Try
|
||
log.InsertJournale("EDKB07: Distiller Kill", clsLog.Enum_InfoTyp.Keine)
|
||
proc.Kill() 'Variante 2 mit KILL
|
||
Catch ex As Exception
|
||
log.InsertJournale("EDKB07: Fehler beim Killen der Distiller Instanz", clsLog.Enum_InfoTyp.Keine)
|
||
End Try
|
||
Next
|
||
End If
|
||
Try
|
||
If UCase(Globals.OpenModeDistiller) = "TRUE" Then
|
||
log.InsertJournale("EDKB07: Distiller Start", clsLog.Enum_InfoTyp.Keine)
|
||
Shell(Globals.PathDistiller, AppWinStyle.NormalNoFocus, True)
|
||
Else
|
||
log.InsertJournale("EDKB07: Distiller Start", clsLog.Enum_InfoTyp.Keine)
|
||
Shell(Globals.PathDistiller, AppWinStyle.NormalNoFocus, False)
|
||
End If
|
||
Catch ex As Exception
|
||
log.InsertJournale("EDKB07: Fehler beim Start von Distiller", clsLog.Enum_InfoTyp.Keine)
|
||
End Try
|
||
End Sub
|
||
|
||
#Region " Cold-Mehrfachdruck"
|
||
|
||
Public Sub GetColdMehrfachDruck(ByVal sTGNummer As String, ByVal iJobID As Integer, ByVal colData As Object, ByRef binOutput As Object) Implements EDKB07Verarbeitung.EDKB07Verarbeitung.IEDKB07.GetColdMehrfachDruck
|
||
'Aufbereiten des Mehrfachdrucks
|
||
Dim log As New clsLog
|
||
Try
|
||
|
||
|
||
|
||
log.InsertJournale("EDKB07: Mehrfachdruck von " & sTGNummer & " angefordert " & CType(Now, String) + " DruckjobID: " & iJobID, clsLog.Enum_InfoTyp.Keine)
|
||
StartMehrfachDruck(sTGNummer, iJobID, colData, binOutput)
|
||
log.InsertJournale("EDKB07: Mehrfachdruck von " & sTGNummer & " angeschlossen " & CType(Now, String) + " DruckjobID: " & iJobID, clsLog.Enum_InfoTyp.Keine)
|
||
Catch ex As Exception
|
||
log.InsertJournale("EDKB07: Mehrfachdruck Allg. Fehler: " & CType(Now, String) & " Error: " & ex.Message & " DruckjobID: " & iJobID, clsLog.Enum_InfoTyp.Warnung)
|
||
End Try
|
||
End Sub
|
||
|
||
#End Region
|
||
|
||
End Class
|