Exemple #1
0
		static void Main(string[] args) {
			using(new ActivityTraceContext(ts, "Main")) {
				try {
					int top = Console.CursorTop; Console.CursorTop = 1; Console.CursorTop = top; hasConsole = true;
					ts.TraceInformation("Console Curser positioning possible");
				} catch(Exception) {
					switches |= eSwitches.SupressProgress; hasConsole = false;
					ts.TraceInformation("Console Curser positioning not possible");
				}

				ts.TraceInformation("Adding console output filter (Suppress bell characters)");
				var consoleIn = Console.In;
				Console.SetOut(new ConsoleOutFilter(Console.Out));

				if((switches & eSwitches.UseUTF8OutputStream) != 0) Console.OutputEncoding = new UTF8Encoding();


				Thread.CurrentThread.CurrentCulture = CultureInfo.InvariantCulture;
				AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(GlobalExceptionHandler);


#if(!PublicRelease)
				if(args.Length == 0) SetArguments(out args);
#endif
				ts.TraceInformation("Parse commandline Arguments");
				if(!ParseArgs(args)) return;

				ts.TraceInformation("Run self check");
				if(!SelfCheck()) return;

				if((switches & eSwitches.HashingSpeedTest) != 0) { Benchmark(); return; }

				ts.TraceInformation("Process Media");
				ProcessMedia(new List<string>(mediaLst));

				if((switches & eSwitches.MonitorFolder) != 0) MonitorFiles();

#if(HasACreq)
				if(anidb != null) {
					ts.TraceInformation("Wait until all ACReqs are sent before terminating");
					while(anidb.UnsentQueryCount != 0) {
						Console.WriteLine("ACReq( Done: " + sentACReqs + " Todo: 0 Failed: " + failedACReqs + " Pending: " + anidb.UnsentQueryCount + " )");
						if(hasConsole) Console.SetCursorPosition(0, Console.CursorTop - 1);
						Thread.Sleep(200);
					}
					Console.WriteLine("ACReq( Done: " + sentACReqs + " Todo: 0 Failed: " + failedACReqs + " Pending: 0 )");
					anidb.Stop();
					anidb.Join();
					ts.TraceInformation("All ACReqs sent");
				}
#endif

				if((switches & eSwitches.PauseWhenDone) != 0) { Console.WriteLine("Press any alpha-numeric key to continue"); Pause(); }
			}

		}
