This class provides helper functions for handling errors and displaying them to users
Inheritance: System.Windows.Forms.Form
        /// <summary>
        /// Displays exception information. Should be called from try...catch handlers
        /// </summary>
        /// <param name="ex">Exception object to handle</param>
        new public static void Handle(Exception ex)
        {
            if (ex != null)
            {
                if (ex is System.Net.WebException)
                {
                    MessageBox.Show(ex.Message, "Network access error. Please try again later", MessageBoxButtons.OK, MessageBoxIcon.Error);
                }
                else
                {
                    ErrorHandler handler = new ErrorHandler();

                    handler.txtError.Text = ex.Message;

                    handler.txtDetails.Text = "{{AWB bug\r\n | status      = new <!-- when fixed replace with \"fixed\" -->\r\n | description = Exception: " + ex.GetType().Name + "\r\nMessage: " +
                        ex.Message + "\r\nCall stack:" + ex.StackTrace + "\r\n~~~~\r\n | OS          = " + Environment.OSVersion.ToString() + "\r\n | version     = " + Assembly.GetExecutingAssembly().GetName().Version.ToString();

                    handler.txtDetails.Text += "\r\n}}";

                    handler.textBox1.Text = "AWB Updater encountered " + ex.GetType().Name;

                    handler.ShowDialog();
                }
            }
        }
        /// <summary>
        /// Displays exception information. Should be called from try...catch handlers
        /// </summary>
        /// <param name="ex">Exception object to handle</param>
        public static void HandleException(Exception ex)
        {
            if (ex == null || HandleKnownExceptions(ex)) return;

            // TODO: suggest a bug report for other exceptions
            ErrorHandler handler = new ErrorHandler { txtError = { Text = ex.Message } };

            var errorMessage = new BugReport(ex).PrintForPhabricator();
            handler.txtDetails.Text = errorMessage;

            handler.txtSubject.Text = ex.GetType().Name + " in " + Thrower(ex);

               // Tools.WriteDebug("HandleException", errorMessage);
            handler.ShowDialog();
        }
        /// <summary>
        /// Displays exception information. Should be called from try...catch handlers
        /// </summary>
        /// <param name="ex">Exception object to handle</param>
        new public static void Handle(Exception ex)
        {
            if (ex == null) return;

            if (ex is System.Net.WebException)
            {
                MessageBox.Show(ex.Message, "Network access error",
                                MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
                // out of memory error
            else if (ex is OutOfMemoryException)
            {
                MessageBox.Show(ex.Message, "Out of Memory error",
                                MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
            else // suggest a bug report for other exceptions
            {
                ErrorHandler handler = new ErrorHandler {txtError = {Text = ex.Message}};

                StringBuilder errorMessage = new StringBuilder("{{AWB bug\r\n | status      = new <!-- when fixed replace with \"fixed\" -->\r\n | description = ");

                if (Thread.CurrentThread.Name != "Main thread")
                    errorMessage.AppendLine("Thread: " + Thread.CurrentThread.Name);

                errorMessage.Append("<table>");
                FormatException(ex, errorMessage, ExceptionKind.TopLevel);
                errorMessage.AppendLine("</table>\r\n~~~~");
                errorMessage.AppendLine(" | OS          = " + Environment.OSVersion);

                AssemblyName hostingApp = Assembly.GetExecutingAssembly().GetName();

                errorMessage.Append(string.Format(" | version     = {0} ({1}), {2} ({3})", Application.ProductName,
                                                  Application.ProductVersion,
                                                  hostingApp.Name, hostingApp.Version));

                errorMessage.AppendLine(" | net = " + Environment.Version);
                errorMessage.AppendLine(" | workaround     = <!-- Any workaround for the problem -->");
                errorMessage.AppendLine(" | fix_version    = <!-- Version of AWB the fix will be included in; AWB developer will complete when it's fixed -->");
                errorMessage.AppendLine("}}");

                handler.txtDetails.Text = errorMessage.ToString();

                handler.txtSubject.Text = ex.GetType().Name + " in " + Thrower(ex);

                handler.ShowDialog();
            }
        }
        /// <summary>
        /// Displays exception information. Should be called from try...catch handlers
        /// </summary>
        /// <param name="ex">Exception object to handle</param>
        new public static void Handle(Exception ex)
        {
            if (ex == null) return;

            if (ex is System.Net.WebException)
            {
                MessageBox.Show(ex.Message, "Network access error",
                                MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
                // out of memory error
            else if (ex is OutOfMemoryException)
            {
                MessageBox.Show(ex.Message, "Out of Memory error",
                                MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
            else // suggest a bug report for other exceptions
            {
                ErrorHandler handler = new ErrorHandler {txtError = {Text = ex.Message}};

                StringBuilder errorMessage = new StringBuilder("{{AWB bug\r\n | status      = new <!-- when fixed replace with \"fixed\" -->\r\n | description = ");

                if (Thread.CurrentThread.Name != "Main thread")
                    errorMessage.Append("\r\nThread: " + Thread.CurrentThread.Name);

                errorMessage.Append("<table>");
                FormatException(ex, errorMessage, true);
                errorMessage.Append("</table>\r\n~~~~\r\n | OS          = " + Environment.OSVersion + "\r\n | version     = " + Assembly.GetExecutingAssembly().GetName().Version);

                errorMessage.Append("\r\n}}");

                handler.txtDetails.Text = errorMessage.ToString();

                handler.txtSubject.Text = ex.GetType().Name + " in " + Thrower(ex);

                handler.ShowDialog();
            }
        }
        /// <summary>
        /// Displays exception information. Should be called from try...catch handlers
        /// </summary>
        /// <param name="ex">Exception object to handle</param>
        new public static void Handle(Exception ex)
        {
            if (ex != null)
            {
                /*// invalid regex - only ArgumentException, without subclasses
                if (ex.GetType().ToString().Equals("System.ArgumentException")
                    && ex.StackTrace.Contains("System.Text.RegularExpressions"))
                {
                    MessageBox.Show(ex.Message, "Invalid regular expression",
                        MessageBoxButtons.OK, MessageBoxIcon.Error);
                }
                // network access error
                else */if (ex is System.Net.WebException)
                {
                    MessageBox.Show(ex.Message, "Network access error",
                        MessageBoxButtons.OK, MessageBoxIcon.Error);
                }
                // out of memory error
                else if (ex is OutOfMemoryException)
                {
                    MessageBox.Show(ex.Message, "Out of Memory error",
                        MessageBoxButtons.OK, MessageBoxIcon.Error);
                }
                else // suggest a bug report for other exceptions
                {
                    ErrorHandler handler = new ErrorHandler();

                    handler.txtError.Text = ex.Message;

                    StringBuilder errorMessage = new StringBuilder("{{AWB bug\r\n | status      = new <!-- when fixed replace with \"fixed\" -->\r\n | description = ");

                    if (Thread.CurrentThread.Name != "Main thread")
                        errorMessage.Append("\r\nThread: " + Thread.CurrentThread.Name);

                    errorMessage.Append("<table>");
                    FormatException(ex, errorMessage, true);
                    errorMessage.Append("</table>\r\n~~~~\r\n | OS          = " + Environment.OSVersion + "\r\n | version     = " + Assembly.GetExecutingAssembly().GetName().Version.ToString());

                    //if (!Variables.Revision.Contains("?")) errorMessage.Append(", revision " + Variables.Revision);

                    //if (!string.IsNullOrEmpty(CurrentPage))
                    //{
                    //    // don't use Tools.WikiEncode here, to keep code portable to updater
                    //    // as it's not a pretty URL, we don't need to follow the MediaWiki encoding rules
                    //    string link = "[" + Variables.URLLong + "index.php?title=" + HttpUtility.UrlEncode(CurrentPage) + "&oldid=" + CurrentRevision.ToString() + "]";

                    //    errorMessage.Append("\r\n | duplicate = [encountered while processing page ''" + link + "'']");
                    //}
                    //else if (!string.IsNullOrEmpty(ListMakerText))
                    //    errorMessage.Append("\r\n | duplicate = '''ListMaker Text:''' " + ListMakerText);

                    errorMessage.Append("\r\n}}");

                    handler.txtDetails.Text = errorMessage.ToString();

                    handler.txtSubject.Text = ex.GetType().Name + " in " + Thrower(ex);

                    handler.ShowDialog();
                }
            }
        }