// Only document uppercase static functions and uppercase constants /// ======================================================================================================= public static string Features(string path) { string alltext = ""; path = DISK.AutoAddBaseDirectory(DISK.AutoAddExt(path, "dll")); Assembly assembly = Assembly.LoadFile(path); Type[] ts = assembly.GetTypes(); foreach (Type t in ts) { if (!Regex.IsMatch(t.Name, "<>") && t.Name != "RunType" && t.Name.ToUpper() == t.Name) { var inst = Activator.CreateInstance(t); alltext += t.Namespace + "." + t.Name; try { alltext += ": " + t.GetField("Description").GetValue(inst); } catch { } alltext += "\r\n"; foreach (FieldInfo f in t.GetFields()) { if (f.IsLiteral && f.Name.ToUpper() == f.Name) { alltext += "const " + f.Name + ": " + f.GetValue(f); alltext += "\r\n"; } } foreach (MethodInfo m in t.GetMethods()) { if (m.IsStatic && m.Name.ToUpper() == m.Name) { alltext += "* " + m.Name + "("; foreach (ParameterInfo pi in m.GetParameters()) { alltext += pi.Name + ","; } alltext = alltext.Substring(alltext.Length - 1) == "," ? alltext.Remove(alltext.Length - 1, 1) : alltext; alltext += ")"; alltext += "\r\n"; } } } } return(alltext); }
// 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); }