Exemple #2
0
		private static CLManagement CreateCLArgParser() {
			using(new ActivityTraceContext(ts, "CreateCLArgParser")) {
				CLManagement clArgManagement = new CLManagement();

				//Action<string, string, object> handler = (nameSpace, argName, param) => Console.WriteLine(nameSpace + "." + argName + (param != null ? "=" + param : ""));
				//Func<string, object> transformer = ldParam => ldParam;

				Func<string, object> splitParams = (param) => param.Split(new char[] { ':' }, 2);

				Func<string, object> parseHost = (param) => {
					for(int i = 0;i < 5;i++) try { return new IPEndPoint(Dns.GetHostAddresses(param.Split(':')[0]).First(), int.Parse(param.Split(':')[1])); } catch(Exception) { }
					throw new Exception("Couldn't resolve host");
				};

				Func<string, object> toInt = (ldParam) => int.Parse(ldParam);

				Func<string, object> pathParam = (ldParam) => {
					var path = Path.IsPathRooted(ldParam) ? ldParam : Path.Combine(CurrentDirectory, ldParam);
					if(!Directory.Exists(Path.GetDirectoryName(path))) Directory.CreateDirectory(Path.GetDirectoryName(path));
					//if(!File.Exists(path)) File.Create(path).Close();
					return path;
				};

				Func<string, int, int, int> between = (value, min, max) => Math.Max(Math.Min((int)toInt(value), max), min);

				#region ACReq
				ts.TraceInformation("Registering ACReq ArgGroup");
				clArgManagement.RegisterArgGroup(new ArgGroup("ACReq",
					"Updates meta info of an existing file entry on AniDB",
					(nameSpace, argName, argParam) => {
						switch(argName) {
							case "Authentication": username = ((string[])argParam)[0]; password = ((string[])argParam)[1]; switches |= eSwitches.UseACreqHashes; break;
							case "HostEndPoint": hostAddress = (string)((object[])argParam)[0]; hostPort = (int)((object[])argParam)[1]; break;
							case "LocalPort": localPort = (int)argParam; break;
							case "TimeOut": timeout = ((int[])argParam)[0]; retries = ((int[])argParam)[1]; break;
						}
					},
					new ArgStructure("Authentication", "Auth", null,
						splitParams,
						"--Auth=<username>:<api_key>",
						"Enables ACReqing when valid credentials are provided.\nAlso enables error Reporting! (Add -noerr to disable)\nVisit anidb.net/perl-bin/animedb.pl?show=profile (Account Tab) to set key"
					),
					new ArgStructure("HostEndPoint", "Host", null,
						(ldParams) => ((string[])splitParams(ldParams)).Select((ldParam, i) => i == 0 ? ldParam : toInt(ldParam)).ToArray(),
					//parseHost,
						"--Host=<hostname>:<hostport>",
						"Change endpoint of AniDB UDP API server"
					),
					new ArgStructure("LocalPort", "LPort", null,
						toInt,
						"--LPort=<localport>",
						"Local UDP port used for ACReqing"
					),
					new ArgStructure("TimeOut", "TOut", null,
						(ldParams) => ((string[])splitParams(ldParams)).Select(ldParam => (int)toInt(ldParam)).ToArray(),
						"--TOut=<seconds>:<retries>",
						"Sets the retry count and the timeout before resending the dump"
					)
				));
				#endregion

				#region Logging
				ts.TraceInformation("Registering Logging ArgGroup");
				clArgManagement.RegisterArgGroup(new ArgGroup("Logging",
					"",
					(nameSpace, argName, argParam) => {
						switch(argName) {
							case "ACReqError": acErrListPath = (string)argParam; break;
							case "CRCError": crcMismatchListPath = (string)argParam; switches |= eSwitches.Crc; break;
							case "ExtensionDifference": extDiffListPath = (string)argParam; break;
							case "FixExtensions": extFixPath = (string)argParam; break;
							case "DoneLog": doneListPath = (string)argParam; if(File.Exists(doneListPath)) doneListContent = new List<string>(File.ReadAllLines(doneListPath).OrderBy(ldPath => ldPath)); break;
							case "HashLog": hashListPath = ((string[])argParam)[1]; hashLogStyle = ((string[])argParam)[0]; break;
							case "LogFile": logPath = (string)argParam; break;
						}
					},
					new ArgStructure("ACReqError", "ACErr", null, pathParam, "--ACErr=acerr.txt", "Log file paths of failed dumps to file"),
					new ArgStructure("CRCError", "CRCErr", null, pathParam, "--CRCErr=crcerr.txt", "Logs the filepath if the calculated CRC is not contained in the filename"),
					new ArgStructure("ExtensionDifference", "ExtDiff", null, pathParam, "--ExtDiff=extdiff.txt", "Logs the filepath if the detected Extension does not match the actual extension"),
					new ArgStructure("FixExtensions", "FixExt", null, pathParam, "--FixExt=extfix.txt", "Changes the fileextension to the dectected extension and logs the action"),
					new ArgStructure("DoneLog", "Done", null, pathParam, "--Done=done.txt", "Skip paths present in the log and appends paths to newly processed files"),
					new ArgStructure("HashLog", "HLog", null,
						(ldParams) => ((string[])splitParams(ldParams)).Select((ldParam, i) => i == 0 ? ldParam : (string)pathParam(ldParam)).ToArray(),
						"--HLog=<Format>:hlog.txt",
						"Appends lines for each processed file to the specified file in a custom format.\nFormat: $HashName$ is replaced with the calculated hash. Hash must be enabled.\nFormat may not contain colons."
					),
					new ArgStructure("LogFile", "Log", null, pathParam, "--Log=log.txt", "Any enabled reports (See Report Namespace) will be appended to this file")
				));
				#endregion

				#region Report
				ts.TraceInformation("Registering Report ArgGroup");
				clArgManagement.RegisterArgGroup(new ArgGroup("Report",
					"",
					(nameSpace, argName, argParam) => {
						switch(argName) {
							case "MediaInfoTxtDump": switches |= eSwitches.MediaInfoOutPut; break;
							case "MediaInfoXmlDump": switches |= eSwitches.MediaInfoXMLOutPut; break;
							case "SimpleTxtFormat": switches |= eSwitches.TxtFormat; break;
							case "CreqFormat": switches |= eSwitches.CreqXmlFormat; break;
							case "AVD2Format": switches |= eSwitches.NewCreqXmlFormat; break;
							case "HashDump": switches |= eSwitches.HashOutput; break;
						}
					},
					new ArgStructure("MediaInfoTxtDump", "", 'M', null, "", ""),
					new ArgStructure("MediaInfoXmlDump", "", 'm', null, "", ""),
					new ArgStructure("SimpleTxtFormat", "", 't', null, "", ""),
					new ArgStructure("CreqFormat", "", 'C', null, "", ""),
					new ArgStructure("AVD2Format", "", 'c', null, "", ""),
					new ArgStructure("HashDump", "", 'h', null, "", "")
				));
				#endregion

				#region Control
				ts.TraceInformation("Registering Control ArgGroup");
				clArgManagement.RegisterArgGroup(new ArgGroup("Control",
					"",
					(nameSpace, argName, argParam) => {
						switch(argName) {
							case "RetryOnIOException": retriesOnIOException = (int)argParam; break;
							case "BlockSize": blockSize = ((int[])argParam)[0]; blockCount = ((int[])argParam)[1]; break;
							case "ExtensionList": processExtensions = (HashSet<string>)argParam; break;
							case "MonitorFolders": monitorSleepDuration = (int)argParam * 1000; switches |= eSwitches.MonitorFolder; break;
							case "NoRecurse": switches |= eSwitches.ExcludeSubFolders; break;
							case "PauseWhenDone": switches |= eSwitches.PauseWhenDone; break;
							case "PauseAfterFile": switches |= eSwitches.PauseWhenFileDone; break;
							case "Randomize": switches |= eSwitches.RandomFileOrder; break;
							case "Quiet": switches |= eSwitches.SupressProgress; break;
							case "Delete": switches |= eSwitches.DeleteFileWhenDone; break;
							case "RenameFile": break;
							case "DoneLogFileNameOnly": switches |= eSwitches.DoneLogFilenameOnly; break;
							case "Benchmark": switches |= eSwitches.HashingSpeedTest; break;
							case "UseUtf8": switches |= eSwitches.UseUTF8OutputStream; break;
							case "UseCWD": switches |= eSwitches.UseCWD; break;
							case "Debug": debugPath = (string)argParam; break;
						}
					},
					new ArgStructure("BlockSize", "BSize", null,
						(ldParams) => ((string[])splitParams(ldParams)).Select((ldParam, i) => between(ldParam, i == 0 ? 512 : 1, i == 0 ? 64 * 1024 : 64)).ToArray(),
						"--BSize=<blocksize in kb>:<block count>",
						"Circular buffer size for hashing"
					),
					new ArgStructure("ExtensionList", "Ext", null,
						ldParam => {
							var exts = ldParam.ToLower().Split(',');
							if(exts.Length == 1 && exts[0].Equals("*")) return null;
							if(exts.Any(str => str.StartsWith("-")) && !exts.All(str => str.StartsWith("-"))) throw new Exception("Inclusive and exclusive extensions cannot be mixed");
							return new HashSet<string>(exts[0][0] == '-' ? processExtensions.Except(exts.Select(ldExt => ldExt.Substring(1))) : exts);
						},
						"--Ext=avi,mkv OR --Ext=-zip,-rar OR --Ext=*", ""
					),
					new ArgStructure("MonitorFolders", "Mon", null, toInt, "--Mon=3600", "Processes the given paths again after the specified idletime (seconds)"),
					new ArgStructure("NoErrorReporting", "NoErr", null, null, "", "Disables exception reporting\nBy default an exception report is sent to AniDB if there is one.\nIt does not contain any private information.\nThis greatly helps discovering bugs."),
					new ArgStructure("NoRecurse", "", 'R', null, "", "Do _not_ recurse into subfolders"),
					new ArgStructure("DoneLogFileNameOnly", "", 'R', null, "", "Use only the filename for Donelog comparsion"),
					new ArgStructure("PauseWhenDone", "", 'p', null, "", ""),
					new ArgStructure("RetryOnIOException", "", null, toInt, "--RetryOnIOException=3", "Retries processing files which have failed with an IOException"),
					new ArgStructure("PauseAfterFile", "", 'P', null, "", ""),
					new ArgStructure("Randomize", "", 'r', null, "", ""),
					new ArgStructure("Quiet", "", 'q', null, "", ""),
					new ArgStructure("Delete", "", null, null, "", ""),
					//new ArgStructure("RenameFile", "Rename", null, null, "--Rename=Format.cs", "After processing, the file is renamed to result of the userdefined function\nThe function is run a new AppDomain with minimal trust."),
					new ArgStructure("Benchmark", "", 'B', null, "", "Used in conjunction with the hash args\nAdd one file to the args to test read speed."),
					new ArgStructure("UseCWD", "", null, null, "", "Use the current working directoy for file output"),
					new ArgStructure("UseUtf8", "", 'U', null, "", ""),
					new ArgStructure("Debug", "", null, pathParam, "", "")
				));
				#endregion

				#region Hashing
				ts.TraceInformation("Registering Hashing ArgGroup");
				clArgManagement.RegisterArgGroup(new ArgGroup("Hashing",
					"",
					(nameSpace, argName, argParam) => {
						switch(argName) {
							case "CRC32": switches |= eSwitches.Crc; break;
							case "SHA1": switches |= eSwitches.Sha1; break;
							case "ED2K": switches |= eSwitches.Ed2k; break;
							case "TIGER": switches |= eSwitches.Tiger; break;
							case "MD4": switches |= eSwitches.Md4; break;
							case "MD5": switches |= eSwitches.Md5; break;
							case "TTH": switches |= eSwitches.Tth; break;
							case "AllHashes": switches |= eSwitches.UseAllHashes; break;
						}
					},
					new ArgStructure("CRC32", "", '0', null, "", ""),
					new ArgStructure("SHA1", "", '1', null, "", ""),
					new ArgStructure("ED2K", "", '2', null, "", ""),
					new ArgStructure("TIGER", "", '3', null, "", ""),
					new ArgStructure("MD4", "", '4', null, "", ""),
					new ArgStructure("MD5", "", '5', null, "", ""),
					new ArgStructure("TTH", "", '6', null, "", ""),
					new ArgStructure("AllHashes", "", 'a', null, "", "")
				));
				#endregion

				#region AniDB
				ts.TraceInformation("Registering AniDB ArgGroup");
				clArgManagement.RegisterArgGroup(new ArgGroup("AniDB",
					"",
					(nameSpace, argName, argParam) => {
						switches |= eSwitches.Ed2k;
						switch(argName) {
							case "ExportEd2kLinks": ed2kListPath = (string)argParam; break;
							case "PrintEd2kLink": switches |= eSwitches.PrintEd2kLink; break;
							case "PrintAniDBLink": switches |= eSwitches.PrintAniDBLink; break;
							case "OpenAniDBLink": switches |= eSwitches.OpenInBrowser; break;
						}
					},
					new ArgStructure("ExportEd2kLinks", "Exp", null, pathParam, "--Exp=ed2k.txt", ""),
					new ArgStructure("PrintEd2kLink", "", null, null, "", ""),
					new ArgStructure("PrintAniDBLink", "", null, null, "", ""),
					new ArgStructure("OpenAniDBLink", "", null, null, "", "")
				));
				#endregion

				clArgManagement.SetUnnamedParamHandler(param => mediaLst.Add(param));

				return clArgManagement;
			}
		}
