GPAL's philosophy is to publish, not persist. Every significant operation, element found, not found, action taken, exception raised, publishes an event. What you do with those events is entirely up to you: write to a file, insert to a database, display in a UI, send an email, or ignore them entirely. GPAL imposes nothing. An event carries a GPALEventType, and everything that receives events subscribes to the types it wants.
GPALEventType is a flags enum, so a subscription is a set of types rather than a single level. The individual types are INFO, WARNING, ERROR, EXCEPTION, DEBUG, DEEPDEBUG, NOTICE, CAUTION, and FAILURE.
Two named combinations save you spelling out the common cases. GPALALL is what GPAL itself raises: INFO, WARNING, ERROR and EXCEPTION. USERALL is what your workflow raises: NOTICE, CAUTION, FAILURE and EXCEPTION.
The split matters because a workflow wants to see its own story without GPAL's running commentary underneath it.
Publish your own events with GPAL.PublishSimpleEvent, which captures the calling method name for you, so your events arrive with the same context as GPAL's own.
// Handlers of your own, one for each channel
GPAL
// Or the built-in ones, told which types they want
GPAL
GPAL
GPAL
// Publish your own event into the same stream
GPAL
// Dynamic values in a message go in brackets, so a message reads the same whatever is in them
GPAL
WithPublishToConsole and WithPublishToDebug both default to every type worth reading, so calling them with no argument is the quick way to see everything. Pass a type set once you know which half of the story you are watching. A logger is attached the same way, with GPAL.WithPublishToLogger.
An event is published by the thread that raised it, which during a workflow is rarely the one your form is running on. A handler that writes into a control is therefore writing across threads. GPAL's own controls take care of that, and a text control's AppendLine is the one to reach for, because it queues the line and returns. What a handler must not do is wait for the UI thread: a workflow started from a button owns that thread until it finishes, so anything that blocks on it waits for a thread that is waiting for the workflow, and neither moves again.
GPALEventArgs contains: GPALEventType, Message, DateTimeStamp, the current UOW and Selector, GPALObject (the Browser or Application that raised the event), the matched element list, ExceptionRaised on EXCEPTION events, Tokens and TokenList for data-bearing events, and a ScreenShot. The screenshot is the one thing that is not free and it is off until asked for: WithTakeEventScreenshot(true) turns it on, and even then it is taken only on ERROR and EXCEPTION, where seeing what was on screen when something failed is worth what it costs.
// both channels, because an ERROR with no exception is not an exception event
GPAL
// what a handler is for: read the context, decide, and let the workflow know
static bool givenUp = false;
static void OnGPALInfo(object sender, GPAL
{
// the selector and the unit of work say what GPAL was doing, not just that it went wrong
if (GPALEventType
GPAL
$"[{args
// a message the workflow cares about is a place to stop, and the workflow reads the flag
if (true == args
givenUp = true;
}
static void OnGPALException(object sender, GPAL
{
// the elements are the evidence: what was found, and what it looked like
foreach (GPALElement element in args
GPAL
args
givenUp = true;
}
There are two handlers and an event goes to exactly one of them. It goes to the exception handler when it carries an exception or is typed EXCEPTION, and to the information handler otherwise. The level is not what decides: an ERROR published without an exception is an ordinary message about something that went wrong, and it arrives at the information handler. A workflow that attaches only WithExceptionHandler therefore sees none of its ERRORs, which is the difference between a failure you can read and a program that appears to do nothing. Attach both. Each has its own set of types, WithInformationHandlerEvents and WithExceptionHandlerEvents, and both start as every type. Narrow them when a handler is only interested in part of the story, and remember that narrowing the information handler is what silences DEBUG rather than turning DEBUG off.
If nothing is attached, every event is discarded. GPAL will never create log files, write to disk, or output to console on its own. Attach a handler, a console, or a logger before starting a workflow, or the run leaves no trace of itself.
Showing off some plain text in these paragraphs eligendi laboriosam illo nostrum corporis at libero vel voluptas? Expedita, facere dolores voluptatem ad ab rem assumenda soluta!
Lorem ipsum dolor sit amet consectetur adipisicing elit. Obcaecati, iste distinctio veritatis eligendi laboriosam illo nostrum corporis at libero vel voluptas? Expedita, facere dolores voluptatem ad ab rem assumenda soluta!
Lorem ipsum dolor sit amet consectetur adipisicing elit. Obcaecati, iste distinctio veritatis eligendi laboriosam illo nostrum corporis at libero vel voluptas? Expedita, facere dolores voluptatem ad ab rem assumenda soluta!
Lorem ipsum dolor sit amet consectetur adipisicing elit. Quo veniam mollitia excepturi animi eum illum non libero sapiente provident assumenda, delectus voluptatum nobis sed dolorem adipisci laudantium incidunt. Error, ratione?
Lorem ipsum dolor sit amet consectetur adipisicing elit. Quo veniam mollitia excepturi animi eum illum non libero sapiente provident assumenda, delectus voluptatum nobis sed dolorem adipisci laudantium incidunt. Error, ratione?
Lorem ipsum dolor sit amet consectetur adipisicing elit. Quo veniam mollitia excepturi animi eum illum non libero sapiente provident assumenda, delectus voluptatum nobis sed dolorem adipisci laudantium incidunt. Error, ratione?
Lorem ipsum dolor sit amet consectetur adipisicing elit. Quo veniam mollitia excepturi animi eum illum non libero sapiente provident assumenda, delectus voluptatum nobis sed dolorem adipisci laudantium incidunt. Error, ratione?
Here you can find different accents and emphasis sit amet consectetur adipisicing elit. Obcaecati, iste distinctio veritatis eligendi laboriosam illo nostrum corporis at libero vel voluptas? Expedita, facere dolores voluptatem ad ab rem assumenda soluta!
This is a link and how it could look like bestlinkinthebeautifulworld. Obcaecati, iste distinctio veritatis eligendi laboriosam illo nostrum corporis at libero vel voluptas? Expedita, facere dolores voluptatem ad ab rem assumenda soluta!
Here's just some classic bold text adipisicing elit. Obcaecati, iste distinctio veritatis eligendi laboriosam notBoldSecondbestlinkinthebeautifulworld illo nostrum corporis at libero vel voluptas? Expedita, facere dolores voluptatem ad ab rem assumenda soluta!
Obcaecati, iste distinctio veritatis eligendi laboriosam adipisicing elit illo nostrum corporis at adipisicing elit libero vel voluptas? Expedita, adipisicing facere dolores voluptatem ad ab rem assumenda soluta!
Other cuple of colors in case we want to emphasize several ways adipisicing elit. Obcaecati, iste distinctio veritatis eligendi laboriosam adipisicing elit illo nostrum corporis at voluptatem libero vel voluptas? Expedita, facere dolores voluptatem ad ab rem assumenda soluta!
Lorem ipsum dolor sit amet consectetur adipisicing elit. Obcaecati, iste distinctio veritatis eligendi laboriosam illo nostrum corporis at libero vel voluptas? Expedita, facere dolores voluptatem ad ab rem assumenda soluta! Lorem ipsum dolor, sit amet consectetur adipisicing elit. Quod veniam, quam ad expedita laborum sed at voluptates culpa ipsam ut vel. Ullam temporibus a mollitia quod aliquam ratione exercitationem nesciunt.
Lorem ipsum dolor sit amet consectetur adipisicing elit. Obcaecati, iste distinctio veritatis eligendi laboriosam illo nostrum corporis at libero vel voluptas? Expedita, facere dolores voluptatem ad ab rem assumenda soluta! Lorem ipsum dolor, sit amet consectetur adipisicing elit. Quod veniam, quam ad expedita laborum sed at voluptates culpa ipsam ut vel. Ullam temporibus a mollitia quod aliquam ratione exercitationem nesciunt.
Lorem ipsum dolor sit amet consectetur adipisicing elit. Obcaecati, iste distinctio veritatis eligendi laboriosam illo nostrum corporis at libero vel voluptas? Expedita, facere dolores voluptatem ad ab rem assumenda soluta!
Lorem ipsum dolor sit amet consectetur adipisicing elit. Repudiandae quas consequuntur illo numquam assumenda autem exercitationem distinctio perspiciatis in natus. Eius dicta similique ipsam ipsa minima, nemo quae enim tempore.
GPAL
.CallIfNotFound(GenericCallIfNotFound)
.WithPublishToConsole();
//System.Drawing.Rectangle windowSize = new System.Drawing.Rectangle(10, 10, 1500, 1024);
// NOTE: we have to set browser = before we execute any steps
// this is due to the 'GenericCallIfNotFound' which might throw an exception, and BankScraper will not have the browser set when it calls scraper.Close()
// until the complete fluent line gets executed (meaning every step, meaning browser is not set until everything else succeeds)
browser = GPAL.Browser
.WithBrowserType(Enums.BrowserType.Chrome)
.WithProfileDataDirectory(ChromeProfileLocation)
.WithUseAutomationEngine(AutomationEngine.Selenium)
.WithWindowSize(new System.Drawing.Rectangle(0,0,1920,1080))
.ToGPALObject();