1 |
#Region "Microsoft.VisualBasic::69ea48bcfccd3737ab9c2660a4589dd6, Microsoft.VisualBasic.Core\Extensions\IO\Path\ProgramPathSearchTool.vb"
|
2 |
|
3 |
|
4 |
|
5 |
|
6 |
|
7 |
|
8 |
|
9 |
|
10 |
|
11 |
|
12 |
|
13 |
|
14 |
|
15 |
|
16 |
|
17 |
|
18 |
|
19 |
|
20 |
|
21 |
|
22 |
|
23 |
|
24 |
|
25 |
|
26 |
|
27 |
|
28 |
|
29 |
|
30 |
|
31 |
|
32 |
|
33 |
|
34 |
|
35 |
|
36 |
|
37 |
|
38 |
|
39 |
|
40 |
|
41 |
|
42 |
|
43 |
|
44 |
|
45 |
#End Region
|
46 |
|
47 |
Imports System.Collections.ObjectModel
|
48 |
Imports System.ComponentModel
|
49 |
Imports System.IO
|
50 |
Imports System.Runtime.CompilerServices
|
51 |
Imports System.Text.RegularExpressions
|
52 |
Imports Microsoft.VisualBasic.CommandLine.Reflection
|
53 |
Imports Microsoft.VisualBasic.Language
|
54 |
Imports Microsoft.VisualBasic.Language.Default
|
55 |
Imports Microsoft.VisualBasic.Language.UnixBash
|
56 |
Imports Microsoft.VisualBasic.Linq
|
57 |
Imports ENV = System.Environment
|
58 |
Imports r = System.Text.RegularExpressions.Regex
|
59 |
|
60 |
Namespace FileIO.Path
|
61 |
|
62 |
|
63 |
|
64 |
|
65 |
|
66 |
|
67 |
|
68 |
Public Class ProgramPathSearchTool
|
69 |
|
70 |
ReadOnly Environments As New List(Of String) From {"ProgramFiles(x86)", "ProgramFiles"}
|
71 |
|
72 |
Const VERSION As String = "[-_`~.]\d+(\.\d+)*"
|
73 |
Const TopDirectory As SearchOption = SearchOption.SearchTopLevelOnly
|
74 |
|
75 |
Public ReadOnly Property Directories As IReadOnlyCollection(Of String)
|
76 |
<MethodImpl(MethodImplOptions.AggressiveInlining)>
|
77 |
Get
|
78 |
Return Environments _
|
79 |
.Select(Function(var) ENV.GetEnvironmentVariable(var)) _
|
80 |
.Join(CustomDirectories.SafeQuery) _
|
81 |
.Where(Function(dir)
|
82 |
Return (Not dir.StringEmpty) AndAlso dir.DirectoryExists
|
83 |
End Function) _
|
84 |
.ToArray
|
85 |
End Get
|
86 |
End Property
|
87 |
|
88 |
Public Property CustomDirectories As String()
|
89 |
|
90 |
|
91 |
|
92 |
|
93 |
|
94 |
|
95 |
|
96 |
Sub New(ParamArray ENV$())
|
97 |
Environments += ENV
|
98 |
End Sub
|
99 |
|
100 |
Public Iterator Function FindScript(keyword$, Optional withExtension$ = Nothing) As IEnumerable(Of String)
|
101 |
For Each dir As String In Directories
|
102 |
For Each file As String In SearchScriptFile(dir, keyword, withExtension)
|
103 |
Yield file
|
104 |
Next
|
105 |
Next
|
106 |
End Function
|
107 |
|
108 |
|
109 |
|
110 |
|
111 |
|
112 |
|
113 |
|
114 |
Public Iterator Function FindProgram(keyword$, Optional includeDll As Boolean = True) As IEnumerable(Of String)
|
115 |
For Each dir As String In Directories
|
116 |
For Each file As String In SearchProgram(dir, keyword, includeDll)
|
117 |
Yield file
|
118 |
Next
|
119 |
For Each file As String In SearchProgram($"{dir}/{keyword}", keyword, includeDll)
|
120 |
Yield file
|
121 |
Next
|
122 |
Next
|
123 |
End Function
|
124 |
|
125 |
#Region "Search Implementation Internal"
|
126 |
|
127 |
|
128 |
|
129 |
|
130 |
|
131 |
|
132 |
|
133 |
|
134 |
Private Shared Function BranchRule(programFiles$, keyword$) As IEnumerable(Of String)
|
135 |
Dim programFilesDirectories = FileSystem.GetDirectories(programFiles, TopDirectory, keyword)
|
136 |
Dim fsObjs As New List(Of String)
|
137 |
|
138 |
For Each dir As String In programFilesDirectories
|
139 |
fsObjs += FileSystem.GetDirectories(dir, TopDirectory)
|
140 |
Next
|
141 |
|
142 |
Call fsObjs.Add(programFilesDirectories.ToArray)
|
143 |
|
144 |
If fsObjs = 0 Then
|
145 |
|
146 |
Dim dirs = FileSystem.GetDirectories(programFiles, TopDirectory)
|
147 |
Dim version As String = keyword & ProgramPathSearchTool.VERSION
|
148 |
Dim patterns$() = LinqAPI.Exec(Of String) _
|
149 |
_
|
150 |
() <= From DIR As String
|
151 |
In dirs
|
152 |
Let name As String = FileSystem.GetDirectoryInfo(DIR).Name
|
153 |
Let match = r.Match(name, version, RegexOptions.IgnoreCase)
|
154 |
Where match.Success
|
155 |
Select DIR
|
156 |
|
157 |
Call fsObjs.Add(patterns)
|
158 |
End If
|
159 |
|
160 |
Return fsObjs
|
161 |
End Function
|
162 |
|
163 |
|
164 |
|
165 |
|
166 |
|
167 |
|
168 |
|
169 |
|
170 |
|
171 |
|
172 |
<ExportAPI("Search.Scripts", Info:="Search for the path of a script file with a specific extension name.")>
|
173 |
Public Shared Function SearchScriptFile(dir$, keyword$, Optional withExtension$ = Nothing) As IEnumerable(Of String)
|
174 |
Dim scriptFileNameRule$ = $"*{keyword}*{withExtension}"
|
175 |
Dim extNameAssert As Assert(Of String)
|
176 |
|
177 |
If withExtension.StringEmpty Then
|
178 |
extNameAssert = Function(path) path.ExtensionSuffix.StringEmpty
|
179 |
Else
|
180 |
extNameAssert = Function(path) True
|
181 |
End If
|
182 |
|
183 |
Return searchImpl(dir, {scriptFileNameRule}).Where(Function(file) extNameAssert(file))
|
184 |
End Function
|
185 |
|
186 |
Private Shared Function safeGetFiles(dir$, rules$()) As IEnumerable(Of String)
|
187 |
If dir.DirectoryExists Then
|
188 |
Return FileSystem.GetFiles(dir, TopDirectory, rules)
|
189 |
Else
|
190 |
Return {}
|
191 |
End If
|
192 |
End Function
|
193 |
|
194 |
Private Shared Iterator Function searchImpl(dir$, rules$()) As IEnumerable(Of String)
|
195 |
Dim files As IEnumerable(Of String) = safeGetFiles(dir, rules)
|
196 |
Dim binDIR As String = $"{dir}/bin/"
|
197 |
Dim programDIR As String = $"{dir}/Program"
|
198 |
Dim scriptsDIR As String = $"{dir}/scripts"
|
199 |
|
200 |
For Each folder As String In {binDIR, programDIR, scriptsDIR}
|
201 |
If FileSystem.DirectoryExists(folder) Then
|
202 |
For Each file As String In ls - l - rules <= folder
|
203 |
Yield file
|
204 |
Next
|
205 |
End If
|
206 |
Next
|
207 |
|
208 |
For Each file As String In files
|
209 |
Yield file
|
210 |
Next
|
211 |
End Function
|
212 |
|
213 |
|
214 |
|
215 |
|
216 |
|
217 |
|
218 |
|
219 |
|
220 |
<ExportAPI("DIR.Search.Program_Directory")>
|
221 |
<Description("Search for the directories which its name was matched the keyword pattern.")>
|
222 |
Public Shared Iterator Function SearchDirectory(keyword$, Optional specificDrive$ = Nothing) As IEnumerable(Of String)
|
223 |
Dim drives As ReadOnlyCollection(Of DriveInfo)
|
224 |
|
225 |
If String.IsNullOrEmpty(specificDrive) Then
|
226 |
drives = FileSystem.Drives
|
227 |
Else
|
228 |
drives = New ReadOnlyCollection(Of DriveInfo)({FileSystem.GetDriveInfo(specificDrive)})
|
229 |
End If
|
230 |
|
231 |
For Each drive As DriveInfo In drives
|
232 |
For Each dir As String In SearchDrive(drive, keyword)
|
233 |
Yield dir
|
234 |
Next
|
235 |
Next
|
236 |
End Function
|
237 |
|
238 |
Private Shared Function SearchDrive(drive As DriveInfo, keyword As String) As String()
|
239 |
If Not drive.IsReady Then
|
240 |
Return New String() {}
|
241 |
End If
|
242 |
|
243 |
Dim driveName$ = drive.RootDirectory.FullName
|
244 |
Dim driveRoot = FileSystem.GetDirectories(driveName, SearchOption.SearchTopLevelOnly, keyword)
|
245 |
Dim files As New List(Of String)
|
246 |
Dim ProgramFiles As String = String.Format("{0}/Program Files", drive.RootDirectory.FullName)
|
247 |
|
248 |
If FileSystem.DirectoryExists(ProgramFiles) Then
|
249 |
Call files.AddRange(BranchRule(ProgramFiles, keyword))
|
250 |
End If
|
251 |
|
252 |
Dim ProgramFilesX86 = String.Format("{0}/Program Files(x86)", drive.RootDirectory.FullName)
|
253 |
|
254 |
If FileSystem.DirectoryExists(ProgramFilesX86) Then
|
255 |
Call files.AddRange(BranchRule(ProgramFilesX86, keyword))
|
256 |
End If
|
257 |
|
258 |
Call files.AddRange(driveRoot)
|
259 |
Call files.AddRange(driveRoot.Select(Function(rootDir) BranchRule(rootDir, keyword)).Unlist)
|
260 |
|
261 |
Return files.ToArray
|
262 |
End Function
|
263 |
|
264 |
|
265 |
|
266 |
|
267 |
|
268 |
|
269 |
|
270 |
|
271 |
|
272 |
<ExportAPI("File.Search.Program")>
|
273 |
<Description("Invoke the search session for the program file using a specific keyword string value.")>
|
274 |
Public Shared Function SearchProgram(dir$, keyword$, Optional includeDll As Boolean = True) As IEnumerable(Of String)
|
275 |
Dim exeNameRule As String = $"*{keyword}*.exe"
|
276 |
Dim dllNameRule As String = $"*{keyword}*.dll"
|
277 |
Dim rules$()
|
278 |
|
279 |
If includeDll Then
|
280 |
rules = {exeNameRule, dllNameRule}
|
281 |
Else
|
282 |
rules = {exeNameRule}
|
283 |
End If
|
284 |
|
285 |
Return searchImpl(dir, rules)
|
286 |
End Function
|
287 |
#End Region
|
288 |
|
289 |
End Class
|
290 |
End Namespace
|