/// ======================================================================================================= public static void ShowReport(AutoReport auto_report, double y_scale = 0.1) { FormAccess(FormDelegates.FormClose, null, "Report"); int reportwidth = (int)(0.5 * ScreenXy().X); Status autostatus = auto_report.CalculatedAutoResult(); GroupBox autogroup = GetGroupBox(auto_report.AutoSummary(), autostatus, min_width: (reportwidth - 25)); FlowLayoutPanel flpauto = GetFlowPanel(); foreach (BatchReport batchreport in auto_report.BatchReports.Values) { FlowLayoutPanel flpbatch = GetFlowPanel(auto_scroll: false); Status batchstatus = batchreport.ResultStatus; GroupBox batchgroup = GetGroupBox(batchreport.Summary(), batchstatus, min_width: (reportwidth - 35)); // Add batch decription as first label foreach (CommandReport commandreport in batchreport.CommandReports.Values) { string commanddetail = "[" + IndexLetter(commandreport.CommandMap.C) + "]" + (commandreport.CommandMap.D == 0 ? " " : "#" + commandreport.CommandMap.D + " ") + commandreport.Description + " " + commandreport.StartTime + " " + commandreport.Duration() + " " + commandreport.ResultStatus; flpbatch.Controls.Add(GetLabel(commanddetail, commandreport.ResultStatus, max_width: (reportwidth - 35))); // Charts - design decision to perform frequency time graph split to keep aligned if (commandreport.Charts.Count > 0) { GroupBox chartgroup = GetGroupBox("chart" + batchreport.Summary(), Status.BUSY); foreach (List <ChartData> charts in commandreport.Charts) { //int tracknumber = 0; foreach (ChartData chart in charts) { flpbatch.Controls.Add(Graph.Milliseconds(chart, chart.Name, 150, y_scale, reportwidth - 65)); } } } // Messages foreach (Msg message in commandreport.Messages) { flpbatch.Controls.Add(GetLabel(message.Text, message.ResultStatus)); } } flpbatch.Controls.Add(GetLabel(batchstatus == Status.PASS ? ":)" : ":(", batchstatus)); batchgroup.Controls.Add(flpbatch); flpauto.Controls.Add(batchgroup); } autogroup.Controls.Add(flpauto); CustomForm form = new CustomForm("Report", "Report for " + auto_report.Alias, autogroup, Side.Right); new Thread(() => Application.Run(form)).Start(); }
/// ======================================================================================================= static Checker GetChecker(AutoReport auto_report, Map map, string command_check) { string check = null; string checktype = null; string checkfunction = null; List <string> checkparameters = null; if (command_check.Split('=').Length > 1) { check = command_check.Split('=')[command_check.Split('=').Length - 1]; if (command_check.Split('.').Length != 2 || !Regex.IsMatch(command_check.Split('.')[1], FUNC_FORMAT + PARAM_FORMAT)) { if (auto_report != null) { auto_report.AddOverlayedMessage(map, "Check '" + command_check + "' is invalid", Status.FAIL); } throw new Exception("Check '" + command_check + "' is invalid"); } else { checktype = check.Split('.')[0]; if (PropertyNames <Return>().Contains(checktype)) { if (auto_report != null) { auto_report.AddOverlayedMessage(map, "Check type '" + checktype + "' is invalid", Status.FAIL); } return(null); } checkfunction = ExtractCheckFunction(check); if (!new[] { "Contain", "Contains", "Equal", "Equals", "Number", "Numbers" }.Contains(checktype)) { if (auto_report != null) { auto_report.AddOverlayedMessage(map, "Check function '" + checkfunction + "' is invalid", Status.FAIL); } throw new Exception("Check function '" + checkfunction + "' is invalid"); } checkparameters = ExtractParameters(checkfunction); if (checkparameters == null) { if (auto_report != null) { auto_report.AddOverlayedMessage(map, "Check parameter(s) '" + checkfunction + "' is/are invalid", Status.FAIL); } throw new Exception("Check parameter(s) '" + checkfunction + "' is invalid"); } return(new Checker(checktype, checkfunction, checkparameters)); } } return(null); // no checker specified }
/// ======================================================================================================= private static void RunAuto(AutoReport auto_report, string auto_alias, string binary_name, out List <Control> interactive_controls) { List <Control> interactivecontrols = new List <Control>(); DataGridView autodata = Data.BlankDgv((int)CAT.AutoFields.NumberOfColumns); DataGridView batchdata = Data.BlankDgv((int)CAT.BatchFields.NumberOfColumns); string binary_path = DISK.AutoAddBaseDirectory(auto_alias + @"\" + binary_name); Data.LoadDataGrid(binary_path, ref autodata); FormAccess(FormDelegates.LoadAutoData, null, auto_alias); FormAccess(FormDelegates.ClearAutoStatuses, new object[] { }, auto_alias); foreach (DataGridViewRow autorow in autodata.Rows) { if (autorow.Index < autodata.RowCount - 1) { if (!AbortAll) { Data.LoadDataGrid(new FileInfo(binary_path).Directory.FullName + @"\batch" + autorow.Index + ".bin", ref batchdata); Action runbatch = new Action(() => { List <Control> ctrls; RunBatch(auto_report, auto_alias, autorow.Index, autodata, batchdata, out ctrls); if (ctrls != null) { foreach (Control ctrl in ctrls) { interactivecontrols.Add(ctrl); } } }); if (Regex.IsMatch(Data.GetCell(autodata, (int)CAT.AutoFields.Mode, autorow.Index), "-t")) { Task t = new Task(() => { runbatch(); }); AutoTasks.Add(t); t.Start(); } else { runbatch(); } } else { FormAccess(FormDelegates.SetBatchStatus, new object[] { Status.ABORT, autorow.Index }, auto_alias); } } } CAT.FormAccess(CAT.FormDelegates.SaveAuto, new object[] { }, auto_alias); interactive_controls = interactivecontrols; }
/// ======================================================================================================= public static void InteractiveShowReport(Func <Return> returndatafunction, double y_scale) { CAT.FormAccess(CAT.FormDelegates.FormClose, null, "Report"); AutoReport autoreport = new AutoReport(CAT.InteractiveControlsFormName); Map map = new Map(CAT.InteractiveControlsFormName, 0, 0); try { DateTime start = DateTime.Now; bool complete = false; InteractiveAddNamedOverlay("InteractiveProgress", "Started", Status.BUSY); new Thread(() => { while (!complete) { InteractiveUpdateNamedOverlay("InteractiveProgress", "Processing " + (DateTime.Now - start).TotalMilliseconds + "ms", Status.BUSY); Thread.Sleep(10); } InteractiveUpdateNamedOverlay("InteractiveProgress", "Complete " + (DateTime.Now - start).TotalMilliseconds + "ms", Status.PASS); }).Start(); autoreport.AddBatch(new BatchReport(0, "Batch")); autoreport.AddCommand(new CommandReport(map, "Command")); Return returndata = returndatafunction(); if (returndata.Charts != null) { autoreport.AddChartList(map, returndata.Charts); } if (returndata.Messages != null) { foreach (CATMessage msg in returndata.Messages) { autoreport.AddOverlayedMessage(map, msg.Text, msg.Status); } } autoreport.CommandComplete(map, CAT.Status.PASS); autoreport.BatchComplete(0); autoreport.AutoComplete(); CAT.ShowReport(autoreport, y_scale); complete = true; } catch (Exception ex) { InteractiveUpdateNamedOverlay("InteractiveProgress", "Failed control", Status.PASS); autoreport.AddOverlayedMessage(map, CAT.ErrorMsg(ex), CAT.Status.FAIL); try { CAT.ShowReport(autoreport, y_scale); } catch { } } }
/// ======================================================================================================= public static bool Run(string auto_alias, string binary_name, string number = null, bool new_form = false) { int commandnumber = Convert.ToInt32(number); int batchnumber = 0; // Default AutoReport autoreport = new AutoReport(auto_alias); // Always something to report autoreport.Enabled = (bool)FormAccess(FormDelegates.ReportEnabled, null, auto_alias); List <Control> interactivecontrols = new List <Control>(); if (!Running) // Not allowed to run while running { string autovars = (string)FormAccess(FormDelegates.GetAutoVars, null, auto_alias); if (!autovars.Contains(COMMAND_MODE_DIRTY_RUN)) { CleanRun(auto_alias); } AutoTasks = new List <Task>(); BatchTasks = new List <Task>(); CommandTasks = new List <Task>(); Running = true; RunMode = RunType.Command; string binary_path = DISK.AutoAddBaseDirectory(auto_alias + @"\" + binary_name); DataGridView batchdata = Data.BlankDgv((int)CAT.BatchFields.NumberOfColumns); DataGridView autodata = Data.BlankDgv((int)CAT.AutoFields.NumberOfColumns); if (File.Exists(binary_path)) { if (Regex.IsMatch(binary_path, "auto.bin")) { Data.LoadDataGrid(binary_path, ref autodata); RunMode = number == null ? RunType.Auto : RunType.Batch; if (RunMode == RunType.Batch) { Data.LoadDataGrid(new FileInfo(binary_path).Directory.FullName + @"\batch" + number + ".bin", ref batchdata); } } else if (Regex.IsMatch(binary_path, @"batch\d*.bin")) { Data.LoadDataGrid(new FileInfo(binary_path).Directory.FullName + @"\auto.bin", ref autodata); RunMode = number == null ? RunType.Batch : RunType.Command; Data.LoadDataGrid(binary_path, ref batchdata); string subvalue = Regex.Match(binary_path, @"batch\d*.bin").Value; string newvalue = Regex.Match(subvalue, @"[0-9]+").Value; batchnumber = Convert.ToInt32(newvalue); } else { Running = false; throw new Exception("Binary " + binary_path + " is invalid - thus did not start automation"); } } else { Running = false; throw new Exception("Binary " + binary_path + " does not exist - thus did not start automation"); } switch (RunMode) { case RunType.Command: if (Regex.IsMatch(Data.GetCell(batchdata, (int)CAT.BatchFields.Mode, commandnumber), "-nr")) { autoreport.Enabled = false; } autoreport.AddBatch(new BatchReport(batchnumber, Data.GetCell(autodata, (int)CAT.AutoFields.Name, batchnumber))); RunCommand(autoreport, new Map(auto_alias, batchnumber, commandnumber), batchdata, out interactivecontrols, GetAutoVars(autodata, batchnumber, auto_alias)); autoreport.WaitForBatch(batchnumber); Running = false; break; case RunType.Batch: if (Regex.IsMatch(Data.GetCell(autodata, (int)CAT.AutoFields.Mode, batchnumber), "-nr")) { autoreport.Enabled = false; } RunBatch(autoreport, auto_alias, batchnumber, autodata, batchdata, out interactivecontrols); Running = false; break; case RunType.Auto: RunAuto(autoreport, auto_alias, binary_name, out interactivecontrols); Running = false; break; } autoreport.WaitForAuto(); if (autoreport.Enabled) { ShowReport(autoreport); } if (interactivecontrols != null && interactivecontrols.Count > 0) { InteractiveShowControls(interactivecontrols); } return(true); } else { autoreport.AddOverlay("Busy running automation - thus did not start new automation - please wait (or click abort then retry run)...", Status.BUSY); return(false); } }
/// ======================================================================================================= private static void RunBatch(AutoReport auto_report, string auto_alias, int batch_number, DataGridView auto_data, DataGridView batch_data, out List <Control> interactive_controls, int?command_number = null) { List <Control> interactivecontrols = new List <Control>(); int rep = 1; if (Regex.IsMatch(Data.GetCell(auto_data, (int)CAT.AutoFields.Mode, batch_number), COMMAND_MODE_REPEAT)) { rep = Convert.ToInt16(Regex.Match(Data.GetCell(auto_data, (int)CAT.AutoFields.Mode, batch_number), COMMAND_MODE_REPEAT).Value.Substring(1)); } for (int i = 0; i < rep; i++) { Action runbatch = new Action(() => { FormAccess(FormDelegates.SelectAutoRow, new object[] { batch_number }, auto_alias); FormAccess(FormDelegates.LoadBatchData, new object[] { batch_number }, auto_alias); FormAccess(FormDelegates.ClearBatchStatuses, new object[] { }, auto_alias); auto_report.AddBatch(new BatchReport(batch_number, Data.GetCell(auto_data, (int)CAT.AutoFields.Name, batch_number))); Status?status = null; if (Data.IsBatchEnabled(auto_data, batch_number) || command_number != null) { CAT.FormAccess(CAT.FormDelegates.SetBatchStatus, new object[] { Status.BUSY, batch_number }, auto_alias); foreach (DataGridViewRow commandrow in batch_data.Rows) { if (!AbortAll && ((command_number != null && command_number == commandrow.Index) || command_number == null) && commandrow.Index < batch_data.RowCount - 1) { FormAccess(FormDelegates.SelectBatchRow, new object[] { commandrow.Index }, auto_alias); List <Control> ctrls; RunCommand(auto_report, new Map(auto_alias, batch_number, commandrow.Index), batch_data, out ctrls, GetAutoVars(auto_data, batch_number, auto_alias)); if (ctrls != null) { foreach (Control ctrl in ctrls) { interactivecontrols.Add(ctrl); } } } } status = auto_report.CalculatedBatchResult(batch_number); } else { status = Status.SKIP; } CAT.FormAccess(CAT.FormDelegates.SetBatchStatus, new object[] { status, batch_number }, auto_alias); auto_report.BatchComplete(batch_number, status); }); if (Regex.IsMatch(Data.GetCell(auto_data, (int)CAT.AutoFields.Mode, batch_number), "-t")) { Task t = new Task(() => { runbatch(); }); BatchTasks.Add(t); t.Start(); } else { runbatch(); CAT.FormAccess(CAT.FormDelegates.SaveSelectedBatch, new object[] { }, auto_alias); } } interactive_controls = interactivecontrols; }
/// ======================================================================================================= // String based command line executer. Return all the standard output text. Ignore error text, as this isn't considered important (this is not a debug application). public static Status RunCmd(AutoReport auto_report, Map map, string fileName = "cmd.exe", string path = @"C:\", string command = "", int timeout = 120, string commandPrefix = "/C", bool use_shell = false, bool redirect_std_out = true, bool redirect_std_in = false, bool redirect_std_err = false, bool nowindow = true) { DateTime starttime = DateTime.Now; if (!CAT.AbortAll) { try { if (string.IsNullOrWhiteSpace(path) && Directory.Exists(command)) { command = @"%SystemRoot%\explorer.exe " + command; auto_report.AddOverlayedMessage(map, "Applied assumption: " + command, Status.WARN); } } catch { } path = DISK.AutoAddBaseDirectory(path); if (!Directory.Exists(path)) { if (auto_report != null) { auto_report.AddOverlayedMessage(map, "Path '" + path + "' is invalid", Status.FAIL); } } Process process = new Process(); try { ProcessStartInfo processinfo = new ProcessStartInfo() { CreateNoWindow = nowindow, UseShellExecute = use_shell, RedirectStandardOutput = redirect_std_out, RedirectStandardError = redirect_std_err, RedirectStandardInput = redirect_std_in, WorkingDirectory = path, WindowStyle = ProcessWindowStyle.Normal, FileName = fileName, Arguments = commandPrefix + command }; string alias = path + ">" + command; process.StartInfo = processinfo; process.Start(); string standardoutputtext = ""; string overlayname = "standardOutput" + map.A + map.B + map.C; if (auto_report != null) { auto_report.AddOverlay(overlayname, "", Status.INFO); } while (!process.StandardOutput.EndOfStream) { string line = process.StandardOutput.ReadLine(); standardoutputtext += line + "\r\n"; if (auto_report != null) { auto_report.UpdateOverlay(overlayname, standardoutputtext, Status.INFO); auto_report.UpdateCommandProgress(map); } if (CAT.AbortAll || CAT.AbortCurrent) { CAT.AbortCurrent = false; process.Close(); if (auto_report != null) { auto_report.AddOverlayedMessage(map, "User aborted after " + (DateTime.Now - starttime).TotalSeconds + "s", Status.ABORT); } return(Status.ABORT); } Thread.Sleep(10); if ((DateTime.Now - starttime).TotalMilliseconds > (timeout * 1000)) { process.Close(); if (auto_report != null) { auto_report.AddOverlayedMessage(map, "Timeout occured (timeout = " + timeout + "s)", Status.TIMEOUT); } return(Status.TIMEOUT); } } if (auto_report != null) { auto_report.AddMessage(map, standardoutputtext, Status.INFO); } process.Close(); return(Status.PASS); } catch (Exception e) { try { process.Close(); } catch { } if (auto_report != null) { auto_report.AddOverlayedMessage(map, ErrorMsg(e), Status.FAIL); } } } else { return(Status.ABORT); } return(Status.PASS); }
// String based DLL function executer. Path-format:"name.dll" Command-format:"namespace.class functionname(parameter1,parameter2,parameter3,parameteretc)" Do not deviate from the format! Do not use special characters! /// ======================================================================================================= public static Status RunDll(Map map, string path, string command, int timeout, out List <Control> interactive_controls, AutoReport auto_report = null) { string c = command; interactive_controls = new List <Control>(); Status status = Status.PASS; foreach (string namespace_class_function in c.Split(';')) { // Get cheker Checker checker = null; try { checker = GetChecker(auto_report, map, command); } catch (Exception e) { auto_report.AddOverlayedMessage(map, e.Message, Status.ABORT); } // Check for abort if (CAT.AbortAll) { return(Status.ABORT); } // Command started auto_report.OverlayCommandStarted(map); // Check for valid function and class string functionwithparameters = namespace_class_function.Substring(Regex.Match(namespace_class_function, @"\s").Index + 1, namespace_class_function.Length - Regex.Match(namespace_class_function, @"\s").Index - 1); string namespaceclass = namespace_class_function.Substring(0, Regex.Match(namespace_class_function, @"\s").Index); if (string.IsNullOrWhiteSpace(namespaceclass)) { functionwithparameters = namespace_class_function; } // Check function if (!Regex.IsMatch(functionwithparameters, FUNC_FORMAT + PARAM_FORMAT)) { functionwithparameters += "()"; } // Auto add brackets (no parameters) // Retry function check if (!Regex.IsMatch(functionwithparameters, FUNC_FORMAT + PARAM_FORMAT)) { auto_report.AddOverlayedMessage(map, "Function '" + functionwithparameters + "' is invalid", Status.FAIL); return(Status.FAIL); } // Function Name and Parameters string functionname = ExtractFunctionName(functionwithparameters); List <string> parameterList = ExtractParameters(functionwithparameters); // Default DLL if (string.IsNullOrWhiteSpace(namespaceclass)) { Type[] types = Assembly.GetExecutingAssembly().GetTypes(); foreach (Type t in types) { if (t.GetMethod(functionname) != null) { namespaceclass = "API." + t.Name; auto_report.AddOverlayedMessage(map, "Applied assumption (Namespace.Class): " + namespaceclass, Status.WARN); } } if (string.IsNullOrWhiteSpace(namespaceclass)) { namespaceclass = DISK.RemoveExtension(path) + "." + DISK.RemoveExtension(path); auto_report.AddOverlayedMessage(map, "Applied assumption (Namespace.Class): " + namespaceclass, Status.WARN); } } // Class if (string.IsNullOrWhiteSpace(namespaceclass)) { auto_report.AddOverlayedMessage(map, "Class '" + namespaceclass + "' is invalid", Status.FAIL); return(Status.FAIL); } // DLL Thread object returnvalue = null; path = DISK.AutoAddBaseDirectory(DISK.AutoAddExt(path, "dll")); DateTime starttime = DateTime.Now; Assembly assembly = null; try { assembly = Assembly.LoadFile(path); if (assembly == null) { throw new Exception("Assembly still null"); } } catch (Exception e) { auto_report.AddOverlayedMessage(map, "Error loading assembly " + path + ":\r\n" + ErrorMsg(e), Status.FAIL); return(Status.FAIL); } Type type = null; try { type = assembly.GetType(namespaceclass); if (type == null) { throw new Exception("Type still null"); } } catch (Exception e) { auto_report.AddOverlayedMessage(map, "Error loading type " + namespaceclass + ":\r\n" + ErrorMsg(e), Status.FAIL); return(Status.FAIL); } object instance = null; try { instance = Activator.CreateInstance(type); if (instance == null) { throw new Exception("Instance still null"); } } catch (Exception e) { auto_report.AddOverlayedMessage(map, "Error loading instance for " + type + ":\r\n" + ErrorMsg(e), Status.FAIL); return(Status.FAIL); } MethodInfo newmethod = null; try { newmethod = type.GetMethod(functionname); if (newmethod == null) { throw new Exception("Method still null"); } } catch (Exception e) { auto_report.AddOverlayedMessage(map, "Error loading method " + functionname + " for " + type + ":\r\n" + ErrorMsg(e), Status.FAIL); return(Status.FAIL); } string name = newmethod.Name; var ts = new CancellationTokenSource(); CancellationToken ct = ts.Token; bool iscomplete = false; bool exception = false; Task.Factory.StartNew(() => { try { if (newmethod.ReturnType == typeof(void)) { newmethod.Invoke(instance, parameterList.Cast <object>().ToArray()); } else { if (parameterList != null) { returnvalue = newmethod.Invoke(null, parameterList.Cast <object>().ToArray()); } else { returnvalue = newmethod.Invoke(null, null); } } } catch (Exception e) { auto_report.AddOverlayedMessage(map, ErrorMsg(e), Status.FAIL); exception = true; } iscomplete = true; }, ct); while (!iscomplete) { // Timeout if ((DateTime.Now - starttime).TotalSeconds > timeout) { ts.Cancel(); auto_report.AddOverlayedMessage(map, "Timeout occured (timeout = " + timeout + "s)", Status.TIMEOUT); return(Status.TIMEOUT); } // Abort if (CAT.AbortAll || CAT.AbortCurrent) { ts.Cancel(); CAT.AbortCurrent = false; // Reset to jump to next command Thread.Sleep(500); // Allow threads to cleanup using abort flags auto_report.AddOverlayedMessage(map, "User aborted after " + (int)((DateTime.Now - starttime).TotalMilliseconds) + "ms", Status.ABORT); return(Status.ABORT); } // CPU handling Thread.Sleep(10); // Progress Feedback auto_report.UpdateCommandProgress(map); } // RETURN VALUE if (exception) { status = Status.FAIL; } else if (returnvalue == null) { } else if (returnvalue is Control) { interactive_controls.Add(returnvalue as Control); } else if (returnvalue is List <Control> ) { foreach (Control ctrl in (returnvalue as List <Control>)) { interactive_controls.Add(ctrl); } ; } else if (!(returnvalue is Return)) { auto_report.AddOverlayedMessage(map, "This framework only supports 'Return' return type (or void)!\r\n" + returnvalue.GetType() + " is invalid", Status.FAIL); status = Status.FAIL; } else { if (((Return)returnvalue).Messages != null) { foreach (CATMessage message in ((Return)returnvalue).Messages) { auto_report.AddOverlayedMessage(map, message.Text, message.Status); if (message.Status == Status.FAIL) { status = Status.FAIL; } } // Add extra message checker messages if (checker != null && checker.CheckType == "Messages") { List <Result> messageresults = Results.Check(((Return)returnvalue).Messages, checker.CheckFunction, checker.CheckParameters); foreach (Result message in messageresults) { auto_report.AddOverlayedMessage(map, message.Message, message.Passed ? Status.PASS : Status.FAIL); } } } // Charts if (((Return)returnvalue).Charts != null) { List <ChartData> newdata = new List <ChartData>(); foreach (ChartData chart in ((Return)returnvalue).Charts) { newdata.Add(chart); } auto_report.AddChartList(map, newdata); // Add extra chart checker messages if (checker != null && checker.CheckType == "Charts") { List <Result> chartresults = Results.Check(((Return)returnvalue).Charts, checker.CheckFunction, checker.CheckParameters); foreach (Result chartmessage in chartresults) { auto_report.AddMessage(map, chartmessage.Message, chartmessage.Passed ? Status.PASS : Status.FAIL); } } } // Charts List if (((Return)returnvalue).ChartsList != null) { foreach (List <ChartData> chartlist in ((Return)returnvalue).ChartsList) { auto_report.AddChartList(map, chartlist); } } } } return(status); }
/// ======================================================================================================= private static void RunCommand(AutoReport auto_report, Map map, DataGridView batch_data, out List <Control> interactive_controls, List <Var> vars = null) { List <Control> interactivecontrols = null; int rep = 1; if (Regex.IsMatch(Data.GetCell(batch_data, (int)CAT.BatchFields.Mode, map.C), COMMAND_MODE_REPEAT)) { rep = Convert.ToInt16(Regex.Match(Data.GetCell(batch_data, (int)CAT.BatchFields.Mode, map.C), COMMAND_MODE_REPEAT).Value.Substring(1)); } if (Regex.IsMatch(Data.GetCell(batch_data, (int)CAT.BatchFields.Mode, map.C), COMMAND_MODE_THREAD_CATCH)) { auto_report.WaitForPreviousBatches(map); } Action runcommand = new Action(() => { for (int i = 1; i <= rep; i++) { DataGridViewRow cmd = batch_data.Rows[map.C]; string workdir = Data.GetCell(cmd, (int)CAT.BatchFields.Path); string command = Data.GetCell(cmd, (int)CAT.BatchFields.Command); Map newmap = new Map(map.A, map.B, map.C, rep > 1 ? i : 0); auto_report.AddCommand(new CommandReport(newmap, workdir + ">" + command)); Status status = Status.START; if (Data.IsCommandEnabled(cmd)) { if (vars != null) { string initialcommand = command; string initialworkdir = workdir; foreach (Var vartoinsert in vars) { command = command.Replace("{" + vartoinsert.Name + "}", vartoinsert.Value); workdir = workdir.Replace("{" + vartoinsert.Name + "}", vartoinsert.Value); } command = BasicArithmetic(command); if (initialcommand != command || initialworkdir != workdir) { auto_report.AddOverlayedMessage(newmap, "Variable updates (Workdir>Command): " + workdir + ">" + command, Status.WARN); } } if (string.IsNullOrWhiteSpace(Data.GetCell(cmd, (int)CAT.BatchFields.Command))) { auto_report.AddOverlayedMessage(newmap, "Command is null", Status.FAIL); status = Status.FAIL; } else if (string.IsNullOrWhiteSpace(Data.GetCell(cmd, (int)CAT.BatchFields.Timeout))) { auto_report.AddOverlayedMessage(newmap, "Timeout is null", Status.FAIL); status = Status.FAIL; } else { CAT.FormAccess(CAT.FormDelegates.SetCommandStatus, new object[] { Status.BUSY, newmap.C }, newmap.A); if (Regex.IsMatch(Data.GetCell(cmd, (int)CAT.BatchFields.Path), @".*\.dll")) { status = RunDll(newmap, workdir, command, Data.GetCmdTimeout(cmd), out interactivecontrols, auto_report); } else { status = RunCmd(auto_report, newmap, "cmd.exe", workdir, command, Data.GetCmdTimeout(cmd), "/C"); } } } else { status = Status.SKIP; } auto_report.CommandComplete(newmap, status); CAT.FormAccess(CAT.FormDelegates.SetCommandStatus, new object[] { status, newmap.C }, newmap.A); } }); if (Regex.IsMatch(Data.GetCell(batch_data, (int)CAT.BatchFields.Mode, map.C), "-t")) { Task t = new Task(() => { runcommand(); }); CommandTasks.Add(t); t.Start(); } else { runcommand(); } interactive_controls = interactivecontrols; }