Exemple #3
0
		private static bool ParseArgs(string[] args) {
			using(new ActivityTraceContext(ts, "ParseArgs")) {
				bool triedOldCmd = false;

			tryOldCmd:
				try {
					ts.TraceInformation("Creating Arg Parser");
					var clArgParser = CreateCLArgParser();
					if(args.Length == 0 || args.All(ldArg => ldArg.Trim().Equals(string.Empty))) {
						Console.WriteLine("Help:    http://wiki.anidb.info/w/Avdump2");
						Console.WriteLine("Version: " + appVersion);
						Console.WriteLine("Usage:   AVDump2CL.exe [--options] <file/folder> [<file/folder> ...]");
						Console.WriteLine();

						clArgParser.PrintHelp(false);
						Console.WriteLine("For a quickstart use \"AVDump2CL.exe --Auth=<UserName>:<APIKey> <Path>\"");
						Console.WriteLine("Visit anidb.net/perl-bin/animedb.pl?show=profile (Account Tab) to set key");
						Console.ReadKey();
						return false;
					}

					ts.TraceInformation("Parsing Args");
					if(!clArgParser.ParseArgs(args)) return false;

					var uselessCombination = true;
					if((switches & (eSwitches.UseAllHashes | eSwitches.HashingSpeedTest)) != 0) uselessCombination = false;
					if(logPath != null && (switches & (eSwitches.CreqXmlFormat | eSwitches.MediaInfoOutPut | eSwitches.MediaInfoXMLOutPut | eSwitches.NewCreqXmlFormat | eSwitches.TxtFormat | eSwitches.HashOutput)) == 0) switches |= eSwitches.CreqXmlFormat;
					if((switches & (eSwitches.CreqXmlFormat | eSwitches.MediaInfoOutPut | eSwitches.MediaInfoXMLOutPut | eSwitches.NewCreqXmlFormat | eSwitches.TxtFormat | eSwitches.HashOutput)) != 0) uselessCombination = false;

					if(uselessCombination) {
						ts.TraceInformation("Combination of arguments is invalid (Nothing to do)");
						ColoredWriteLine(ConsoleColor.Red, "Combination of arguments is invalid (Nothing to do)", true);
						Pause(true);
						return false;
					}

				} catch(Exception ex) {

					if(!triedOldCmd && ConvertOldArgs(ref args)) {
						ts.TraceEvent(TraceEventType.Warning, 0, "Falling back to old arg format");

						triedOldCmd = true;
						goto tryOldCmd; //Well, Sue me 
					} else {
						ts.TraceEvent(TraceEventType.Warning, 0, "Couldn't parse args.");

						ColoredWriteLine(ConsoleColor.Red, "Error while interpreting commandline arguments", true);
						ColoredWriteLine(ConsoleColor.Red, ex.Message + (ex.InnerException != null ? "\n" + ex.InnerException.Message : ""), true);
						Console.WriteLine("Press any alpha-numeric key to continue");
						Pause(true);
						return false;
					}
				}

				if(triedOldCmd) {
					ColoredWriteLine(ConsoleColor.Red, "Please update your command line arguments. Refer to --Help");
					ColoredWriteLine(ConsoleColor.Red, "Converted Args: " + string.Join(" ", args
						.Where(ldArg => ldArg.StartsWith("-"))
						.Select(ldArg => ldArg.Contains(" ") && ldArg.Contains("=") ? ldArg.Substring(0, ldArg.IndexOf('=')) + "=\"" + ldArg.Substring(ldArg.IndexOf('=') + 1) + "\"" : ldArg)
						.ToArray()
					));
					Thread.Sleep(1000);
				}


				return true;
			}
		}