diff options
Diffstat (limited to 'src/WixToolset.Core/CommandLine/CommandLineParser.cs')
-rw-r--r-- | src/WixToolset.Core/CommandLine/CommandLineParser.cs | 514 |
1 files changed, 173 insertions, 341 deletions
diff --git a/src/WixToolset.Core/CommandLine/CommandLineParser.cs b/src/WixToolset.Core/CommandLine/CommandLineParser.cs index d0484e45..11e5751d 100644 --- a/src/WixToolset.Core/CommandLine/CommandLineParser.cs +++ b/src/WixToolset.Core/CommandLine/CommandLineParser.cs | |||
@@ -1,4 +1,4 @@ | |||
1 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | 1 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. |
2 | 2 | ||
3 | namespace WixToolset.Core.CommandLine | 3 | namespace WixToolset.Core.CommandLine |
4 | { | 4 | { |
@@ -6,437 +6,269 @@ namespace WixToolset.Core.CommandLine | |||
6 | using System.Collections.Generic; | 6 | using System.Collections.Generic; |
7 | using System.IO; | 7 | using System.IO; |
8 | using WixToolset.Data; | 8 | using WixToolset.Data; |
9 | using WixToolset.Extensibility; | ||
10 | using WixToolset.Extensibility.Data; | ||
11 | using WixToolset.Extensibility.Services; | 9 | using WixToolset.Extensibility.Services; |
12 | 10 | ||
13 | internal enum Commands | ||
14 | { | ||
15 | Unknown, | ||
16 | Build, | ||
17 | Preprocess, | ||
18 | Compile, | ||
19 | Link, | ||
20 | Bind, | ||
21 | } | ||
22 | |||
23 | internal class CommandLineParser : ICommandLineParser | 11 | internal class CommandLineParser : ICommandLineParser |
24 | { | 12 | { |
25 | private static readonly char[] BindPathSplit = { '=' }; | 13 | private const string ExpectedArgument = "expected argument"; |
26 | |||
27 | public CommandLineParser(IServiceProvider serviceProvider) | ||
28 | { | ||
29 | this.ServiceProvider = serviceProvider; | ||
30 | |||
31 | this.Messaging = this.ServiceProvider.GetService<IMessaging>(); | ||
32 | } | ||
33 | 14 | ||
34 | private IServiceProvider ServiceProvider { get; } | 15 | public string ErrorArgument { get; set; } |
35 | 16 | ||
36 | private IMessaging Messaging { get; set; } | 17 | private Queue<string> RemainingArguments { get; } |
37 | 18 | ||
38 | public IExtensionManager ExtensionManager { get; set; } | 19 | private IMessaging Messaging { get; } |
39 | 20 | ||
40 | public ICommandLineArguments Arguments { get; set; } | 21 | public CommandLineParser(IMessaging messaging, string[] arguments, string errorArgument) |
41 | 22 | { | |
42 | public static string ExpectedArgument { get; } = "expected argument"; | 23 | this.Messaging = messaging; |
43 | 24 | this.RemainingArguments = new Queue<string>(arguments); | |
44 | public string ActiveCommand { get; private set; } | 25 | this.ErrorArgument = errorArgument; |
26 | } | ||
45 | 27 | ||
46 | public bool ShowHelp { get; private set; } | 28 | public bool IsSwitch(string arg) |
29 | { | ||
30 | return !String.IsNullOrEmpty(arg) && ('/' == arg[0] || '-' == arg[0]); | ||
31 | } | ||
47 | 32 | ||
48 | public ICommandLineCommand ParseStandardCommandLine() | 33 | public string GetArgumentAsFilePathOrError(string argument, string fileType) |
49 | { | 34 | { |
50 | var context = this.ServiceProvider.GetService<ICommandLineContext>(); | 35 | if (!File.Exists(argument)) |
51 | context.ExtensionManager = this.ExtensionManager ?? this.ServiceProvider.GetService<IExtensionManager>(); | ||
52 | context.Arguments = this.Arguments; | ||
53 | |||
54 | var next = String.Empty; | ||
55 | |||
56 | var command = Commands.Unknown; | ||
57 | var showLogo = true; | ||
58 | var showVersion = false; | ||
59 | var outputFolder = String.Empty; | ||
60 | var outputFile = String.Empty; | ||
61 | var outputType = String.Empty; | ||
62 | var platformType = String.Empty; | ||
63 | var verbose = false; | ||
64 | var files = new List<string>(); | ||
65 | var defines = new List<string>(); | ||
66 | var includePaths = new List<string>(); | ||
67 | var locFiles = new List<string>(); | ||
68 | var libraryFiles = new List<string>(); | ||
69 | var suppressedWarnings = new List<int>(); | ||
70 | |||
71 | var bindFiles = false; | ||
72 | var bindPaths = new List<string>(); | ||
73 | |||
74 | var intermediateFolder = String.Empty; | ||
75 | |||
76 | var cabCachePath = String.Empty; | ||
77 | var cultures = new List<string>(); | ||
78 | var contentsFile = String.Empty; | ||
79 | var outputsFile = String.Empty; | ||
80 | var builtOutputsFile = String.Empty; | ||
81 | |||
82 | this.Parse(context, (cmdline, arg) => Enum.TryParse(arg, true, out command), (cmdline, parser, arg) => | ||
83 | { | 36 | { |
84 | if (parser.IsSwitch(arg)) | 37 | this.Messaging.Write(ErrorMessages.FileNotFound(null, argument, fileType)); |
85 | { | 38 | return null; |
86 | var parameter = arg.Substring(1); | 39 | } |
87 | switch (parameter.ToLowerInvariant()) | ||
88 | { | ||
89 | case "?": | ||
90 | case "h": | ||
91 | case "help": | ||
92 | cmdline.ShowHelp = true; | ||
93 | return true; | ||
94 | |||
95 | case "arch": | ||
96 | case "platform": | ||
97 | platformType = parser.GetNextArgumentOrError(arg); | ||
98 | return true; | ||
99 | |||
100 | case "bindfiles": | ||
101 | bindFiles = true; | ||
102 | return true; | ||
103 | |||
104 | case "bindpath": | ||
105 | parser.GetNextArgumentOrError(arg, bindPaths); | ||
106 | return true; | ||
107 | |||
108 | case "cc": | ||
109 | cabCachePath = parser.GetNextArgumentOrError(arg); | ||
110 | return true; | ||
111 | |||
112 | case "culture": | ||
113 | parser.GetNextArgumentOrError(arg, cultures); | ||
114 | return true; | ||
115 | case "contentsfile": | ||
116 | contentsFile = parser.GetNextArgumentAsFilePathOrError(arg); | ||
117 | return true; | ||
118 | case "outputsfile": | ||
119 | outputsFile = parser.GetNextArgumentAsFilePathOrError(arg); | ||
120 | return true; | ||
121 | case "builtoutputsfile": | ||
122 | builtOutputsFile = parser.GetNextArgumentAsFilePathOrError(arg); | ||
123 | return true; | ||
124 | |||
125 | case "d": | ||
126 | case "define": | ||
127 | parser.GetNextArgumentOrError(arg, defines); | ||
128 | return true; | ||
129 | |||
130 | case "i": | ||
131 | case "includepath": | ||
132 | parser.GetNextArgumentOrError(arg, includePaths); | ||
133 | return true; | ||
134 | |||
135 | case "intermediatefolder": | ||
136 | intermediateFolder = parser.GetNextArgumentAsDirectoryOrError(arg); | ||
137 | return true; | ||
138 | |||
139 | case "loc": | ||
140 | parser.GetNextArgumentAsFilePathOrError(arg, "localization files", locFiles); | ||
141 | return true; | ||
142 | |||
143 | case "lib": | ||
144 | parser.GetNextArgumentAsFilePathOrError(arg, "library files", libraryFiles); | ||
145 | return true; | ||
146 | |||
147 | case "o": | ||
148 | case "out": | ||
149 | outputFile = parser.GetNextArgumentAsFilePathOrError(arg); | ||
150 | return true; | ||
151 | |||
152 | case "outputtype": | ||
153 | outputType = parser.GetNextArgumentOrError(arg); | ||
154 | return true; | ||
155 | |||
156 | case "nologo": | ||
157 | showLogo = false; | ||
158 | return true; | ||
159 | |||
160 | case "v": | ||
161 | case "verbose": | ||
162 | verbose = true; | ||
163 | return true; | ||
164 | |||
165 | case "version": | ||
166 | case "-version": | ||
167 | showVersion = true; | ||
168 | return true; | ||
169 | |||
170 | case "sval": | ||
171 | // todo: implement | ||
172 | return true; | ||
173 | |||
174 | case "sw": | ||
175 | case "suppresswarning": | ||
176 | var warning = parser.GetNextArgumentOrError(arg); | ||
177 | if (!String.IsNullOrEmpty(warning)) | ||
178 | { | ||
179 | var warningNumber = Convert.ToInt32(warning); | ||
180 | this.Messaging.SuppressWarningMessage(warningNumber); | ||
181 | } | ||
182 | return true; | ||
183 | } | ||
184 | |||
185 | return false; | ||
186 | } | ||
187 | else | ||
188 | { | ||
189 | parser.GetArgumentAsFilePathOrError(arg, "source code", files); | ||
190 | return true; | ||
191 | } | ||
192 | }); | ||
193 | 40 | ||
194 | this.Messaging.ShowVerboseMessages = verbose; | 41 | return argument; |
42 | } | ||
195 | 43 | ||
196 | if (showVersion) | 44 | public void GetArgumentAsFilePathOrError(string argument, string fileType, IList<string> paths) |
45 | { | ||
46 | foreach (var path in this.GetFiles(argument, fileType)) | ||
197 | { | 47 | { |
198 | return new VersionCommand(); | 48 | paths.Add(path); |
199 | } | 49 | } |
50 | } | ||
200 | 51 | ||
201 | if (showLogo) | 52 | public string GetNextArgumentOrError(string commandLineSwitch) |
53 | { | ||
54 | if (this.TryGetNextNonSwitchArgumentOrError(out var argument)) | ||
202 | { | 55 | { |
203 | AppCommon.DisplayToolHeader(); | 56 | return argument; |
204 | } | 57 | } |
205 | 58 | ||
206 | if (this.ShowHelp) | 59 | this.Messaging.Write(ErrorMessages.ExpectedArgument(commandLineSwitch)); |
207 | { | 60 | return null; |
208 | return new HelpCommand(command); | 61 | } |
209 | } | ||
210 | 62 | ||
211 | switch (command) | 63 | public bool GetNextArgumentOrError(string commandLineSwitch, IList<string> args) |
212 | { | 64 | { |
213 | case Commands.Build: | 65 | if (this.TryGetNextNonSwitchArgumentOrError(out var arg)) |
214 | { | 66 | { |
215 | var sourceFiles = GatherSourceFiles(files, outputFolder); | 67 | args.Add(arg); |
216 | var variables = this.GatherPreprocessorVariables(defines); | 68 | return true; |
217 | var bindPathList = this.GatherBindPaths(bindPaths); | ||
218 | var filterCultures = CalculateFilterCultures(cultures); | ||
219 | var type = CalculateOutputType(outputType, outputFile); | ||
220 | var platform = CalculatePlatform(platformType); | ||
221 | return new BuildCommand(this.ServiceProvider, sourceFiles, variables, locFiles, libraryFiles, filterCultures, outputFile, type, platform, cabCachePath, bindFiles, bindPathList, includePaths, intermediateFolder, contentsFile, outputsFile, builtOutputsFile); | ||
222 | } | 69 | } |
223 | 70 | ||
224 | case Commands.Compile: | 71 | this.Messaging.Write(ErrorMessages.ExpectedArgument(commandLineSwitch)); |
72 | return false; | ||
73 | } | ||
74 | |||
75 | public string GetNextArgumentAsDirectoryOrError(string commandLineSwitch) | ||
76 | { | ||
77 | if (this.TryGetNextNonSwitchArgumentOrError(out var arg) && this.TryGetDirectory(commandLineSwitch, this.Messaging, arg, out var directory)) | ||
225 | { | 78 | { |
226 | var sourceFiles = GatherSourceFiles(files, outputFolder); | 79 | return directory; |
227 | var variables = this.GatherPreprocessorVariables(defines); | ||
228 | var platform = CalculatePlatform(platformType); | ||
229 | return new CompileCommand(this.ServiceProvider, sourceFiles, variables, platform); | ||
230 | } | ||
231 | } | 80 | } |
232 | 81 | ||
82 | this.Messaging.Write(ErrorMessages.ExpectedArgument(commandLineSwitch)); | ||
233 | return null; | 83 | return null; |
234 | } | 84 | } |
235 | 85 | ||
236 | private static IEnumerable<string> CalculateFilterCultures(List<string> cultures) | 86 | public bool GetNextArgumentAsDirectoryOrError(string commandLineSwitch, IList<string> directories) |
237 | { | 87 | { |
238 | var result = new List<string>(); | 88 | if (this.TryGetNextNonSwitchArgumentOrError(out var arg) && this.TryGetDirectory(commandLineSwitch, this.Messaging, arg, out var directory)) |
239 | |||
240 | if (cultures == null) | ||
241 | { | ||
242 | } | ||
243 | else if (cultures.Count == 1 && cultures[0].Equals("null", StringComparison.OrdinalIgnoreCase)) | ||
244 | { | 89 | { |
245 | // When null is used treat it as if cultures wasn't specified. This is | 90 | directories.Add(directory); |
246 | // needed for batching in the MSBuild task since MSBuild doesn't support | 91 | return true; |
247 | // empty items. | ||
248 | } | ||
249 | else | ||
250 | { | ||
251 | foreach (var culture in cultures) | ||
252 | { | ||
253 | // Neutral is different from null. For neutral we still want to do culture filtering. | ||
254 | // Set the culture to the empty string = identifier for the invariant culture. | ||
255 | var filter = (culture.Equals("neutral", StringComparison.OrdinalIgnoreCase)) ? String.Empty : culture; | ||
256 | result.Add(filter); | ||
257 | } | ||
258 | } | 92 | } |
259 | 93 | ||
260 | return result; | 94 | this.Messaging.Write(ErrorMessages.ExpectedArgument(commandLineSwitch)); |
95 | return false; | ||
261 | } | 96 | } |
262 | 97 | ||
263 | private static OutputType CalculateOutputType(string outputType, string outputFile) | 98 | public string GetNextArgumentAsFilePathOrError(string commandLineSwitch) |
264 | { | 99 | { |
265 | if (String.IsNullOrEmpty(outputType)) | 100 | if (this.TryGetNextNonSwitchArgumentOrError(out var arg) && this.TryGetFile(commandLineSwitch, arg, out var path)) |
266 | { | 101 | { |
267 | outputType = Path.GetExtension(outputFile); | 102 | return path; |
268 | } | 103 | } |
269 | 104 | ||
270 | switch (outputType.ToLowerInvariant()) | 105 | this.Messaging.Write(ErrorMessages.ExpectedArgument(commandLineSwitch)); |
271 | { | 106 | return null; |
272 | case "bundle": | 107 | } |
273 | case ".exe": | ||
274 | return OutputType.Bundle; | ||
275 | |||
276 | case "library": | ||
277 | case ".wixlib": | ||
278 | return OutputType.Library; | ||
279 | |||
280 | case "module": | ||
281 | case ".msm": | ||
282 | return OutputType.Module; | ||
283 | |||
284 | case "patch": | ||
285 | case ".msp": | ||
286 | return OutputType.Patch; | ||
287 | |||
288 | case ".pcp": | ||
289 | return OutputType.PatchCreation; | ||
290 | |||
291 | case "product": | ||
292 | case "package": | ||
293 | case ".msi": | ||
294 | return OutputType.Product; | ||
295 | 108 | ||
296 | case "transform": | 109 | public bool GetNextArgumentAsFilePathOrError(string commandLineSwitch, string fileType, IList<string> paths) |
297 | case ".mst": | 110 | { |
298 | return OutputType.Transform; | 111 | if (this.TryGetNextNonSwitchArgumentOrError(out var arg)) |
112 | { | ||
113 | foreach (var path in this.GetFiles(arg, fileType)) | ||
114 | { | ||
115 | paths.Add(path); | ||
116 | } | ||
299 | 117 | ||
300 | case "intermediatepostlink": | 118 | return true; |
301 | case ".wixipl": | ||
302 | return OutputType.IntermediatePostLink; | ||
303 | } | 119 | } |
304 | 120 | ||
305 | return OutputType.Unknown; | 121 | this.Messaging.Write(ErrorMessages.ExpectedArgument(commandLineSwitch)); |
122 | return false; | ||
306 | } | 123 | } |
307 | 124 | ||
308 | private static Platform CalculatePlatform(string platformType) | 125 | public bool TryGetNextSwitchOrArgument(out string arg) |
309 | { | 126 | { |
310 | return Enum.TryParse(platformType, true, out Platform platform) ? platform : Platform.X86; | 127 | return TryDequeue(this.RemainingArguments, out arg); |
311 | } | 128 | } |
312 | 129 | ||
313 | private ICommandLineParser Parse(ICommandLineContext context, Func<CommandLineParser, string, bool> parseCommand, Func<CommandLineParser, IParseCommandLine, string, bool> parseArgument) | 130 | private bool TryGetNextNonSwitchArgumentOrError(out string arg) |
314 | { | 131 | { |
315 | var extensions = this.ExtensionManager.Create<IExtensionCommandLine>(); | 132 | var result = this.TryGetNextSwitchOrArgument(out arg); |
316 | 133 | ||
317 | foreach (var extension in extensions) | 134 | if (!result && !this.IsSwitch(arg)) |
318 | { | 135 | { |
319 | extension.PreParse(context); | 136 | this.ErrorArgument = arg ?? CommandLineParser.ExpectedArgument; |
320 | } | 137 | } |
321 | 138 | ||
322 | var parser = context.Arguments.Parse(); | 139 | return result; |
323 | 140 | } | |
324 | while (!this.ShowHelp && | ||
325 | String.IsNullOrEmpty(parser.ErrorArgument) && | ||
326 | parser.TryGetNextSwitchOrArgument(out var arg)) | ||
327 | { | ||
328 | if (String.IsNullOrWhiteSpace(arg)) // skip blank arguments. | ||
329 | { | ||
330 | continue; | ||
331 | } | ||
332 | 141 | ||
333 | if (parser.IsSwitch(arg)) | 142 | private static bool IsValidArg(string arg) |
334 | { | 143 | { |
335 | if (!parseArgument(this, parser, arg) && | 144 | return !(String.IsNullOrEmpty(arg) || '/' == arg[0] || '-' == arg[0]); |
336 | !this.TryParseCommandLineArgumentWithExtension(arg, parser, extensions)) | 145 | } |
337 | { | ||
338 | parser.ErrorArgument = arg; | ||
339 | } | ||
340 | } | ||
341 | else if (String.IsNullOrEmpty(this.ActiveCommand) && parseCommand != null) // First non-switch must be the command, if commands are supported. | ||
342 | { | ||
343 | if (parseCommand(this, arg)) | ||
344 | { | ||
345 | this.ActiveCommand = arg; | ||
346 | } | ||
347 | else | ||
348 | { | ||
349 | parser.ErrorArgument = arg; | ||
350 | } | ||
351 | } | ||
352 | else if (!this.TryParseCommandLineArgumentWithExtension(arg, parser, extensions) && | ||
353 | !parseArgument(this, parser, arg)) | ||
354 | { | ||
355 | parser.ErrorArgument = arg; | ||
356 | } | ||
357 | } | ||
358 | 146 | ||
359 | foreach (var extension in extensions) | 147 | private static bool TryDequeue(Queue<string> q, out string arg) |
148 | { | ||
149 | if (q.Count > 0) | ||
360 | { | 150 | { |
361 | extension.PostParse(); | 151 | arg = q.Dequeue(); |
152 | return true; | ||
362 | } | 153 | } |
363 | 154 | ||
364 | return this; | 155 | arg = null; |
156 | return false; | ||
365 | } | 157 | } |
366 | 158 | ||
367 | private static IEnumerable<SourceFile> GatherSourceFiles(IEnumerable<string> sourceFiles, string intermediateDirectory) | 159 | private bool TryGetDirectory(string commandlineSwitch, IMessaging messageHandler, string arg, out string directory) |
368 | { | 160 | { |
369 | var files = new List<SourceFile>(); | 161 | directory = null; |
370 | 162 | ||
371 | foreach (var item in sourceFiles) | 163 | if (File.Exists(arg)) |
372 | { | 164 | { |
373 | var sourcePath = item; | 165 | this.Messaging.Write(ErrorMessages.ExpectedDirectoryGotFile(commandlineSwitch, arg)); |
374 | var outputPath = Path.Combine(intermediateDirectory, Path.GetFileNameWithoutExtension(sourcePath) + ".wir"); | 166 | return false; |
375 | |||
376 | files.Add(new SourceFile(sourcePath, outputPath)); | ||
377 | } | 167 | } |
378 | 168 | ||
379 | return files; | 169 | directory = this.VerifyPath(arg); |
170 | return directory != null; | ||
380 | } | 171 | } |
381 | 172 | ||
382 | private IDictionary<string, string> GatherPreprocessorVariables(IEnumerable<string> defineConstants) | 173 | private bool TryGetFile(string commandlineSwitch, string arg, out string path) |
383 | { | 174 | { |
384 | var variables = new Dictionary<string, string>(); | 175 | path = null; |
385 | 176 | ||
386 | foreach (var pair in defineConstants) | 177 | if (!IsValidArg(arg)) |
387 | { | 178 | { |
388 | var value = pair.Split(new[] { '=' }, 2); | 179 | this.Messaging.Write(ErrorMessages.FilePathRequired(commandlineSwitch)); |
389 | 180 | } | |
390 | if (variables.ContainsKey(value[0])) | 181 | else if (Directory.Exists(arg)) |
391 | { | 182 | { |
392 | this.Messaging.Write(ErrorMessages.DuplicateVariableDefinition(value[0], (1 == value.Length) ? String.Empty : value[1], variables[value[0]])); | 183 | this.Messaging.Write(ErrorMessages.ExpectedFileGotDirectory(commandlineSwitch, arg)); |
393 | continue; | 184 | } |
394 | } | 185 | else |
395 | 186 | { | |
396 | variables.Add(value[0], (1 == value.Length) ? String.Empty : value[1]); | 187 | path = this.VerifyPath(arg); |
397 | } | 188 | } |
398 | 189 | ||
399 | return variables; | 190 | return path != null; |
400 | } | 191 | } |
401 | 192 | ||
402 | private IEnumerable<BindPath> GatherBindPaths(IEnumerable<string> bindPaths) | 193 | /// <summary> |
194 | /// Get a set of files that possibly have a search pattern in the path (such as '*'). | ||
195 | /// </summary> | ||
196 | /// <param name="searchPath">Search path to find files in.</param> | ||
197 | /// <param name="fileType">Type of file; typically "Source".</param> | ||
198 | /// <returns>An array of files matching the search path.</returns> | ||
199 | /// <remarks> | ||
200 | /// This method is written in this verbose way because it needs to support ".." in the path. | ||
201 | /// It needs the directory path isolated from the file name in order to use Directory.GetFiles | ||
202 | /// or DirectoryInfo.GetFiles. The only way to get this directory path is manually since | ||
203 | /// Path.GetDirectoryName does not support ".." in the path. | ||
204 | /// </remarks> | ||
205 | /// <exception cref="WixFileNotFoundException">Throws WixFileNotFoundException if no file matching the pattern can be found.</exception> | ||
206 | private string[] GetFiles(string searchPath, string fileType) | ||
403 | { | 207 | { |
404 | var result = new List<BindPath>(); | 208 | if (null == searchPath) |
405 | |||
406 | foreach (var bindPath in bindPaths) | ||
407 | { | 209 | { |
408 | var bp = ParseBindPath(bindPath); | 210 | throw new ArgumentNullException(nameof(searchPath)); |
211 | } | ||
409 | 212 | ||
410 | if (File.Exists(bp.Path)) | 213 | // Convert alternate directory separators to the standard one. |
214 | var filePath = searchPath.Replace(Path.AltDirectorySeparatorChar, Path.DirectorySeparatorChar); | ||
215 | var lastSeparator = filePath.LastIndexOf(Path.DirectorySeparatorChar); | ||
216 | var files = new string[0]; | ||
217 | |||
218 | try | ||
219 | { | ||
220 | if (0 > lastSeparator) | ||
411 | { | 221 | { |
412 | this.Messaging.Write(ErrorMessages.ExpectedDirectoryGotFile("-bindpath", bp.Path)); | 222 | files = Directory.GetFiles(".", filePath); |
413 | } | 223 | } |
414 | else | 224 | else // found directory separator |
415 | { | 225 | { |
416 | result.Add(bp); | 226 | files = Directory.GetFiles(filePath.Substring(0, lastSeparator + 1), filePath.Substring(lastSeparator + 1)); |
417 | } | 227 | } |
418 | } | 228 | } |
229 | catch (DirectoryNotFoundException) | ||
230 | { | ||
231 | // Don't let this function throw the DirectoryNotFoundException. This exception | ||
232 | // occurs for non-existant directories and invalid characters in the searchPattern. | ||
233 | } | ||
234 | catch (ArgumentException) | ||
235 | { | ||
236 | // Don't let this function throw the ArgumentException. This exception | ||
237 | // occurs in certain situations such as when passing a malformed UNC path. | ||
238 | } | ||
239 | catch (IOException) | ||
240 | { | ||
241 | } | ||
419 | 242 | ||
420 | return result; | 243 | if (0 == files.Length) |
244 | { | ||
245 | this.Messaging.Write(ErrorMessages.FileNotFound(null, searchPath, fileType)); | ||
246 | } | ||
247 | |||
248 | return files; | ||
421 | } | 249 | } |
422 | 250 | ||
423 | private bool TryParseCommandLineArgumentWithExtension(string arg, IParseCommandLine parse, IEnumerable<IExtensionCommandLine> extensions) | 251 | private string VerifyPath(string path) |
424 | { | 252 | { |
425 | foreach (var extension in extensions) | 253 | string fullPath; |
254 | |||
255 | if (0 <= path.IndexOf('\"')) | ||
426 | { | 256 | { |
427 | if (extension.TryParseArgument(parse, arg)) | 257 | this.Messaging.Write(ErrorMessages.PathCannotContainQuote(path)); |
428 | { | 258 | return null; |
429 | return true; | ||
430 | } | ||
431 | } | 259 | } |
432 | 260 | ||
433 | return false; | 261 | try |
434 | } | 262 | { |
263 | fullPath = Path.GetFullPath(path); | ||
264 | } | ||
265 | catch (Exception e) | ||
266 | { | ||
267 | this.Messaging.Write(ErrorMessages.InvalidCommandLineFileName(path, e.Message)); | ||
268 | return null; | ||
269 | } | ||
435 | 270 | ||
436 | public static BindPath ParseBindPath(string bindPath) | 271 | return fullPath; |
437 | { | ||
438 | var namedPath = bindPath.Split(BindPathSplit, 2); | ||
439 | return (1 == namedPath.Length) ? new BindPath(namedPath[0]) : new BindPath(namedPath[0], namedPath[1]); | ||
440 | } | 272 | } |
441 | } | 273 | } |
442 | } | 274 | } |