17using DocumentFormat.OpenXml.Office.CustomUI;
22using OpenQA.Selenium.Remote;
24using System.Collections;
25using System.Collections.Generic;
26using System.Data.SqlClient;
27using System.Diagnostics;
29using System.Drawing.Imaging;
33using System.Runtime.CompilerServices;
35using System.Threading.Tasks;
36using System.Windows.Automation;
37using System.Windows.Forms;
50 private static Stopwatch _appTimer;
51 private static DateTime _startTime;
53 #region <Virtual Keys>
58 public static byte VK_ALT { [Keys(Description =
"Virtual key code for Alt, for use with keybd_event")]
get {
return 0x12; } }
62 public static byte VK_DELETE { [Keys(Description =
"Virtual key code for Delete, for use with keybd_event")]
get {
return 0x2e; } }
66 public static byte VK_F10 { [Keys(Description =
"Virtual key code for F10, for use with keybd_event")]
get {
return 0x79; } }
70 public static byte VK_PRIOR { [Keys(Description =
"Virtual key code for Page Up, for use with keybd_event")]
get {
return 0x21; } }
74 public static byte VK_NEXT { [Keys(Description =
"Virtual key code for Page Down, for use with keybd_event")]
get {
return 0x22; } }
78 public static byte VK_END { [Keys(Description =
"Virtual key code for End, for use with keybd_event")]
get {
return 0x23; } }
82 public static byte VK_HOME { [Keys(Description =
"Virtual key code for Home, for use with keybd_event")]
get {
return 0x24; } }
86 public static byte VK_DOWN { [Keys(Description =
"Virtual key code for the Down Arrow, for use with keybd_event")]
get {
return 0x28; } }
90 public static byte VK_UP { [Keys(Description =
"Virtual key code for the Up Arrow, for use with keybd_event")]
get {
return 0x26; } }
94 public static byte VK_TAB { [Keys(Description =
"Virtual key code for Tab, for use with keybd_event")]
get {
return 0x09; } }
98 public static byte VK_RETURN { [Keys(Description =
"Virtual key code for Enter, for use with keybd_event")]
get {
return 0x0D; } }
102 public static byte VK_SHIFT_RIGHT { [Keys(Description =
"Virtual key code for the right Shift, for use with keybd_event")]
get {
return 0xA1; } }
106 public static byte VK_SHIFT_LEFT { [Keys(Description =
"Virtual key code for the left Shift, for use with keybd_event")]
get {
return 0xA0; } }
110 public static byte VK_CONTROL_LEFT { [Keys(Description =
"Virtual key code for the left Control, for use with keybd_event")]
get {
return 0xA2; } }
114 public static byte VK_CONTROL_RIGHT { [Keys(Description =
"Virtual key code for the right Control, for use with keybd_event")]
get {
return 0xA3; } }
118 public static byte VK_LWIN { [Keys(Description =
"Virtual key code for the left Windows key, for use with keybd_event")]
get {
return 0x5B; } }
122 public static byte VK_RWIN { [Keys(Description =
"Virtual key code for the right Windows key, for use with keybd_event")]
get {
return 0x5C; } }
126 public static byte VK_SCROLL { [Keys(Description =
"Scroll Lock key virtual keycode (VK) for use with keybd_event")]
get {
return 0x91; } }
130 public static byte VK_LMENU { [Keys(Description =
"Left Alt key virtual keycode (VK) for use with keybd_event")]
get {
return 0xA4; } }
134 public static byte VK_RMENU { [Keys(Description =
"Right Alt key virtual keycode (VK) for use with keybd_event")]
get {
return 0xA5; } }
138 public static byte VK_APPS { [Keys(Description =
"Application (Menu) key virtual keycode (VK) for use with keybd_event")]
get {
return 0x5D; } }
142 public static byte VK_SPACE { [Keys(Description =
"Virtual key code for the space bar, for use with keybd_event")]
get {
return 0x20; } }
146 public static byte VK_BACK { [Keys(Description =
"Virtual key code for Backspace, for use with keybd_event")]
get {
return 0x08; } }
160 [Keys(Description =
"keybd_event flag marking an extended key, such as the right-hand Alt and Control")]
161 public static uint
KEYEVENTF_EXTENDEDKEY { [Keys(Description =
"keybd_event flag marking an extended key, such as the right-hand Alt and Control")]
get {
return 0x0001; } }
171 public static uint
KEYEVENTF_KEYUP { [Keys(Description =
"keybd_event flag that sends the release of a key rather than the press")]
get {
return 0x0002; } }
172 #endregion <Virtual Keys>
173 #region <Working Variables>
174 private static List<
Application.
Application> ApplicationList {
get; } =
new List<Application.Application>();
175 private static List<Browser.Browser> BrowserList {
get; } =
new List<
Browser.Browser>();
176 private static List<Selector> SelectorList {
get; } =
new List<Selector>();
177 private static List<GPALForm.GPALForm> FormList {
get; } =
new List<GPALForm.GPALForm>();
178 private static List<IGPALAI> AIList {
get; } =
new List<IGPALAI>();
179 private static List<GPALFile> FileList {
get; } =
new List<GPALFile>();
180 private static List<IGPALMail> MailList {
get; } =
new List<IGPALMail>();
181 public static List<IGPALLogger> LoggerList {
get; } =
new List<IGPALLogger>();
182 private static List<GPALControl> ControlList {
get; } =
new List<GPALControl>();
183 private static List<IGPALGrid<string>> GridList {
get; } =
new List<IGPALGrid<string>>();
185 private static bool SettingsLoaded
189 return gpalSettings.SettingsLoaded;
194 gpalSettings.SettingsLoaded = value;
198 private static GPALSettings gpalSettings =
new GPALSettings(
true);
199 private static string _settingsFilePath =
"GPAL.yaml";
200 public static GPALSettings GPALSettings
202 [GPALSettings(Description =
"The global settings GPAL is running with")]
get
208 gpalSettings = value;
211 private static Browser.ElementAssistant elementAssistant {
get; } =
new Browser.ElementAssistant();
212 private static Application.ElementAssistant applicationElementAssistant {
get; } =
new Application.ElementAssistant();
214 private static Browser.Browser tmpBrowser {
get;
set; } =
null;
215 private static Application.Application tmpApplication {
get;
set; } =
null;
216 private static bool UncaughtExceptionHandlerSet {
get;
set; } =
false;
218 private static int applicationCount = 1;
219 private static int browserCount = 1;
220 private static int selectorCount = 1;
221 private static int formCount = 1;
222 private static int controlCount = 1;
223 private static int executableCount = 1;
224 private static int restClientCount = 1;
226 private static readonly
string applicationName =
"Application";
227 private static readonly
string browserName =
"Browser";
228 private static readonly
string chartName =
"Chart";
229 private static readonly
string selectorName =
"Selector";
230 private static readonly
string formName =
"Form";
231 private static readonly
string buttonName =
"Button";
232 private static readonly
string checkboxName =
"Checkbox";
233 private static readonly
string inputName =
"Input";
234 private static readonly
string labelName =
"Label";
235 private static readonly
string linkLabelName =
"LinkLabel";
236 private static readonly
string spacerName =
"Spacer";
237 private static readonly
string radioButtonName =
"Radiobutton";
238 private static readonly
string textAreaName =
"TextArea";
239 private static readonly
string richTextBoxName =
"RichTextBox";
240 private static readonly
string executableName =
"Executable";
241 private static readonly
string restClientName =
"RESTClient";
243 private static bool inPublishEvent =
false;
246 [ThreadStatic]
private static HashSet<IGPALLogger> loggersWriting;
247 #endregion <Working Variables>
249 static bool inStaticInit =
false;
259 if (
false == inStaticInit)
264 _startTime = DateTime.Now;
265 _appTimer = Stopwatch.StartNew();
269 if (ConsoleEvents.HasFlag(GPALEventType.INFO))
272 PublishSimpleEvent(GPALEventType.INFO, $
">>> Application Start Time: [{_startTime.ToString("yyyy-MM-dd HH:mm:ss
")}] <<<");
274 else if (ConsoleEvents.HasFlag(GPALEventType.NOTICE))
277 PublishSimpleEvent(GPALEventType.NOTICE, $
">>> Application Start Time: [{_startTime.ToString("yyyy-MM-dd HH:mm:ss
")}] <<<");
280 SetCatchUncaughtExceptions();
282 inStaticInit =
false;
285 #endregion Constructor
286 #region <Exception & Information EventHandler>
296 public Enums.GPALEventType GPALEventType {
get;
set; }
354 public IGPALGrid<string>
Tokens {
get;
set; }
366 public dynamic
Data {
get;
set; }
373 internal static EventHandler<GPALEventArgs> ExceptionEventHandler {
get;
set; }
374 internal static EventHandler<GPALEventArgs> InformationEventHandler {
get;
set; }
375 #endregion <Exception & Information EventHandler>
396 internal static EventHandler<GPALEventArgs> ExceptionHandler
400 return ExceptionEventHandler;
423 internal static EventHandler<GPALEventArgs> InformationHandler
427 return InformationEventHandler;
431 #region <GPAL Object Getters>
432 public static Cryptography Cryptography
434 [Component(Description =
"Encrypt, decrypt, hash, sign and verify data", Submenu =
"Security")]
get =>
new Cryptography();
436 public static Base64Helper Base64Helper
438 [Component(Description =
"Encode and decode Base64", Submenu =
"Security")]
get =>
new Base64Helper();
462 [Component(Description =
"Entry point for the GPAL AI subsystem, providing a fluent interface for AI tasks", Submenu =
"Services")]
get
470 public static IGPALYouTube YouTube { [Component(Description =
"Upload videos to YouTube, manage playlists and search", Submenu =
"Google")]
get =>
new Browser.
GPALYouTube(); }
482 internal static IImageMatcher ImageMatcher {
get;
private set; }
484 [Action(Description =
"Register the image matcher from the GPAL.Image package, which image selectors need")]
485 public static void RegisterImageMatcher(IImageMatcher imageMatcher) => ImageMatcher = imageMatcher;
487 internal static ImageHelper imageHelper;
488 public static IImageHelper ImageHelper
490 [Component(Description =
"Screenshots and image matching", Submenu =
"System")]
get
492 if (
null == imageHelper)
493 imageHelper =
new ImageHelper();
520 [Component(Description =
"A file, or several, for a step to read from or write to, such as FillInFrom or SaveTo", Submenu =
"Data")]
531 public static IAllowGridActions<string>
Grid
533 [Component(Description =
"A grid of rows and columns that steps fill in from and save data into", Submenu =
"Data")]
536 IGPALGrid<string> grid =
new GPALGrid<string>();
546 [Component(Description =
"A logger that records the events GPAL publishes", Submenu =
"System")]
550 LoggerList.Add(logger);
559 [Component(Description =
"Send and receive email over SMTP, POP or IMAP", Submenu =
"Services")]
572 [Fluent(Description =
"Convert data from one shape to another: file, grid, database, class, and the CSV, JSON, XML, YAML and Excel formats")]
598 [Fluent(Description =
"Start or attach to a desktop application and automate it")]
602 tmpApplication.Name = applicationName + applicationCount++.ToString();
603 ApplicationList.Add(tmpApplication);
604 return tmpApplication;
629 [Fluent(Description =
"Start or attach to a browser and automate it on Selenium, Puppeteer or OttoMagic")]
632 tmpBrowser =
new Browser.Browser();
633 tmpBrowser.Name = browserName + browserCount++.ToString();
638 if (0 < BrowserList.Count)
639 tmpBrowser.WithAutomationEngine(BrowserList[0].AutomationEngine);
641 BrowserList.Add(tmpBrowser);
688 [Component(Description =
"Read or set the Windows clipboard", Submenu =
"Data")]
697 [Component(Description =
"Read from and write to a database table or stored procedure", Submenu =
"Data")]
730 [Component(Description =
"Describe how to find an element in a browser or an application", Submenu =
"Selectors")]
734 if (
null != tmpBrowser)
735 tmpSelector =
new Selector(tmpBrowser);
736 else if (
null != tmpApplication)
737 tmpSelector =
new Selector(tmpApplication);
740 tmpSelector.Name = selectorName + selectorCount++.ToString();
741 SelectorList.Add(tmpSelector);
761 [Component(Description =
"Describe an API request for Fetch to send from inside the page, carrying the session the browser already has", Submenu =
"Browser")]
769 [Component(Description =
"Start a program or open a document, with arguments, and optionally read what it prints", Submenu =
"System")]
774 Name = executableName + executableCount++.ToString()
951 [Component(Description =
"Call a REST API: base url, endpoint, parameters and credentials", Submenu =
"Services")]
956 Name = restClientName + restClientCount++.ToString()
966 [Component(Description =
"Credentials from a password manager, an API key or an OAuth provider", Submenu =
"Security")]
971 [Component(Description =
"Write a workflow as Given, When and Then steps", Submenu =
"System")]
972 get =>
new Gherkin();
979 [Component(Description =
"Read and write a Google Sheets spreadsheet", Submenu =
"Google")]
987 [Component(Description =
"Work with files in Google Drive", Submenu =
"Google")]
992 [Component(Description =
"Read and write an Excel workbook", Submenu =
"Data")]
997 [Component(Description =
"A url, and the website storage on it to read or change", Submenu =
"Browser")]
1001 #region Internal GPAL factory for ActivatorHelper
1002 internal static GPALElement Element
1004 get =>
new GPALElement();
1006 internal static GPALFileSettings FileSettings
1008 get =>
new GPALFileSettings();
1010 internal static GPALMailSettings MailSettings
1012 get =>
new GPALMailSettings();
1014 internal static GPALSettings Settings
1016 get =>
new GPALSettings();
1018 #endregion Internal GPAL factory for ActivatorHelper
1019 #endregion <GPAL Objects>
1020 #region Shorthand Helpers
1021 [Component(Description =
"An Excel workbook for the given file", Submenu =
"Data")]
1022 public static IGPALExcel ExcelFor(GPALFile excelFile)
1024 return new GPALExcel().WithFile(excelFile).ToGPALObject();
1027 [Component(Description =
"Credentials for the given service", Submenu =
"Security")]
1028 public static ICredentials CredentialsFor(CredentialServiceType credentialServiceType)
1032 [Component(Description =
"A Google Sheets spreadsheet, opened by name or id", Submenu =
"Google")]
1033 public static IGoogleSheets GoogleSheetsFor(
string spreadsheetName)
1035 return new GoogleSheets().WithSpreadsheet(spreadsheetName).ToGPALObject();
1037 [Component(Description =
"Google Drive, signed in with the given credentials", Submenu =
"Google")]
1038 public static IGoogleDrive GoogleDriveFor(ICredentials credentials)
1040 return new GoogleDrive().WithCredentials(credentials).ToGPALObject();
1042 [Component(Description =
"A grid whose rows are objects of the given class", Submenu =
"Data")]
1043 public static IGPALGrid<T> GridForType<T>()
1045 return new GPALGrid<T>();
1061 [Component(Description =
"A selector that finds an element by CSS, optionally named", Submenu =
"Selectors")]
1064 if (
null != selectorName)
1065 return Selector.WithCSS(css).WithSelectorName(selectorName).ToGPALObject();
1067 return Selector.WithCSS(css).ToGPALObject();
1070 [Component(Description =
"A selector that finds an element by XPath, optionally named", Submenu =
"Selectors")]
1071 public static Selector XPathSelector(
string xpath,
string selectorName =
null)
1073 if (
null != selectorName)
1078 [Component(Description =
"A GPALFile for the given path", Submenu =
"Data")]
1079 public static GPALFile FileFor(
string path)
1081 return File.WithFileName(path).ToGPALObject();
1084 [Component(Description =
"Start a browser with no window on the given url", Submenu =
"Browser")]
1085 public static IBrowser BrowserGet(GPALUrl url)
1092 [Component(Description =
"Start a browser window on the given url", Submenu =
"Browser")]
1093 public static IBrowser BrowserGoto(GPALUrl url)
1099 [Component(Description =
"A button with the given text, for a GPAL form", Submenu =
"Form Controls/Buttons and Choices")]
1100 public static GPALButton ButtonFor(
string text)
1102 var c =
new GPALButton { Name = buttonName + controlCount++.ToString() };
1103 c.IsDefault =
false;
1108 [Component(Description =
"A label with the given text, for a GPAL form", Submenu =
"Form Controls/Text")]
1109 public static GPALLabel LabelFor(
string text)
1111 var c =
new GPALLabel { Name = labelName + controlCount++.ToString() };
1116 [Component(Description =
"Empty space this many pixels tall between two controls on a GPAL form", Submenu =
"Form Controls/Layout")]
1117 public static GPALSpacer SpacerFor(
int pixels)
1119 var c =
new GPALSpacer { Name = spacerName + controlCount++.ToString() };
1124 [Component(Description =
"A link for a GPAL form that opens this address in the default browser, showing the address as its text", Submenu =
"Form Controls/Text")]
1125 public static GPALLinkLabel LinkLabelFor(
string url)
1127 var c =
new GPALLinkLabel { Name = linkLabelName + controlCount++.ToString() };
1133 [Component(Description =
"A one-line input box for a GPAL form, optionally with starting text", Submenu =
"Form Controls/Text")]
1134 public static GPALInput InputFor(
string text =
"")
1136 var c =
new GPALInput { Name = inputName + controlCount++.ToString() };
1141 [Component(Description =
"A multi-line text box for a GPAL form, optionally with starting text", Submenu =
"Form Controls/Text")]
1142 public static GPALTextArea TextAreaFor(
string text =
"")
1144 var c =
new GPALTextArea { Name = textAreaName + controlCount++.ToString() };
1149 [Component(Description =
"A rich text box for a GPAL form that renders Markdown, optionally with starting text", Submenu =
"Form Controls/Text")]
1150 public static GPALRichTextBox RichTextBoxFor(
string text =
"")
1152 var c =
new GPALRichTextBox { Name = richTextBoxName + controlCount++.ToString() };
1157 [Component(Description =
"A checkbox with the given text, for a GPAL form, checked or not", Submenu =
"Form Controls/Buttons and Choices")]
1158 public static GPALCheckbox CheckboxFor(
string text,
bool isChecked =
false)
1160 var c =
new GPALCheckbox { Name = checkboxName + controlCount++.ToString() };
1162 c.IsChecked = isChecked;
1166 [Component(Description =
"A radio button with the given text, for a GPAL form, selected or not", Submenu =
"Form Controls/Buttons and Choices")]
1167 public static GPALRadioButton RadioButtonFor(
string text,
bool isChecked =
false)
1169 var c =
new GPALRadioButton { Name = radioButtonName + controlCount++.ToString() };
1171 c.IsChecked = isChecked;
1175 [Component(Description =
"A tab with the given title, for a GPAL form", Submenu =
"Form Controls/Layout")]
1176 public static GPALTab TabFor(
string text)
1178 var c =
new GPALTab { Name = radioButtonName + controlCount++.ToString() };
1183 [Component(Description =
"A chart for a GPAL form, optionally with a title", Submenu =
"Form Controls/Lists and Data")]
1184 public static GPALChart ChartFor(
string title =
"")
1186 var c =
new GPALChart { Name = chartName + controlCount++.ToString() };
1187 if (!
string.IsNullOrEmpty(title)) c.WithTitle(title);
1191 [Component(Description =
"A drop-down list with the given items, for a GPAL form", Submenu =
"Form Controls/Buttons and Choices")]
1192 public static GPALComboBox ComboBoxFor(params
string[] items)
1194 var c =
new GPALComboBox { Name =
"ComboBox" + controlCount++.ToString() };
1195 if (items !=
null && items.Length > 0) c.WithItems(items);
1198 [Component(Description =
"A data grid with the given columns, for a GPAL form", Submenu =
"Form Controls/Lists and Data")]
1199 public static GPALDataGridView DataGridViewFor(params
string[] columns)
1201 var c =
new GPALDataGridView { Name =
"DataGridView" + controlCount++.ToString() };
1202 if (columns !=
null && columns.Length > 0) c.WithColumns(columns);
1205 [Component(Description =
"A list view with the given columns, for a GPAL form", Submenu =
"Form Controls/Lists and Data")]
1206 public static GPALListView ListViewFor(params
string[] columns)
1208 var c =
new GPALListView { Name =
"ListView" + controlCount++.ToString() };
1209 if (columns !=
null && columns.Length > 0) c.WithColumns(columns);
1212 [Component(Description =
"A picture box showing the given image file, for a GPAL form", Submenu =
"Form Controls/Lists and Data")]
1213 public static GPALPicture PictureFor(GPALFile file)
1215 var c =
new GPALPicture { Name =
"Picture" + controlCount++.ToString() };
1219 [Component(Description =
"A slider from 0 to the given maximum, for a GPAL form", Submenu =
"Form Controls/Buttons and Choices")]
1220 public static GPALSlider SliderFor(
int maximum = 100)
1222 var c =
new GPALSlider { Name =
"Slider" + controlCount++.ToString() };
1223 c.WithMaximum(maximum);
1226 [Component(Description =
"A progress bar from 0 to the given maximum, for a GPAL form", Submenu =
"Form Controls/Lists and Data")]
1227 public static GPALProgressBar ProgressBarFor(
int maximum = 100)
1229 var c =
new GPALProgressBar { Name =
"ProgressBar" + controlCount++.ToString() };
1230 c.WithMaximum(maximum);
1233 [Component(Description =
"A status strip with the given text, for a GPAL form", Submenu =
"Form Controls/Menus and Bars")]
1234 public static GPALStatusStrip StatusStripFor(
string text =
"Ready")
1236 var c =
new GPALStatusStrip { Name =
"StatusStrip" + controlCount++.ToString() };
1240 [Component(Description =
"A number box held between the given minimum and maximum, for a GPAL form", Submenu =
"Form Controls/Buttons and Choices")]
1241 public static GPALNumericUpDown NumericUpDownFor(decimal minimum = 0, decimal maximum = 100)
1243 var c =
new GPALNumericUpDown { Name =
"NumericUpDown" + controlCount++.ToString() };
1244 c.WithMinimum(minimum);
1245 c.WithMaximum(maximum);
1248 [Component(Description =
"A date and time picker for a GPAL form, optionally set to a value", Submenu =
"Form Controls/Buttons and Choices")]
1249 public static GPALDateTimePicker DateTimePickerFor(DateTime? value =
null)
1251 var c =
new GPALDateTimePicker { Name =
"DateTimePicker" + controlCount++.ToString() };
1252 if (value.HasValue) c.WithValue(value.Value);
1255 [Component(Description =
"An empty tree view for a GPAL form", Submenu =
"Form Controls/Lists and Data")]
1256 public static GPALTreeView TreeViewFor()
1258 return new GPALTreeView { Name =
"TreeView" + controlCount++.ToString() };
1260 [Component(Description =
"A file or folder picker with the given dialog title, for a GPAL form", Submenu =
"Form Controls/Buttons and Choices")]
1261 public static GPALFileSelector FileSelectorFor(
string title =
"Select File/Folder")
1263 var c =
new GPALFileSelector { Name =
"FileSeleector" + controlCount++.ToString() };
1267 [Component(Description =
"A layout panel with the given columns and rows, for a GPAL form", Submenu =
"Form Controls/Layout")]
1268 public static GPALTableLayoutPanel TableLayoutPanelFor(
int columns = 1,
int rows = 1)
1270 var c =
new GPALTableLayoutPanel { Name =
"TableLayoutPanel" + controlCount++.ToString() };
1271 c.WithColumnCount(columns);
1272 c.WithRowCount(rows);
1275 #endregion Shorthand Helpers
1276 #region <ElementAssitant>
1299 [ElementAssitant(Description =
"Work with the elements a browser selector found, from inside a callback")]
1302 elementAssistant.Browser = selector.
Browser;
1303 elementAssistant.ForSelector(selector);
1304 return elementAssistant;
1330 [ElementAssitant(Description =
"Work with the elements an application selector found, from inside a callback")]
1333 applicationElementAssistant.Application = application;
1334 return applicationElementAssistant;
1336 #endregion <ElementAssitant>
1337 #region <Form Controls>
1370 [Fluent(Description =
"Build a form of controls to give a workflow a user interface")]
1375 FormName = formName + formCount++.ToString(),
1377 FormList.Add(tmpForms);
1415 [Forms(Description =
"A button for a GPAL form, calling back when it is clicked", Submenu =
"Buttons and Choices")]
1420 Name = buttonName + controlCount++.ToString(),
1424 tmpControl.IsDefault =
false;
1425 ControlList.Add(tmpControl);
1472 [Forms(Description =
"A chart for a GPAL form", Submenu =
"Lists and Data")]
1477 Name = chartName + controlCount++.ToString()
1479 ControlList.Add(tmpControl);
1515 [Forms(Description =
"A checkbox for a GPAL form, calling back when it is checked or cleared", Submenu =
"Buttons and Choices")]
1520 Name = checkboxName + controlCount++.ToString()
1522 ControlList.Add(tmpControl);
1554 [Forms(Description =
"Instantiates a new GPALComboBox for use on a GPAL form", Submenu =
"Buttons and Choices")]
get
1558 Name =
"ComboBox" + controlCount++.ToString()
1582 [Forms(Description =
"Instantiates a new GPALDataGridView for use on a GPAL form", Submenu =
"Lists and Data")]
get
1586 Name =
"DataGridView" + controlCount++.ToString()
1611 [Forms(Description =
"Instantiates a new GPALDateTimePicker for use on a GPAL form", Submenu =
"Buttons and Choices")]
get
1615 Name =
"DateTimePicker" + controlCount++.ToString()
1663 [Forms(Description =
"Instantiates a new GPALFileSelector for use on a GPAL form", Submenu =
"Buttons and Choices")]
get
1667 Name =
"FileSeleector" + controlCount++.ToString()
1694 [Forms(Description =
"A one-line input box for a GPAL form, calling back when its text changes", Submenu =
"Text")]
1699 Name = inputName + controlCount++.ToString()
1701 ControlList.Add(tmpControl);
1719 [Forms(Description =
"A link for a GPAL form that opens an address in the default browser", Submenu =
"Text")]
1724 Name = linkLabelName + controlCount++.ToString()
1726 ControlList.Add(tmpControl);
1751 [Forms(Description =
"A label for a GPAL form", Submenu =
"Text")]
1756 Name = labelName + controlCount++.ToString()
1758 ControlList.Add(tmpControl);
1791 [Forms(Description =
"Instantiates a new GPALListView for use on a GPAL form", Submenu =
"Lists and Data")]
get
1795 Name =
"ListView" + controlCount++.ToString()
1822 [Forms(Description =
"Instantiates a new GPALNumericUpDown for use on a GPAL form", Submenu =
"Buttons and Choices")]
get
1826 Name =
"NumericUpDown" + controlCount++.ToString()
1850 [Forms(Description =
"A picture control for GPAL forms", Submenu =
"Lists and Data")]
get
1854 Name =
"Picture" + controlCount++.ToString()
1880 [Forms(Description =
"A slider control for GPAL forms", Submenu =
"Buttons and Choices")]
get
1884 Name =
"Slider" + controlCount++.ToString()
1911 [Forms(Description =
"A progress bar control for GPAL forms", Submenu =
"Lists and Data")]
get
1915 Name =
"ProgressBar" + controlCount++.ToString()
1960 [Forms(Description =
"A radio button for a GPAL form, calling back when it is selected", Submenu =
"Buttons and Choices")]
1965 Name = radioButtonName + controlCount++.ToString()
1967 ControlList.Add(tmpControl);
1989 [Forms(Description =
"A status strip control (docked at the bottom) for GPAL forms", Submenu =
"Menus and Bars")]
get
1993 Name =
"StatusStrip" + controlCount++.ToString()
2019 [Forms(Description =
"A menu bar docked to the top of a GPAL form", Submenu =
"Menus and Bars")]
get
2023 Name =
"MenuBar" + controlCount++.ToString()
2046 [Forms(Description =
"A single item shared by menu bars and toolbars: text, optional image, optional shortcut key, and a callback wired to its click", Submenu =
"Menus and Bars")]
get
2050 Name =
"BarItem" + controlCount++.ToString()
2072 [Forms(Description =
"A toolbar docked below the menu bar, holding GPAL.BarItem buttons and optional separators", Submenu =
"Menus and Bars")]
get
2076 Name =
"Toolbar" + controlCount++.ToString()
2107 [Forms(Description =
"A tab page for a GPAL form", Submenu =
"Layout")]
2112 Name = radioButtonName + controlCount++.ToString()
2114 ControlList.Add(tmpControl);
2134 public static IAllowSplitterControlSettings Splitter { [Forms(Description =
"Instantiates a new GPALSplitter for use on a GPAL form: two panes with a bar between them, built whole and then laid out like any other control", Submenu =
"Layout")]
get =>
new GPALSplitter(); }
2171 [Forms(Description =
"A multi-line text box for a GPAL form, calling back when its text changes", Submenu =
"Text")]
2176 Name = textAreaName + controlCount++.ToString()
2178 ControlList.Add(tmpControl);
2205 [Forms(Description =
"A rich text box for a GPAL form that renders Markdown", Submenu =
"Text")]
2210 Name = richTextBoxName + controlCount++.ToString()
2212 ControlList.Add(tmpControl);
2237 [Forms(Description =
"Instantiates a new GPALTreeView for use on a GPAL form", Submenu =
"Lists and Data")]
get
2241 Name =
"TreeView" + controlCount++.ToString()
2246 #endregion <Form Controls>
2247 #region <Getters/Setters>
2248 public static bool UseHardware
2250 [
GPALSettings(Description =
"Whether GPAL uses the real mouse and keyboard by default")]
get => gpalSettings.UseHardware;
2252 public static bool UseJavaSCript
2254 [GPALSettings(Description =
"Whether GPAL interacts through injected JavaScript by default")]
get => gpalSettings.UseJavaScript;
2273 [Component(Description =
"Run whole workflows at once, each owning the browser or application it drives", Submenu =
"System")]
2276 return new Browser.WorkflowScheduler();
2297 [Component(Description =
"The hidden desktops this program made, to peek at, return from or close", Submenu =
"System")]
2300 return new Browser.GPALHiddenDesktops();
2303 public static string Version
2305 [Data(Description =
"The version of GPAL that is running")]
get =>
GPALSettings.Version;
2314 [Data(Description =
"Where an OAuth redirect lands and the token is read back from, e.g. http://localhost:3117/")]
get
2316 return gpalSettings.OAuthTokenUrl;
2320 gpalSettings.OAuthTokenUrl = value;
2323 internal static List<IGPALLogger> PublishToLoggers
2331 internal static GPALTextArea PublishControl
2335 return GPALSettings.PublishControl;
2340 private const int PublishControlMaxLines = 2_000;
2342 internal static bool PublishToConsole
2346 return GPALSettings.PublishToConsole;
2350 GPALSettings.PublishToConsole = value;
2353 internal static bool PublishToDebug
2357 return GPALSettings.PublishToDebug;
2360 internal static GPALEventType ConsoleEvents
2362 get => GPALSettings.ConsoleEvents;
2363 set => GPALSettings.ConsoleEvents = value;
2365 internal static GPALEventType DebugEvents
2367 get => GPALSettings.DebugEvents;
2369 internal static bool PublishStackTrace
2373 return GPALSettings.PublishStackTrace;
2376 internal static string ErrorPlaceholder
2380 return GPALSettings.ErrorPlaceholder;
2383 internal static string DriverLocation
2387 return GPALSettings.DriverLocation;
2390 internal static bool SimulateMouse
2394 return GPALSettings.SimulateMouse;
2397 internal static string TempProfileDirectory
2401 return GPALSettings.TempProfileDirectory;
2404 internal static List<
Browser.Browser> Browsers
2411 internal static int MatchingPercentage
2415 return GPALSettings.MatchingPercentage;
2418 internal static int TypingDelay
2422 return GPALSettings.TypingDelay;
2425 internal static bool StopOnNotFound
2429 return GPALSettings.StopOnNotFound;
2432 internal static bool NoFallbackRecoveryActions
2436 return gpalSettings.NoFallbackRecoveryActions;
2439 #endregion <Getters/Setters>
2441 [Helper(Description =
"Load GPAL's settings from GPAL.yaml or the given file, creating it with the defaults if it is missing")]
2442 public static void LoadSettings(GPALFile settingsFile =
null)
2444 bool hold = GPAL.PublishToConsole;
2445 GPALEventType events = GPAL.GPALSettings.ConsoleEvents;
2449 if (settingsFile !=
null)
2451 _settingsFilePath = settingsFile.Filenames[0];
2452 SettingsLoaded =
false;
2455 if (
false == SettingsLoaded)
2457 SettingsLoaded =
true;
2458 string currentVersion = System.Reflection.Assembly.GetExecutingAssembly().GetName().Version.ToString();
2459 GPALFile resolvedFile = _settingsFilePath;
2461 if (
true == System.IO.File.Exists(resolvedFile.
Filenames[0]))
2464 GPAL.Converter.WithInput(resolvedFile).SaveTo(ref gpalSettings);
2466 hold = GPAL.PublishToConsole;
2467 events = GPAL.GPALSettings.ConsoleEvents;
2470 if (
"1" == Environment.GetEnvironmentVariable(
"GPAL_IS_SILENT"))
2471 GPAL.PublishToConsole =
false;
2473 GPAL.PublishSimpleEvent(GPALEventType.INFO, $
"[{resolvedFile.Filenames[0]}] loaded, using settings.", gpalSettings, GPALObjectType.Other);
2475 if (
false == gpalSettings.Version.Equals(currentVersion))
2477 GPAL.PublishSimpleEvent(GPALEventType.INFO, $
"[{resolvedFile.Filenames[0]}] updated to current GPAL version [{currentVersion}].", gpalSettings, GPALObjectType.Other);
2478 gpalSettings.Version = currentVersion;
2484 GPAL.PublishSimpleEvent(GPALEventType.WARNING, $
"[{resolvedFile.Filenames[0]}] does not exist. Using default settings and creating GPAL.yaml.", gpalSettings, GPALObjectType.Other);
2489 AIProvidersConfig.TryAutoLoad();
2491 catch (Exception ex)
2493 GPAL.PublishSimpleEvent(GPALEventType.EXCEPTION, $
"[{_settingsFilePath}] load error. Try deleting it and restarting.", gpalSettings, GPALObjectType.Other, ex);
2497 GPAL.PublishToConsole = hold;
2498 GPAL.GPALSettings.ConsoleEvents = events;
2501 [Helper(Description =
"Save GPAL's current settings to GPAL.yaml or the given file")]
2502 public static void SaveSettings(GPALFile settingsFile =
null)
2504 if (settingsFile !=
null) _settingsFilePath = settingsFile.Filenames[0];
2505 GPAL.Converter.WithInput(GPALSettings).SaveTo((GPALFile)_settingsFilePath);
2514 [Helper(Description =
"Take a screenshot and keep it on the browser's settings")]
2517 ((ImageHelper)GPAL.ImageHelper).
CaptureScreen(browser).ToBitmap(out ((
Browser.Browser)browser).BrowserSettings.ScreenShot);
2534 [MethodImpl(MethodImplOptions.NoInlining)]
2535 [Helper(Description =
"The name of the method that called it, for event messages")]
2538 var st =
new StackTrace();
2539 var sf = st.GetFrame(1);
2540 string name = sf.GetMethod().Name;
2542 if (name.Equals(
"MoveNext"))
2545 name = sf.GetMethod().ReflectedType.Name
2546 .Split(
new char[] {
'<',
'>' }, StringSplitOptions.RemoveEmptyEntries)[0];
2566 [MethodImpl(MethodImplOptions.NoInlining)]
2567 [Helper(Description =
"Publish an event to the information or exception handlers")]
2568 public static void PublishSimpleEvent(GPALEventType gPALEventType,
string msg, dynamic gPALObject =
null, Enums.GPALObjectType gPALObjectType = GPALObjectType.None, Exception ex =
null)
2577 bool toExceptionChannel =
null != ex ||
true == gPALEventType.HasFlag(GPALEventType.EXCEPTION);
2580 bool handlerWants =
true == toExceptionChannel
2581 ?
null != ExceptionHandler && gpalSettings.ExceptionHandlerEvents.HasFlag(gPALEventType)
2582 :
null != InformationHandler && gpalSettings.InformationHandlerEvents.HasFlag(gPALEventType);
2583 bool consoleWants =
true == GPAL.PublishToConsole && gpalSettings.ConsoleEvents.HasFlag(gPALEventType);
2584 bool debugWants =
true == GPAL.PublishToDebug && gpalSettings.DebugEvents.HasFlag(gPALEventType);
2585 bool controlWants =
null != GPAL.PublishControl && gpalSettings.ControlEvents.HasFlag(gPALEventType);
2586 bool loggerWants = 0 < GPAL.PublishToLoggers.Count;
2588 if (
false == handlerWants &&
false == consoleWants &&
false == debugWants &&
false == controlWants &&
false == loggerWants)
2591 if (
true == handlerWants ||
true == controlWants ||
true == consoleWants ||
true == debugWants ||
true == loggerWants)
2593 var st =
new StackTrace();
2594 var sf = st.GetFrame(1);
2595 string name = sf.GetMethod().Name;
2596 DateTime dateTime = DateTime.Now;
2597 string stackTrace =
null != ex &&
true == GPAL.PublishStackTrace ? $
"[{ex.StackTrace}]" :
string.Empty;
2599 if (name.Equals(
"MoveNext"))
2602 name = sf.GetMethod().ReflectedType.Name
2603 .Split(
new char[] {
'<',
'>' }, StringSplitOptions.RemoveEmptyEntries)[0];
2608 string outMessage = $
"[{dateTime.ToString("yyyy-MM-dd HH:mm:ss.ffff
")}][{gPALEventType,-7}][{name}]: {msg}";
2612 if (GPALEventType.ERROR == gPALEventType || GPALEventType.EXCEPTION == gPALEventType)
2613 if (
false == inPublishEvent &&
false == handlingTermination)
2617 inPublishEvent =
true;
2618 if (
true == gpalSettings.TakeEventScreenshot)
2619 if (typeof(
Browser.Browser) == gPALObject?.GetType())
2620 ((ImageHelper)GPAL.ImageHelper).
CaptureScreen(gPALObject).ToBitmap(out ss);
2622 ((ImageHelper)GPAL.ImageHelper).CaptureScreen().ToBitmap(out ss);
2632 inPublishEvent =
false;
2638 GPALEventType = gPALEventType,
2639 GPALObject = gPALObject,
2640 GPALObjectType = gPALObjectType,
2641 CurrentUOW = (Enums.GPALObjectType.UnitOfWork == gPALObjectType ? (
UnitOfWork)gPALObject :
null),
2642 Message = $
"{name}: {msg}",
2644 ExceptionRaised = ex,
2645 Data = (Enums.GPALObjectType.Converter == gPALObjectType ? gPALObject :
string.Empty),
2646 DateTimeStamp = dateTime
2650 if (
true == handlerWants)
2652 if (
true == toExceptionChannel)
2653 ExceptionHandler?.Invoke(gPALObject, args);
2655 InformationHandler?.Invoke(gPALObject, args);
2658 if (
true == controlWants)
2660 GPAL.PublishControl.AppendLine(outMessage, PublishControlMaxLines);
2663 if (
null != ex &&
true == gpalSettings.ControlEvents.HasFlag(GPALEventType.DEBUG))
2664 GPAL.PublishControl.AppendLine($
"[{ex.Message}]{stackTrace}", PublishControlMaxLines);
2667 if (
true == GPAL.PublishToConsole)
2670 if (gpalSettings.ConsoleEvents.HasFlag(gPALEventType) && Environment.GetEnvironmentVariable(
"GPAL_IS_SILENT") !=
"1")
2672 Console.WriteLine(outMessage);
2676 if (
null != ex && gpalSettings.ConsoleEvents.HasFlag(GPALEventType.DEBUG))
2677 Console.WriteLine($
"[{ex.Message}]{stackTrace}");
2681 if (
true == GPAL.PublishToDebug)
2683 if (gpalSettings.DebugEvents.HasFlag(gPALEventType) && Environment.GetEnvironmentVariable(
"GPAL_IS_SILENT") !=
"1")
2685 Debug.WriteLine(outMessage);
2688 if (
null != ex && gpalSettings.DebugEvents.HasFlag(GPALEventType.DEBUG))
2689 Debug.WriteLine($
"[{ex.Message}]{stackTrace}");
2697 if (0 < GPAL.PublishToLoggers.Count &&
true == Enum.TryParse(gPALEventType.ToString(), out Enums.LogType logType))
2699 if (
null == loggersWriting)
2700 loggersWriting =
new HashSet<IGPALLogger>();
2703 foreach (
IGPALLogger logger
in GPAL.PublishToLoggers.ToList())
2708 if (
true == loggersWriting.Contains(logger))
2713 loggersWriting.Add(logger);
2721 writer.Log(msg, name, logType);
2728 writer.Log($
"[{ex.Message}]{stackTrace}", name, Enums.LogType.DEBUG);
2736 loggersWriting.Remove(logger);
2743 if (Environment.GetEnvironmentVariable(
"GPAL_IS_SILENT") !=
"1")
2745 Console.Out.Flush();
2763 IDictionary<(TRow row, TCol col), TValue> data,
2764 string cornerLabel =
"",
2765 Func<TValue, string> formatCell =
null,
2766 string emptyCell =
"-")
2768 if (
null == data || 0 == data.Count)
2771 formatCell = formatCell ?? (v => v?.ToString() ??
string.Empty);
2773 var rows = data.Keys.Select(k => k.row).Distinct().OrderBy(r => r, Comparer<TRow>.Default).ToList();
2774 var cols = data.Keys.Select(k => k.col).Distinct().OrderBy(c => c, Comparer<TCol>.Default).ToList();
2776 string Cell(TRow r, TCol c) => data.TryGetValue((r, c), out var v) ? formatCell(v) : emptyCell;
2778 int rowHeaderWidth = cornerLabel.Length;
2779 foreach (var r
in rows)
2780 rowHeaderWidth = Math.Max(rowHeaderWidth, (r?.ToString() ??
string.Empty).Length);
2782 var colWidth =
new Dictionary<TCol, int>();
2783 foreach (var c
in cols)
2785 int w = (c?.ToString() ??
string.Empty).Length;
2786 foreach (var r
in rows)
2787 w = Math.Max(w, Cell(r, c).Length);
2791 var sb =
new StringBuilder();
2793 sb.AppendLine($
"=== {title} ===");
2795 sb.Append(cornerLabel.PadRight(rowHeaderWidth));
2796 foreach (var c
in cols)
2797 sb.Append(
" | " + (c?.ToString() ??
string.Empty).PadRight(colWidth[c]));
2800 sb.Append(
new string(
'-', rowHeaderWidth));
2801 foreach (var c
in cols)
2802 sb.Append(
"-+-" +
new string(
'-', colWidth[c]));
2805 foreach (var r
in rows)
2807 sb.Append((r?.ToString() ??
string.Empty).PadRight(rowHeaderWidth));
2808 foreach (var c
in cols)
2809 sb.Append(
" | " + Cell(r, c).PadRight(colWidth[c]));
2822 public static void EmitRuntimeTable(
string title, IDictionary<(BrowserType bt, AutomationEngine ae), TimeSpan> runtimes)
2823 => EmitTable(title +
" runtime (min:sec.ms)", runtimes,
"Browser",
2824 ts => $
"{(int)ts.TotalMinutes}:{ts.Seconds:D2}.{ts.Milliseconds:D3}");
2825 [GPALSettings(Description =
"Global Browser CallIfFound handler called for every selector in every Unit of Work")]
2826 #endregion <Helpers>
2827 #region <GPAL Settings>
2841 gpalSettings.AppCallIfFoundList.Add(callIfFound);
2849 [
GPALSettings(Description =
"Global Browser CallIfNotFound handler called for every selector in every Unit of Work")]
2852 gpalSettings.AppCallIfNotFoundList.Add(callIfNotFound);
2860 [
GPALSettings(Description =
"Global Browser CallIfFound handler called for every selector in every Unit of Work")]
2863 gpalSettings.CallIfFoundList.Add(callIfFound);
2871 [
GPALSettings(Description =
"Global Browser CallIfNotFound handler called for every selector in every Unit of Work")]
2874 gpalSettings.CallIfNotFoundList.Add(callIfNotFound);
2882 [
GPALSettings(Description =
"Print specified GPAL events to the console. [none (default)]")]
2883 public static IAllowGPALSettings WithPublishToConsole(GPALEventType eventType = GPALEventType.INFO | GPALEventType.WARNING | GPALEventType.ERROR | GPALEventType.EXCEPTION | GPALEventType.NOTICE | GPALEventType.CAUTION | GPALEventType.FAILURE)
2885 GPALSettings.ConsoleEvents = eventType;
2886 if (GPALEventType.NONE == eventType)
2887 GPALSettings.PublishToConsole =
false;
2889 GPALSettings.PublishToConsole =
true;
2909 [
GPALSettings(Description =
"Write specified GPAL events to a text area on a form. [none (default)]")]
2912 GPALSettings.PublishControl = control;
2927 [
GPALSettings(Description =
"Which GPAL events reach the form control. [all (default)]")]
2930 GPALSettings.ControlEvents = eventTypes;
2944 [
GPALSettings(Description =
"Which GPAL events reach the information handler. [all (default)]")]
2947 GPALSettings.InformationHandlerEvents = eventTypes;
2961 [
GPALSettings(Description =
"Which GPAL events reach the exception handler. [all (default)]")]
2964 GPALSettings.ExceptionHandlerEvents = eventTypes;
2973 [
GPALSettings(Description =
"Print specified GPAL events to the output window in VisualStudio. [none (default)]")]
2974 public static IAllowGPALSettings WithPublishToDebug(GPALEventType eventType = GPALEventType.INFO | GPALEventType.WARNING | GPALEventType.ERROR | GPALEventType.EXCEPTION | GPALEventType.NOTICE | GPALEventType.CAUTION | GPALEventType.FAILURE)
2976 GPALSettings.DebugEvents = eventType;
2977 if (GPALEventType.NONE == eventType)
2978 GPALSettings.PublishToDebug =
false;
2980 GPALSettings.PublishToDebug =
true;
2990 [
GPALSettings(Description =
"Publish GPAL events to a logger, which writes them to whatever it was given: a file or a database.")]
2993 GPALSettings.WithPublishToLogger(logger);
3001 [
GPALSettings(Description =
"Stop publishing GPAL events to a logger that was previously given one.")]
3004 GPALSettings.RemoveLogger(logger);
3022 [
GPALSettings(Description =
"Which GPAL events reach an attached Information or Exception handler. [All (default)]")]
3025 GPALSettings.InformationHandlerEvents = eventTypes;
3026 GPALSettings.ExceptionHandlerEvents = eventTypes;
3034 [
GPALSettings(Description =
"Print stack trace when PublishToConsole or PublishToDebug is true. [true (default)]")]
3037 GPALSettings.PublishStackTrace = trueFalse;
3049 [
GPALSettings(Description =
"Callback for failures a workflow can decide about, used by any browser without its own CallOnFail")]
3052 GPALSettings.CallOnFailHandlers.Add(callOnFail);
3061 [
GPALSettings(Description =
"Substitue string when data cannot be retrieved for an element [##UNABLE TO GET## (default)]")]
3064 GPALSettings.ErrorPlaceholder = message;
3073 [
GPALSettings(Description =
"Set the default timeout for waiting for a download to start.")]
3076 GPALSettings.DownloadTimeoutInSec = seconds;
3087 [
GPALSettings(
"DO NOT use GPAL fallback actions on failure, just fail. Usually involves javascript recovery attempt. [false (default)")]
3090 GPALSettings.NoFallbackRecoveryActions = trueFalse;
3098 [
GPALSettings(Description =
"Global value for selector matches so it's not set UOW at a time")]
3101 GPALSettings.WithAllThatMatch = matchCount;
3111 [
GPALSettings(Description =
"Automatically download and unzip the web driver that matches the version of the browser being run")]
3114 GPALSettings.AutoUpdateWebDriver = trueFalse;
3123 [
GPALSettings(Description =
"Set the automation type to use for all browsers")]
3126 GPALSettings.AutomationEngine = automationEngine;
3136 [
GPALSettings(Description =
"Global location for browser drivers. [./ (default)(same dir as exe)]")]
3150 [
GPALSettings(Description =
"Where GPAL writes files it created itself and nobody asked to keep. [GPALfilesSafeToDelete beside the exe (default)]")]
3161 internal static string TempDirectory()
3163 string tempPath =
true ==
string.IsNullOrWhiteSpace(
GPALSettings.TempDirectory)
3164 ? Path.Combine(AppDomain.CurrentDomain.BaseDirectory,
"GPALfilesSafeToDelete") +
@"\"
3167 if (
false == Directory.Exists(tempPath))
3168 Directory.CreateDirectory(tempPath);
3207 [GPALSettings(Description =
"Intercharacter typing delay ceiling [0ms (default), no pacing]")]
3210 GPALSettings.WithTypingDelay(delayInTicks);
3225 [
GPALSettings(Description =
"Image matching similarity percentage. [80 (default)]")]
3228 GPALSettings.WithImageMatchingPercentage(matchPercent);
3252 [
GPALSettings(Description =
"Nodes a YAML payload may hold before aliases are dropped for shared references. A cyclic payload always keeps them. [5000 (default), 0 never drops]")]
3255 GPALSettings.WithYamlAliasLimit(nodeLimit);
3271 [
GPALSettings(Description =
"Simulate moving the mouse for every action (implies .WithHardware). [false (default)]")]
3274 GPALSettings.SimulateMouse = trueFalse;
3294 [
GPALSettings(Description =
"Stop workflow if any selector is not found")]
3297 GPALSettings.StopOnNotFound = trueFalse;
3301 [
GPALSettings(Description =
"Set the default location to store temporary profiles if browser.WithProfileDataDirectory is not used. default [C:\\profiles]")]
3302 public static IAllowGPALSettings WithTempProfileParentDirectory(
string tempProfileDirectory)
3306 GPALSettings.TempProfileDirectory = Environment.ExpandEnvironmentVariables(tempProfileDirectory);
3323 [GPALSettings(Description =
"Handler to receive GPAL Exception events")]
3326 ExceptionEventHandler = eventHandler;
3327 Exception ex =
new Exception(
"Welcome Exception :)");
3328 GPAL.PublishSimpleEvent(Enums.GPALEventType.EXCEPTION, $
"Welcome to GPAL [{Version}] Exception Channel",
null, Enums.GPALObjectType.None, ex);
3337 [
GPALSettings(Description =
"Print GPAL published information or exception messages to the output window in VisualStudio. [true (default)]")]
3340 GPALSettings.PromptBeforeUnexpectedExit = trueFalse;
3355 [
GPALSettings(Description =
"Handler to receive GPAL Information events")]
3358 InformationEventHandler = eventHandler;
3359 GPAL.PublishSimpleEvent(Enums.GPALEventType.INFO, $
"Welcome to GPAL [{Version}] Information Channel");
3374 [
GPALSettings(Description =
"Global setting to wait for time in ticks for an element to show up")]
3377 GPALSettings.WaitForInMs = waitForInTicks;
3381 [
GPALSettings(Description =
"Take a screenshot with each published event")]
3384 GPALSettings.TakeEventScreenshot = trueOrFalse;
3389 #endregion <GPAL Settings>
3392 private static void CheckVersions()
3394 if (
string.Empty.Equals(tmpBrowser?.BrowserVersion))
3396 BrowserType browserType = tmpBrowser.BrowserType;
3398 if (BrowserType.Chrome == browserType)
3400 DriverHelper.GetChromeVersion(out tmpBrowser.BrowserSettings.Version);
3402 else if (BrowserType.Edge == browserType)
3404 DriverHelper.GetEdgeVersion(out tmpBrowser.BrowserSettings.Version);
3406 else if (BrowserType.FireFox == browserType)
3408 DriverHelper.GetFirefoxVersion(out tmpBrowser.BrowserSettings.Version);
3438 private static void SetCatchUncaughtExceptions()
3440 if (
false == UncaughtExceptionHandlerSet)
3447 System.Windows.Forms.Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException);
3450 AppDomain.CurrentDomain.UnhandledException +=
3451 new UnhandledExceptionEventHandler(UncaughtExceptionHandler);
3454 Console.CancelKeyPress += OnCancelKeyPress;
3455 AppDomain.CurrentDomain.ProcessExit += OnProcessExit;
3458 catch (Exception ex)
3460 PublishSimpleEvent(GPALEventType.EXCEPTION, $
"Unable to set uncaught exception handler",
null, Enums.GPALObjectType.None, ex);
3463 UncaughtExceptionHandlerSet =
true;
3467 private static bool handlingTermination =
false;
3468 private static void UncaughtExceptionHandler(
object sender, UnhandledExceptionEventArgs args)
3470 Exception e = (Exception)args.ExceptionObject;
3472 if (
false == handlingTermination)
3474 handlingTermination =
true;
3478 bool ours = e is GPALException;
3479 string reason =
true == ours ?
"GPAL exception" :
"uncaught exception";
3481 if (ConsoleEvents.HasFlag(GPALEventType.WARNING))
3483 PublishSimpleEvent(GPALEventType.WARNING, $
">>> Caught {reason}: [{e.Message}][{e.StackTrace}]",
null, Enums.GPALObjectType.None);
3484 PublishSimpleEvent(GPALEventType.WARNING, $
">>> [{reason}] Cleaning up before terminating.",
null, GPALObjectType.None);
3486 else if (ConsoleEvents.HasFlag(GPALEventType.CAUTION))
3488 PublishSimpleEvent(GPALEventType.CAUTION, $
">>> Caught {reason}: [{e.Message}][{e.StackTrace}]",
null, Enums.GPALObjectType.None);
3489 PublishSimpleEvent(GPALEventType.CAUTION, $
">>> [{reason}] Cleaning up before terminating.",
null, GPALObjectType.None);
3492 if (
false == PublishToConsole)
3493 GPAL.PublishSimpleEvent(GPALEventType.NOTICE, $
"Terminating due to [{reason}]: [{e.Message}]");
3495 if (
false == PublishToDebug)
3496 Debug.WriteLine($
"Terminating due to {reason}: [{e.Message}]");
3498 CleanupAndExit(
true == ours ?
"GPAL Exception" :
"Unhandled Exception");
3502 private static void OnCancelKeyPress(
object sender, ConsoleCancelEventArgs e)
3506 if (
false == handlingTermination)
3508 handlingTermination =
true;
3512 if (
false == PublishToConsole)
3513 GPAL.PublishSimpleEvent(GPALEventType.NOTICE, $
"Terminating due to Ctrl+C or Ctrl+Break.");
3515 if (
false == PublishToDebug)
3516 Debug.WriteLine($
"Terminating due to Ctrl+C or Ctrl+Break.");
3518 CleanupAndExit(
"Ctrl+C or Ctrl+Break");
3522 private static void OnProcessExit(
object sender, EventArgs e)
3526 if (
false == handlingTermination)
3528 handlingTermination =
true;
3530 if (
false == PublishToConsole)
3531 GPAL.PublishSimpleEvent(GPALEventType.NOTICE, $
"Terminating due to Process Exit or console X.");
3533 if (
false == PublishToDebug)
3534 Debug.WriteLine($
"Terminating due to Process Exit or console X.");
3536 CleanupAndExit(
"Process Exit or console X");
3540 private static bool _cleanupDone =
false;
3542 internal static void CleanupAndExit(
string reason)
3544 if (
false == _cleanupDone)
3546 _cleanupDone =
true;
3549 if (ConsoleEvents.HasFlag(GPALEventType.INFO))
3550 PublishSimpleEvent(GPALEventType.INFO, $
">>> [{reason}] Cleaning up before terminating.",
null, GPALObjectType.None);
3551 else if (ConsoleEvents.HasFlag(GPALEventType.NOTICE))
3552 PublishSimpleEvent(GPALEventType.NOTICE, $
">>> [{reason}] Cleaning up before terminating.",
null, GPALObjectType.None);
3554 if (
false == PublishToConsole)
3555 GPAL.PublishSimpleEvent(GPALEventType.NOTICE, $
"[{reason}] Cleaning up before terminating.");
3557 if (
false == PublishToDebug)
3558 Debug.WriteLine($
"[{reason}] Cleaning up before terminating.");
3560 BrowserHelper.KillAllRunningProcesses(
true,
null);
3564 GenerallyPositive.Browser.HiddenDesktop.CloseAll();
3566 catch (Exception ex)
3568 PublishSimpleEvent(GPALEventType.EXCEPTION, $
"Cleanup error",
null, GPALObjectType.None, ex);
3573 string endTime = DateTime.Now.ToString(
"yyyy-MM-dd HH:mm:ss");
3574 TimeSpan totalRuntime = _appTimer.Elapsed;
3575 string formattedRuntime = $
"{totalRuntime.Hours:D2}:{totalRuntime.Minutes:D2}:{totalRuntime.Seconds:D2}.{totalRuntime.Milliseconds:D3}";
3577 if (ConsoleEvents.HasFlag(GPALEventType.INFO))
3579 PublishSimpleEvent(GPALEventType.INFO, $
">>> Application End Time: [{endTime}] <<<",
null, GPALObjectType.None);
3580 PublishSimpleEvent(GPALEventType.INFO, $
">>> Total Runtime: [{formattedRuntime}] <<<",
null, GPALObjectType.None);
3582 else if (ConsoleEvents.HasFlag(GPALEventType.NOTICE))
3584 PublishSimpleEvent(GPALEventType.NOTICE, $
">>> Application End Time: [{endTime}] <<<",
null, GPALObjectType.None);
3585 PublishSimpleEvent(GPALEventType.NOTICE, $
">>> Total Runtime: [{formattedRuntime}] <<<",
null, GPALObjectType.None);
3592 if (
true == GPALSettings.PromptBeforeUnexpectedExit)
3594 GPAL.PublishSimpleEvent(GPALEventType.NOTICE,
"Press any key to exit...");
3595 Debug.WriteLine(
"Press any key to exit...");
3601 if (
true == reason.Equals(
"Process Exit or console X"))
3602 Environment.Exit(0);
3604 Environment.Exit(0xdead);
3606 #endregion <Private>
Application object that contains the fluent methods to create your Application workflow....
Browser object that contains the fluent methods to create your Browser workflow. Instatiated using G...
Represents a URL with optional pre-navigation storage cleanup / inspection actions....
Fluent YouTube video uploader. Entry point: GPAL.YouTube. Upload phase: WithCredentials -> WithTitle ...
File-side plumbing behind the fluent chain: writing a unit of work's data out in a delimited format,...
static string EnsureDirectoryEndsWithBackslash(string directoryPath)
Adds a trailing backslash to a directory path when it does not already have one, so the path can be c...
Used to pass objects of interest when publishing an Information or Exception Channel message NOTE: P...
List< GPALElement > WebElements
List of WebElements returned for the given Browser Selector.
IWebDriver BrowserDriver
The browser driver instantiated and used to connect to the browser.
IGPALGrid< string > Tokens
GPALGrid [rows/columns] of tokens being used to fill input.
string Message
The Message being published to the Information/Exception channel.
GPALElement GPALElement
The current web element.
SelectorSettings.SelectorPathEntry SelectorPathEntry
The SelectorPathEntry is the current path (css, xpath, text, image, etc) being evaluated/used to find...
SqlCommand SqlCommand
SqlCommand which threw an exception.
Exception ExceptionRaised
The Exception being published on the Exception channel.
Image ScreenShot
Every message is accompanied by an automatic screenshot in case this additional information provides ...
List< IGPALGrid< string > > TokenList
List of Grids associated with GPALFile.
UnitOfWork CurrentUOW
The Current Unit of Work for the GPALObject supplied. GPALObject (depending upon context) might also...
Selector Selector
The current Selector being used.
DateTime DateTimeStamp
The date/time this event is published.
AutomationElement AutomationElement
The current AutomationElement.
List< GPALAutomationElement > AutomationElements
List of AutomationElements returned for the given Application Selector.
Enums.GPALObjectType GPALObjectType
GPALObjectType enumeration: None, Application, Browser, GPALForm, UnitOfWork.
dynamic Data
Any type of data that does not fite in the above, converter data, for example.
dynamic GPALObject
Current context's Application, Browser, GPALForm, UnitOfWork object.
The Windows clipboard. There is one per machine, so this is a standalone object rather than something...
Class to define database usage. Currently only used for input from a table, sql or stored procedure....
Provides fluent, file-based automation of Excel workbooks: opening one or more workbooks (including w...
GPAL File object instantied with GPAL.File Used to load tokens into a GPALGrid [rows/columns].
List< string > Filenames
Get the list of filenames.
A read-only display control for rendering simple Markdown - headings (#, ##, ###),...
A GPAL multiline textare instantiated with GPAL.TextArea for use on GPAL forms. Callback EventHandle...
static byte VK_ALT
Alt key virtual keycode (VK) for use with keybd_event. https://docs.microsoft.com/en-us/windows/win32...
static IAllowProgressBarControlSettings ProgressBar
A progress bar control for GPAL forms. Displays task completion percentage or indeterminate (marquee...
static IAllowMenuBarControlSettings MenuBar
A menu bar docked to the top of a GPAL form. Open a top-level menu with WithMenu("TopMenu"),...
static IAllowGPALSettings WithNoFallbackActions(bool trueFalse=true)
GPAL has fallback alternatives for actions should they fail, generally applies to selenium....
static IAllowGPALSettings WithHandlerEvents(GPALEventType eventTypes)
Which event types reach the handlers given to WithInformationHandler and WithExceptionHandler....
static IAllowControlSettingsAndChecked Checkbox
Instantiates a new GPALCheckbox for use on a GPAL form. Callback EventHandler is invoked on the GPAL...
static byte VK_END
End key virtual keycode (VK) for use with keybd_event.
static byte VK_F10
F10 key virtual keycode (VK) for use with keybd_event.
static IAllowGPALSettings RemoveLogger(IGPALLogger logger)
Stops publishing events to a logger.
static Browser.IHiddenDesktops HiddenDesktop
Every hidden desktop this process has made, and the screen itself. Peek puts one on the screen and pu...
static IAllowRichTextBoxControlSettings RichTextBox
Instantiates a new GPALRichTextBox for use on a GPAL form. Renders Markdown (headings,...
static IAllowApplicationOpenOrParameters Application
Instantiates a new fluent Application object.
static GPALSpliter SplitRight
Marks the end of a splitter's left pane. Everything added after it is the right pane.
static IAllowControlSettingsAndChartSettings Chart
Instantiates a new GPALChart for use on GPAL forms. Callback EventHandler is invoked on the GPALChar...
static IAllowLoggingSettings Logger
New GPAL Logger.
static IAllowSelectorSettings Selector
Instantiates a new fluent GPAL Selector object used to locate an element. Selectors are for browsers...
static IAllowGraphicSettings CaptureScreen(Browser.IBrowser browser)
Take a screenshot.
static IAllowGPALSettings WithPublishToDebug(GPALEventType eventType=GPALEventType.INFO|GPALEventType.WARNING|GPALEventType.ERROR|GPALEventType.EXCEPTION|GPALEventType.NOTICE|GPALEventType.CAUTION|GPALEventType.FAILURE)
Indicate which event types to print to the console. Default is none.
static IAllowConverterInput Converter
New GPAL Convertor.
static byte VK_LMENU
Left Alt key virtual keycode (VK) for use with keybd_event.
static IAllowGPALSettings WithInformationHandler(EventHandler< GPALEventArgs > eventHandler)
Set the handler to receive Information messages from GPAL which you might like to know about....
static void EmitTable< TRow, TCol, TValue >(string title, IDictionary<(TRow row, TCol col), TValue > data, string cornerLabel="", Func< TValue, string > formatCell=null, string emptyCell="-")
Emits an ASCII table for any 2-axis keyed dictionary as a single INFO event: row keys down the side,...
static GPALSpliter SplitBottom
Marks the end of a splitter's top pane. Everything added after it is the bottom pane.
static Browser.IAllowElementSetting ElementAssistant(Selector selector)
Instantiates a new Browser ElementAssistant object with fluent methods to help you manipulate WebElem...
static byte VK_BACK
Backspace key virtual keycode (VK) for use with keybd_event.
static IAllowGPALSettings CallIfFound(Browser.Browser.CallIfDelegate callIfFound)
Global Browser CallIfFound handler called for every selector in every Unit of Work.
static IAllowPictureControlSettings Picture
A picture control for GPAL forms. Shows an image, from a file or from an Image already in hand....
static IAllowGPALSettings WithPublishStackTrace(bool trueFalse=true)
Print the stack trace along with the published GPAL message.
static IAllowToolbarControlSettings Toolbar
A toolbar docked below the menu bar, holding GPAL.BarItem buttons and optional separators.
static IAllowDateTimePickerControlSettings DateTimePicker
Instantiates a new GPALDateTimePicker for use on a GPAL form. Callback EventHandler is invoked on th...
static uint KEYEVENTF_EXTENDEDKEY
The extended-key flag indicates whether the keystroke message originated from one of the additional k...
static IAllowControlSettingsPlaceholderAndPassword Input
Instantiates a new one-line GPALInput control for use on a GPAL form. Callback EventHandler is invok...
static byte VK_RWIN
Right Windows key virtual keycode (VK) for use with keybd_event.
static Application.IAllowForSelector ElementAssistant(Application.Application application)
Instantiates a new Application ElementAssistant with fluent methods to help you manipulate Automation...
static IAllowSplitterControlSettings Splitter
Instantiates a new GPALSplitter for use on a GPAL form: two panes with a bar between them,...
static IAllowFormSettings Form
Instantiates a new GPALForm for creating simple interactive user interfaces.
static IAllowGridActions< string > Grid
New GPALGrid<string></string> (rows/columns).
static IAllowControlSettingsAndChecked RadioButton
Instantiates a new GPALRadioButton for use on a GPAL form. Callback EventHandler is invoked on the G...
static IAllowComboBoxControlSettings ComboBox
Instantiates a new GPALComboBox for use on a GPAL form. Callback(s) set via WhenSelectedDo are invok...
static IAllowBarItemSettings BarItem
A single item shared by menu bars and toolbars: text, optional image, optional shortcut key,...
static string OAuthTokenUrl
Where an OAuth redirect lands and the token is read back from, e.g. http://localhost:3117/....
static byte VK_RETURN
Enter/Return key virtual keycode (VK) for use with keybd_event.
static byte VK_SCROLL
Scroll Lock key virtual keycode (VK) for use with keybd_event.
static IAllowControlSettingsAndDefault Button
Instantiates a new GPALButton for use on GPAL forms. Callback EventHandler is invoked on the GPALBut...
static byte VK_DOWN
Down Arrow key virtual keycode (VK) for use with keybd_event.
static IAllowDataGridViewControlSettings DataGridView
Instantiates a new GPALDataGridView for use on a GPAL form. Callback EventHandler is invoked on the ...
static IAllowGPALSettings AppCallIfFound(Application.Application.CallIfDelegate callIfFound)
Global Browser CallIfFound handler called for every selector in every Unit of Work.
static IAllowRequestSettings Request
Start describing an API request for .Fetch to issue from inside the page, so it carries the session t...
static IAllowGPALSettings WithPublishToControl(GPALTextArea control)
Writes GPAL events to a text area on a form, as WithPublishToConsole does to a console....
static IAllowRESTEndpoint RESTClient
Instantiate a new fluent RESTClient.
static IAllowGPALSettings WithPublishToLogger(IGPALLogger logger)
Print the published information or exception messages to the supplied database. Uses Database Create ...
static IAllowGPALSettings CallOnFail(Browser.Browser.CallOnFailDelegate callOnFail)
Add a handler to be called when something fails that the workflow is in a position to decide about,...
static byte VK_CONTROL_LEFT
Left Control key virtual keycode (VK) for use with keybd_event.
static byte VK_SHIFT_RIGHT
Right Shift key virtual keycode (VK) for use with keybd_event.
static string MyMethodName()
Returns the calling methods name (used in Information/Exception messages). Instead of harcoding meth...
static IAllowControlSettingsAndUrl LinkLabel
Instantiates a new GPALLinkLabel for use on a GPAL form: a link that opens its address in the default...
static byte VK_SHIFT_LEFT
Left Shift key virtual keycode (VK) for use with keybd_event.
static IAllowControlSettingsAndFontSettings Label
Instantiates a new GPALLabel for use on a GPAL form. Callback EventHandler is invoked on the GPALLab...
static Selector CssSelector(string css, string selectorName=null)
Helper for shorthand notation.
static IAllowListViewControlSettings ListView
Instantiates a new GPALListView for use on a GPAL form. Callback EventHandler is invoked on the GPAL...
static IAllowGPALSettings WithExceptionHandler(EventHandler< GPALEventArgs > eventHandler)
Set the handler to receive handled Exception messages from GPAL. GPAL also sets an unhandled excepti...
static IAllowGPALSettings WithWaitFor(int waitForInTicks)
Global setting to wait for time in ticks for an element to show up. Applied to every element in every...
static IAllowGPALSettings AppCallIfNotFound(Application.Application.CallIfDelegate callIfNotFound)
Global Browser CallIfNotFound handler called for every selector in every Unit of Work.
static IAllowGPALSettings CallIfNotFound(Browser.Browser.CallIfDelegate callIfNotFound)
Global Browser CallIfNotFound handler called for every selector in every Unit of Work.
static IAllowTreeViewControlSettings TreeView
Instantiates a new GPALTreeView for use on a GPAL form. Callback EventHandler is invoked on the GPAL...
static byte VK_APPS
Application (Menu) key virtual keycode (VK) for use with keybd_event.
static byte VK_NEXT
Page Down key virtual keycode (VK) for use with keybd_event.
static void EmitRuntimeTable(string title, IDictionary<(BrowserType bt, AutomationEngine ae), TimeSpan > runtimes)
Convenience wrapper over EmitTable<TRow,TCol,TValue> for test-program bt/ae[/headless] loops: browser...
static IAllowGPALSettings WithAutoUpdateWebDriver(bool trueFalse=true)
Automatically download and unzip the web driver that matches the version of the browser being run....
static IAllowGPALSettings WithControlEvents(GPALEventType eventTypes)
Which event types reach the control given to WithPublishToControl. Defaults to all....
static IAllowNumericUpDownControlSettings NumericUpDown
Instantiates a new GPALNumericUpDown for use on a GPAL form. Callback EventHandler is invoked on the...
static IAllowCredentialServiceType Credentials
Return a new credential manager.
static IAllowGPALSettings WithAutomationEngine(AutomationEngine automationEngine)
Set the automation type to use for all browsers. NOTE: can be overridden at the selector level (to ch...
static IAllowSliderControlSettings Slider
A slider control for GPAL forms. Picks a number from a range by dragging, and exposes that range to ...
static IAllowEmailServerSettings Mail
New GPAL Mail handler.
static IAllowGPALSettings WithStopOnNotFound(bool trueFalse=true)
Global setting instructing GPAL to terminate if any Selector cannot find any elements....
static IAllowGPALSettings WithPublishToConsole(GPALEventType eventType=GPALEventType.INFO|GPALEventType.WARNING|GPALEventType.ERROR|GPALEventType.EXCEPTION|GPALEventType.NOTICE|GPALEventType.CAUTION|GPALEventType.FAILURE)
Print the published information or exception messages to the console.
static IAllowGPALSettings WithImageMatchingPercentage(int matchPercent)
Sets the image matching percentage for image Selectors. .
static IAllowControlSettings Tab
Instantiates a new GPALTab for use on a GPAL form. Callback EventHandler is invoked on the GPALTab....
static IAllowGPALSettings WithExceptionHandlerEvents(GPALEventType eventTypes)
Which event types reach the handler given to WithExceptionHandler. Defaults to all.
static IAllowGPALSettings WithYamlAliasLimit(int nodeLimit)
How many nodes a YAML payload may hold before GPAL stops writing aliases for shared references....
static byte VK_LWIN
Left Windows key virtual keycode (VK) for use with keybd_event.
static IAllowGPALSettings WithDefaultErrorPlaceholder(string message="##UNABLE TO GET##")
When GPAL is unable to retrieve data from an element, this message will be placed in the grid....
static IAllowGPALSettings WithDownloadTimeoutInSec(int seconds)
Set the default timeout time in seconds to wait for a download to start The default is 60 seconds.
static byte VK_UP
Up Arrow key virtual keycode (VK) for use with keybd_event.
static IAllowAIProvider AI
Entry point for the GPAL AI subsystem, providing a fluent interface for AI tasks.
static byte VK_SPACE
Space bar key virtual keycode (VK) for use with keybd_event.
static void PublishSimpleEvent(GPALEventType gPALEventType, string msg, dynamic gPALObject=null, Enums.GPALObjectType gPALObjectType=GPALObjectType.None, Exception ex=null)
Publish a message to either the information channel or exception channel (if exception passed in) Pub...
static byte VK_DELETE
Delete key virtual keycode (VK) for use with keybd_event.
static IAllowGPALSettings WithTempDirectory(string tempPath)
Where GPAL puts files it had to create but nobody asked to keep, such as a GPALFile given a url rathe...
static IAllowGPALSettings WithSimulateMouseMovement(bool trueFalse=true)
Global setting to simulate a human moving the mouse to the next point for all commands....
static IAllowStatusStripControlSettings StatusStrip
A status strip control (docked at the bottom) for GPAL forms. Displays real-time status messages,...
static IAllowDriveCredentials GoogleDrive
New GoogleDrive workflow.
static IAllowGroupBoxControlSettings GroupBox
Instantiates a new GPALGroupBox for use on a GPAL form: a titled box around a set of controls,...
static byte VK_PRIOR
Page Up key virtual keycode (VK) for use with keybd_event.
static IAllowClipboardInput Clipboard
Instantiates a new fluent Database SETTINGS object. This data object defines settings for use by ....
static IAllowControlSettingsAndPlaceholder TextArea
Instantiates a new GPALTextArea for use on a GPAL form. Callback EventHandler is invoked on the GPAL...
static Browser.IAllowScheduledWorkflow Workflow
Runs whole workflows at once, each building and owning whatever it drives, so one can run Chrome on O...
static IAllowGPALSettings WithAllThatMatch(int matchCount=int.MaxValue)
Global value for selector matches so it's not set UOW at a time.
static byte VK_TAB
Tab key virtual keycode (VK) for use with keybd_event.
static uint KEYEVENTF_KEYUP
Indicates a keyup keystroke is being sent. For use with keybd_event.
static IAllowGPALSettings WithDriverLocation(string driverPath)
The location of the browser drivers to be used for each GPAL.Browser instance. This can be overridde...
static IAllowBrowserTypeOrGoto Browser
Instantiates a new fluent Browser object.
static IAllowGPALSettings WithTypingDelay(int delayInTicks)
Sets the ceiling for the inter-character typing delay used by SendString across every automation engi...
static IAllowGPALSettings WithPromptBeforeUnexpectedExit(bool trueFalse=true)
Prompt 'Press any key...' before terminating due to an uncaught exception. GPAL tries to handle all e...
static IAllowGPALSettings WithInformationHandlerEvents(GPALEventType eventTypes)
Which event types reach the handler given to WithInformationHandler. Defaults to all.
static byte VK_HOME
Home key virtual keycode (VK) for use with keybd_event.
static IAllowFileSelectorControlSettings FileSelector
Instantiates a new GPALFileSelector for use on a GPAL form. Opens a standard file or folder selectio...
static byte VK_RMENU
Right Alt key virtual keycode (VK) for use with keybd_event.
static byte VK_CONTROL_RIGHT
Right Control key virtual keycode (VK) for use with keybd_event.
static IAllowSpreadsheetSelection GoogleSheets
New Googlesheets workflow.
static IAllowFileName File
Instantiates a new fluent File SETTINGS object. This data object defines settings for use by the ....
Provides configurable logging to a file (in any format supported by GPALConverter) or to a GPALDataba...
Provides a fluent API for configuring, sending, and receiving email via SMTP, IMAP,...
Describes an API request for .Fetch to issue from inside the page, so it carries the session the brow...
GPAL Selector used to locate Application and Browser elements. Instantiated with GPAL....
Browser.Browser Browser
Browser associated with this selector.
IAllowSelectorSettings WithXPath(string xPath)
Define XPath used to find elements Both.
An entry defining a selector locator, a selector path.
Everything revolves around the Unit of Work. A Unit of Work is defined as one or more selectors betw...
Starting interface - only allows setting the target URL.
Every hidden desktop this process has made, and the screen itself. Peek and Return move the screen,...
What a database is, not what to do with it: the connection, the command, and the definitions of the p...
Finds a picture on a capture of the screen or of a browser. The GPAL.Image package provides one and r...