1 #Region "Microsoft.VisualBasic::59dd318712a705150ac6ad1cc06800f9, Microsoft.VisualBasic.Core\ApplicationServices\Debugger\DebuggerArgs.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 '     Module DebuggerArgs
35
36 '         Properties: AutoPaused, ErrLogs
37
38 '         Sub: __logShell, InitDebuggerEnvir, SaveErrorLog
39
40
41 ' /********************************************************************************/
42
43 #End Region
44
45 Imports System.Runtime.CompilerServices
46 Imports Microsoft.VisualBasic.ComponentModel.DataSourceModel
47 Imports Microsoft.VisualBasic.Language.UnixBash
48 Imports Microsoft.VisualBasic.Language.UnixBash.FileSystem
49 Imports CLI = Microsoft.VisualBasic.CommandLine.CommandLine
50
51 Namespace ApplicationServices.Debugging
52
53     ''' <summary>
54     ''' 调试器设置参数模块
55     ''' </summary>
56     Module DebuggerArgs
57
58         ''' <summary>
59         ''' 错误日志的文件存储位置,默认是在AppData里面
60         ''' </summary>
61         ''' <returns></returns>
62         Public ReadOnly Property ErrLogs As Func(Of String) = Nothing
63
64         ''' <summary>
65         ''' 
66         ''' </summary>
67         ''' <param name="log">日志文本</param>
68         Public Sub SaveErrorLog(log As String)
69             If Not ErrLogs Is Nothing Then
70                 Call log.SaveTo(_ErrLogs())
71             End If
72         End Sub
73
74         ''' <summary>
75         ''' Logging command shell history.
76         ''' </summary>
77         ''' <param name="args"></param>
78         Private Sub __logShell(args As CLI)
79             Dim CLI As String = App.ExecutablePath & " " & args.CLICommandArgvs
80             Dim log As String = $"{PS1.Fedora12.ToString} {CLI}"
81             Dim logFile As String = App.LogErrDIR.ParentPath & "/.shells.log"
82
83             If InStr(logFile.ParentPath, "/sbin/") = 1 Then
84                 ' 当程序运行在apache+linux web服务器上面的时候,
85                 ' 对于apache用户,linux服务器上面得到的文件夹是/sbin,则会出现权限错误,这个时候重定向到应用程序自身的文件夹之中
86                 logFile = App.HOME & "/.logs/.shells.log"
87             End If
88
89             Try
90                 If FileHandles.Wait(file:=logFile) Then
91                     Call FileIO.FileSystem.CreateDirectory(logFile.ParentPath)
92                     Call FileIO.FileSystem.WriteAllText(logFile, log & vbCrLf, True)
93                 End If
94             Catch ex As Exception
95                 ' 连日志记录都出错了,已经没有地方可以写日志了,则只能够直接将错误信息以警告的方式打印出来
96                 Call ex.Message.Warning
97
98                 '[ERROR 09/07/2017 1052:12] :System.Exception : LogException ---> System.Exception: Exception of type 'System.Exception' was thrown. ---> System.ArgumentNullException: Value cannot be null.
99                 'Parameter name: path
100                 '                at System.IO.DirectoryInfo.CheckPath(System.String path) [0x00003] in <902ab9e386384bec9c07fa19aa938869>:0 
101                 '  at System.IO.DirectoryInfo..ctor(System.String path, System.Boolean simpleOriginalPath) [0x00006] in <902ab9e386384bec9c07fa19aa938869>:0 
102                 '  at System.IO.DirectoryInfo..ctor(System.String path) [0x00000] in <902ab9e386384bec9c07fa19aa938869>:0 
103                 '  at(wrapper remoting-invoke-With-check) System.IO.DirectoryInfo:.ctor(Of String)
104                 '                at Microsoft.VisualBasic.FileIO.FileSystem.GetDirectoryInfo(System.String directory) [0x00000] in <828807dda9f14f24a7db780c6c644162>:0 
105                 '  at Microsoft.VisualBasic.ProgramPathSearchTool.GetDirectoryFullPath(System.String dir) [0x00000] in :0 
106                 '   --- End of inner exception stack trace ---
107                 '   --- End of inner exception stack trace ---
108                 '[ERROR 09/07/2017 10:52:12] :System.Exception : GetDirectoryFullPath ---> System.Exception: Exception of type 'System.Exception' was thrown. ---> System.ArgumentNullException: Value cannot be null.
109                 'Parameter name: path
110                 '                at System.IO.DirectoryInfo.CheckPath(System.String path) [0x00003] in <902ab9e386384bec9c07fa19aa938869>:0 
111                 '  at System.IO.DirectoryInfo..ctor(System.String path, System.Boolean simpleOriginalPath) [0x00006] in <902ab9e386384bec9c07fa19aa938869>:0 
112                 '  at System.IO.DirectoryInfo..ctor(System.String path) [0x00000] in <902ab9e386384bec9c07fa19aa938869>:0 
113                 '  at(wrapper remoting-invoke-With-check) System.IO.DirectoryInfo:.ctor(Of String)
114                 '                at Microsoft.VisualBasic.FileIO.FileSystem.GetDirectoryInfo(System.String directory) [0x00000] in <828807dda9f14f24a7db780c6c644162>:0 
115                 '  at Microsoft.VisualBasic.ProgramPathSearchTool.GetDirectoryFullPath(System.String dir) [0x00000] in :0 
116                 '   --- End of inner exception stack trace ---
117                 '   --- End of inner exception stack trace ---
118                 '[ERROR 09/07/2017 10:52:12] :System.Exception : InitDebuggerEnvir ---> System.UnauthorizedAccessException: Access to the path "/sbin/.local" Is denied.
119                 '  at System.IO.Directory.CreateDirectoriesInternal(System.String path) [0x0005e] in <902ab9e386384bec9c07fa19aa938869>:0 
120                 '  at System.IO.Directory.CreateDirectory(System.String path) [0x0008f] in <902ab9e386384bec9c07fa19aa938869>:0 
121                 '  at System.IO.DirectoryInfo.Create() [0x00000] in <902ab9e386384bec9c07fa19aa938869>: 0 
122                 '  at(wrapper remoting-invoke-With-check) System.IO.DirectoryInfo:Create()
123                 '                at System.IO.Directory.CreateDirectoriesInternal(System.String path) [0x00036] in <902ab9e386384bec9c07fa19aa938869>:0 
124                 '  at System.IO.Directory.CreateDirectory(System.String path) [0x0008f] in <902ab9e386384bec9c07fa19aa938869>:0 
125                 '  at System.IO.DirectoryInfo.Create() [0x00000] in <902ab9e386384bec9c07fa19aa938869>: 0 
126                 '  at(wrapper remoting-invoke-With-check) System.IO.DirectoryInfo:Create()
127                 '                at System.IO.Directory.CreateDirectoriesInternal(System.String path) [0x00036] in <902ab9e386384bec9c07fa19aa938869>:0 
128                 '  at System.IO.Directory.CreateDirectory(System.String path) [0x0008f] in <902ab9e386384bec9c07fa19aa938869>:0 
129                 '  at System.IO.DirectoryInfo.Create() [0x00000] in <902ab9e386384bec9c07fa19aa938869>: 0 
130                 '  at(wrapper remoting-invoke-With-check) System.IO.DirectoryInfo:Create()
131                 '                at System.IO.Directory.CreateDirectoriesInternal(System.String path) [0x00036] in <902ab9e386384bec9c07fa19aa938869>:0 
132                 '  at System.IO.Directory.CreateDirectory(System.String path) [0x0008f] in <902ab9e386384bec9c07fa19aa938869>:0 
133                 '  at System.IO.DirectoryInfo.Create() [0x00000] in <902ab9e386384bec9c07fa19aa938869>: 0 
134                 '  at(wrapper remoting-invoke-With-check) System.IO.DirectoryInfo:Create()
135                 '                at System.IO.Directory.CreateDirectoriesInternal(System.String path) [0x00036] in <902ab9e386384bec9c07fa19aa938869>:0 
136                 '  at System.IO.Directory.CreateDirectory(System.String path) [0x0008f] in <902ab9e386384bec9c07fa19aa938869>:0 
137                 '  at Microsoft.VisualBasic.FileIO.FileSystem.CreateDirectory(System.String directory) [0x00025] in <828807dda9f14f24a7db780c6c644162>:0 
138                 '  at Microsoft.VisualBasic.Debugging.DebuggerArgs.__logShell(Microsoft.VisualBasic.CommandLine.CommandLine args) [0x00056] in :0 
139                 '  at Microsoft.VisualBasic.Debugging.DebuggerArgs.InitDebuggerEnvir(Microsoft.VisualBasic.CommandLine.CommandLine args, System.String caller) [0x00018] in :0 
140                 '   --- End of inner exception stack trace ---
141             End Try
142         End Sub
143
144         ''' <summary>
145         ''' Some optional VisualBasic debugger parameter help information.(VisualBasic调试器的一些额外的开关参数的帮助信息)
146         ''' </summary>
147         Public Const DebuggerHelps As String =
148         "Additional VisualBasic App debugger arguments:   --echo on/off/all/warn/error /mute /auto-paused --err <filename.log> /ps1 <bash_PS1> /@set ""var1='value1';var2='value2'""
149
150     [--echo] The debugger echo options, it have 5 values:
151              on     App will output all of the debugger echo message, but the VBDebugger.Mute option is enabled, disable echo options can be control by the program code;
152              off    App will not output any debugger echo message, the VBDebugger.Mute option is disabled;
153              all    App will output all of the debugger echo message, the VBDebugger.Mute option is disabled;
154              warn   App will only output warning level and error level message;
155              error  App will just only output error level message.
156
157     [--err]  The error logs save copy:
158              If there is an unhandled exception in your App, this will cause your program crashed, then the exception will be save to error log, 
159              and by default the error log is saved in the AppData, then if this option is enabled, the error log will saved a copy to the 
160              specific location at the mean time. 
161
162     [/mute]  This boolean flag will mute all debugger output.
163
164     [/auto-paused] This boolean flag will makes the program paused after the command is executed done. and print a message on the console:
165                        ""Press any key to continute..."
166
167     [/@set]  This option will be using for settings of the interval environment variable.
168
169     ** Additionally, you can using ""/linux-bash"" command for generates the bash shortcuts on linux system.
170 "
171         Public ReadOnly Property AutoPaused As Boolean
172
173         ''' <summary>
174         ''' Initialize the global environment variables in this App process.
175         ''' </summary>
176         ''' <param name="args">--echo on/off/all/warn/error --err &lt;path.log></param>
177         <Extension> Public Sub InitDebuggerEnvir(args As CLI, <CallerMemberName> Optional caller$ = Nothing)
178             If Not String.Equals(caller, "Main"Then
179                 Return  ' 这个调用不是从Main出发的,则不设置环境了,因为这个环境可能在其他的代码上面设置过了
180             Else
181                 Try
182                     Call __logShell(args)
183                 Catch ex As Exception
184                     ' 因为只是进行命令行的调用历史的记录,所以实在不行的话就放弃这次的调用记录
185                     Call ex.PrintException
186                 End Try
187             End If
188
189             Dim opt As String = args <= "--echo"
190             Dim log As String = args <= "--err"
191
192             If Not String.IsNullOrEmpty(log) Then
193                 _ErrLogs = Function() log
194             Else
195
196             End If
197
198             Dim config As Config = Config.Load
199
200             If String.IsNullOrEmpty(opt) Then ' 默认的on参数
201                 VBDebugger.__level = config.level
202             Else
203                 Select Case opt.ToLower
204                     Case "on"
205                         VBDebugger.__level = DebuggerLevels.On
206                     Case "off"
207                         VBDebugger.__level = DebuggerLevels.Off
208                     Case "all"
209                         VBDebugger.__level = DebuggerLevels.All
210                     Case "warn""warning"
211                         VBDebugger.__level = DebuggerLevels.Warning
212                     Case "err""error"
213                         VBDebugger.__level = DebuggerLevels.Error
214                     Case Else
215                         VBDebugger.__level = DebuggerLevels.On
216                         Call Console.WriteLine($"[INFO] The debugger argument value --echo:={opt} is invalid, using default settings.")
217                 End Select
218             End If
219
220             _AutoPaused = args.GetBoolean("/auto-paused")
221
222             If args.GetBoolean("/mute"Then
223                 VBDebugger.Mute = True
224             Else
225                 VBDebugger.Mute = config.mute
226             End If
227
228             Dim vars As Dictionary(Of StringString) = args.EnvironmentVariables
229             Dim disableLoadOptions As Boolean = args.GetBoolean("--load_options.disable")
230
231             ' --load_options.disable 开关将会禁止所有的环境项目的设置
232             ' 但是环境变量任然会进行加载设置
233
234             If Not disableLoadOptions AndAlso Not vars.IsNullOrEmpty Then
235                 Call App.JoinVariables(
236                     vars _
237                     .Select(Function(x)
238                                 Return New NamedValue(Of StringWith {
239                                     .Name = x.Key,
240                                     .Value = x.Value
241                                 }
242                             End Function).ToArray)
243
244                 If vars.ContainsKey("Proxy"Then
245                     WebServiceUtils.Proxy = vars("Proxy")
246                     Call $"[Config] webUtils_proxy={WebServiceUtils.Proxy}".__INFO_ECHO
247                 End If
248                 If vars.ContainsKey("setwd"Then
249                     App.CurrentDirectory = vars("setwd")
250                     Call $"[Config] current_work_directory={App.CurrentDirectory}".__INFO_ECHO
251                 End If
252                 If vars.ContainsKey("buffer_size"Then
253                     Call App.SetBufferSize(vars!buffer_size)
254                 End If
255             End If
256
257             ' /@var=name "value"
258             For Each var As NamedValue(Of StringIn args.ParameterList
259                 With var
260                     If InStr(.Name, "/@var=", CompareMethod.Text) = 1 Then
261                         Dim name$ = .Name.GetTagValue("=").Value
262                         Call App.JoinVariable(name, .Value)
263                     End If
264                 End With
265             Next
266         End Sub
267     End Module
268 End Namespace