1 #Region "Microsoft.VisualBasic::66a9a4e8f01366932d9f43d0d0a107cf, Microsoft.VisualBasic.Core\ApplicationServices\Debugger\Logging\EventLog.vb"
2
3     ' Author:
4     
5     '       asuka (amethyst.asuka@gcmodeller.org)
6     '       xie (genetics@smrucc.org)
7     '       xieguigang (xie.guigang@live.com)
8     
9     ' Copyright (c) 2018 GPL3 Licensed
10     
11     
12     ' GNU GENERAL PUBLIC LICENSE (GPL3)
13     
14     
15     ' This program is free software: you can redistribute it and/or modify
16     ' it under the terms of the GNU General Public License as published by
17     ' the Free Software Foundation, either version 3 of the License, or
18     ' (at your option) any later version.
19     
20     ' This program is distributed in the hope that it will be useful,
21     ' but WITHOUT ANY WARRANTY; without even the implied warranty of
22     ' MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
23     ' GNU General Public License for more details.
24     
25     ' You should have received a copy of the GNU General Public License
26     ' along with this program. If not, see <http://www.gnu.org/licenses/>.
27
28
29
30     ' /********************************************************************************/
31
32     ' Summaries:
33
34     '     Class EventLog
35     
36     '         Properties: Initialized, Product, Services
37     
38     '         Constructor: (+1 OverloadsSub New
39     '         Function: __install, (+3 Overloads) LogException, ToString, (+6 Overloads) WriteEntry
40     
41     
42     ' /********************************************************************************/
43
44 #End Region
45
46 Imports System.ComponentModel
47 Imports System.Reflection
48 Imports System.Runtime.CompilerServices
49 Imports Microsoft.VisualBasic.Linq.Extensions
50
51 Namespace ApplicationServices.Debugging.Logging
52
53     ''' <summary>
54     ''' Provides interaction with Windows event logs.(这个日志入口点对象的创建应该调用于安装程序的模块之中,并且以管理员权限执行)
55     ''' </summary>
56     ''' 
57     <InstallerType("System.Diagnostics.EventLogInstaller, System.Configuration.Install, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a")>
58     <MonitoringDescription("EventLogDesc")>
59     Public Class EventLog
60
61         Public ReadOnly Property Product As String
62         Public ReadOnly Property Services As String
63         Public ReadOnly Property Initialized As Boolean
64
65         ''' <summary>
66         ''' 
67         ''' </summary>
68         ''' <param name="Product">Source</param>
69         ''' <param name="Services"></param>
70         Sub New(Services As String, Product As String)
71             Me.Product = Product
72             Me.Services = Services
73             Try
74                 Me.Initialized = __install(Services, Product)
75             Catch ex As Exception  ' 没有管理员权限
76                 Me.Initialized = False
77             End Try
78         End Sub
79
80         Private Shared Function __install(Services As String, Product As StringAs Boolean
81             If Not (System.Diagnostics.EventLog.SourceExists(Product, ".")) Then
82                 Dim evscd As New EventSourceCreationData(Product, Services) With {
83                     .MachineName = Environment.MachineName
84                 }
85                 Try
86                     Call System.Diagnostics.EventLog.CreateEventSource(evscd)
87                 Catch ex As Exception
88                     Call ex.PrintException
89                     Return False
90                 End Try
91             End If
92
93             Return True
94         End Function
95
96         ''' <summary>
97         ''' Writes a localized entry to the event log.
98         ''' </summary>
99         ''' <param name="EventType">An <see cref="System.Diagnostics.EventLogEntryType"/> value that indicates the event type.</param>
100         ''' <param name="category">A resource identifier that corresponds to a string defined in the category resource file of the event source, or zero to specify no category for the event.</param>
101         ''' <returns></returns>
102         Public Function WriteEntry(message As String,
103                                    Optional EventType As EventLogEntryType = EventLogEntryType.Information,
104                                    Optional category As Integer = 1) As Boolean
105             Try
106 #If DEBUG Then
107                 Call message.__DEBUG_ECHO
108 #End If
109                 Using evLog As New System.Diagnostics.EventLog(Services, ".", Product)
110                     Call evLog.WriteEvent(New EventInstance(10001 + category, category, EventType), {message})
111                 End Using
112             Catch ex As Exception
113                 Return False
114             End Try
115
116             Return True
117         End Function
118
119         ''' <summary>
120         ''' Writes a localized entry to the event log.
121         ''' </summary>
122         ''' <param name="EventType">An <see cref="System.Diagnostics.EventLogEntryType"/> value that indicates the event type.</param>
123         ''' <param name="category">A resource identifier that corresponds to a string defined in the category resource file of the event source, or zero to specify no category for the event.</param>
124         ''' <returns></returns>
125         Public Function WriteEntry(Message As IEnumerable(Of String),
126                                    Optional EventType As EventLogEntryType = EventLogEntryType.Information,
127                                    Optional category As Integer = 0) As Boolean
128             Try
129 #If DEBUG Then
130                 Dim s As String = Message.JoinBy(vbCrLf)
131                 Call s.__DEBUG_ECHO
132 #End If
133                 Using evLog As New System.Diagnostics.EventLog(Services, ".", Product)
134                     Dim data As Object() = Message.Select(Function(str) DirectCast(str, Object)).ToArray
135                     Call evLog.WriteEvent(New EventInstance(10001 + category * 55, category, EventType), data)
136                 End Using
137             Catch ex As Exception
138
139                 Return False
140             End Try
141
142             Return True
143         End Function
144
145         ''' <summary>
146         ''' Writes a localized entry to the event log.
147         ''' </summary>
148         ''' <param name="EventType">An <see cref="System.Diagnostics.EventLogEntryType"/> value that indicates the event type.</param>
149         ''' <param name="category">A resource identifier that corresponds to a string defined in the category resource file of the event source, or zero to specify no category for the event.</param>
150         ''' <returns></returns>
151         Public Function WriteEntry(Message As System.Collections.Generic.IEnumerable(Of String),
152                                    Trace As String,
153                                    Optional EventType As System.Diagnostics.EventLogEntryType = EventLogEntryType.Information,
154                                    Optional category As Integer = 0) As Boolean
155             Message = Message.Join("USER_TRACE: " & Trace)
156             Return WriteEntry(Message, EventType, category)
157         End Function
158
159         ''' <summary>
160         ''' Writes a localized entry to the event log.
161         ''' </summary>
162         ''' <param name="EventType">An <see cref="System.Diagnostics.EventLogEntryType"/> value that indicates the event type.</param>
163         ''' <param name="category">A resource identifier that corresponds to a string defined in the category resource file of the event source, or zero to specify no category for the event.</param>
164         ''' <returns></returns>
165         Public Function WriteEntry(Message As System.Collections.Generic.IEnumerable(Of String),
166                                    Trace As MethodBase,
167                                    Optional EventType As System.Diagnostics.EventLogEntryType = EventLogEntryType.Information,
168                                    Optional category As Integer = 0) As Boolean
169             Return WriteEntry(Message, Trace.GetFullName, EventType, category)
170         End Function
171
172         ''' <summary>
173         ''' Writes a localized entry to the event log.
174         ''' </summary>
175         ''' <param name="EventType">An <see cref="System.Diagnostics.EventLogEntryType"/> value that indicates the event type.</param>
176         ''' <param name="category">A resource identifier that corresponds to a string defined in the category resource file of the event source, or zero to specify no category for the event.</param>
177         ''' <returns></returns>
178         Public Function WriteEntry(Message As String, Trace As StringOptional EventType As System.Diagnostics.EventLogEntryType = EventLogEntryType.Information, Optional category As Integer = 2) As Boolean
179             Return WriteEntry({NameOf(Message) & ": " & Message, NameOf(Trace) & ": " & Trace}, EventType, category)
180         End Function
181
182         ''' <summary>
183         ''' Writes a localized entry to the event log.
184         ''' </summary>
185         ''' <param name="EventType">An <see cref="System.Diagnostics.EventLogEntryType"/> value that indicates the event type.</param>
186         ''' <param name="category">A resource identifier that corresponds to a string defined in the category resource file of the event source, or zero to specify no category for the event.</param>
187         ''' <returns></returns>
188         Public Function WriteEntry(Message As String,
189                                    Trace As MethodBase,
190                                    Optional EventType As System.Diagnostics.EventLogEntryType = EventLogEntryType.Information,
191                                    Optional category As Integer = 2) As Boolean
192             Return WriteEntry(Message, Trace.GetFullName, EventType, category)
193         End Function
194
195         ''' <summary>
196         ''' Writes a localized entry to the event log.
197         ''' </summary>
198         ''' <param name="category">A resource identifier that corresponds to a string defined in the category resource file of the event source, or zero to specify no category for the event.</param>
199         ''' <returns></returns>
200         ''' <param name="Trace">可以不需要进行额外的处理,编译器会自动在这个参数填充调用栈的位置</param>
201         ''' 
202 #If NET_40 = 0 Then
203         Public Function LogException(ex As Exception, <CallerMemberName> Optional Trace As String = ""Optional category As Integer = 3) As Boolean
204 #Else
205         Public Function LogException(ex As Exception, Optional Trace As String = ""Optional category As Integer = 3) As Boolean
206 #End If
207             Dim Data As String = ""
208
209             If Not ex.Data Is Nothing Then
210                 Try
211                     Data = String.Join(vbCrLf, (From obj In ex.Data.Keys Select obj.ToString & "  ==> " & ex.Data(obj).ToString).ToArray)
212                 Catch
213                 End Try
214             End If
215
216 #If NET_40 = 0 Then
217             Dim MSG_DATA As New List(Of String) From {
218                 "Exception: " & Scripting.InputHandler.ToString(ex.Message),
219                 "InnerException: " & Scripting.InputHandler.ToString(ex.InnerException),
220                 "HelpLink: " & Scripting.InputHandler.ToString(ex.HelpLink),
221                 "Handle: " & Scripting.InputHandler.ToString(ex.HResult),
222                 "Source: " & Scripting.InputHandler.ToString(ex.Source)
223             }
224 #Else
225             Dim MSG_DATA As New List(Of String) From {
226                 "Exception: " & Scripting.InputHandler.ToString(ex.Message),
227                 "InnerException: " & Scripting.InputHandler.ToString(ex.InnerException),
228                 "HelpLink: " & Scripting.InputHandler.ToString(ex.HelpLink),
229                 "Source: " & Scripting.InputHandler.ToString(ex.Source)
230             }
231 #End If
232             Dim Stacks As String() = Strings.Split(Scripting.InputHandler.ToString(ex.StackTrace), vbCrLf)
233             Dim exTrace As String = If(ex.TargetSite Is Nothing OrElse ex.TargetSite.DeclaringType Is Nothing"null", ex.TargetSite.DeclaringType.FullName)
234             Call MSG_DATA.AddRange((From deepth As Integer In Stacks.Sequence Select $"stack__{Stacks.Length - deepth}:  {Stacks(deepth)}").ToArray)
235             Call MSG_DATA.AddRange({"Data " & Data, $"Trace: {exTrace}:{Scripting.ToString(ex.TargetSite)}""USER_TRACE: " & Trace})
236             Return WriteEntry(MSG_DATA, EventLogEntryType.Error, category)
237         End Function
238
239         ''' <summary>
240         ''' Writes a localized entry to the event log.
241         ''' </summary>
242         ''' <param name="category">A resource identifier that corresponds to a string defined in the category resource file of the event source, or zero to specify no category for the event.</param>
243         ''' <returns></returns>
244         Public Function LogException(ex As Exception, Trace As MethodBase, Optional category As Integer = 3) As Boolean
245             Return LogException(ex, Trace.GetFullName, category)
246         End Function
247
248         ''' <summary>
249         ''' $"{<see cref="Services"/>}//{<see cref="Product"/>}"
250         ''' </summary>
251         ''' <returns></returns>
252         Public Overrides Function ToString() As String
253             Return $"{Services}//{Product}"
254         End Function
255     End Class
256 End Namespace