Reinicializando automaticamente um Verizon FIOS Quantum Router via C # / WebBrowser / ConsoleApp

Abaixo está o meu primeiro C # / WebBrowser ConsoleApp. Muito obrigado a todas as ótimas perguntas / discussões do SO que me ajudaram a chegar aqui. Ele reinicia um roteador Verizon FIOS Quantum. Pretendo adicionar código que monitore minha conexão com a Internet para reiniciar o roteador quando a conexão for perdida. As perdas de conexão são MUITO raras (o FIOS é ótimo), mas acontece.

Esse código funciona (efetua login no roteador e o reinicia), mas precisa ser refinado para uso em produção. Estou postando isso para outras pessoas que gostariam de fazer sugestões de aprimoramento e estou procurando respostas para algumas perguntas que não entendo como um WebBrowser controla novatos. Minhas perguntas para o código abaixo são as seguintes:

Por que isso não funciona sem a adição de um segundo manipulador de eventos DocumentCompleted em Main ()?Aguardo a criação de páginas com javascript, verificando a disponibilidade dos elementos do documento. Existe uma maneira melhor de esperar o javascript ser executado e concluir a criação da página?Por que eu preciso adicionarApplication.DoEvents() depois de definir a entrada.InnerTexto para a senha e depois do botão clicar?Onde devo chamar WebBrowser.Dispose () (se houver)?Que melhorias você sugeriria?

Para usar este código:

Defina a senha de administrador do seu roteador antes de compilar e executarDefina booleano de produção como true quando concluir o teste (quando falso, o código cancela a reinicialização e efetua logout)Se isso não funcionar, verifique se você pode fazer login através do navegador da web para saber que não está bloqueado (muitas sessões de login)No Windows, modifique seu registro, para que o modo de emulação do navegador seja o IE11 (para scripts de páginas da web)

using System; using System.Windows.Forms; using System.Threading;

namespace FIOSMonitor
{
    class Program
    {
        // Set production bool to true for production use
        // Set router admin password

        const bool production = false;

        const string loginUri = "http://192.168.1.1/#/login";
        const string mainUri = "http://192.168.1.1/#/main";
        const string rebootUri = "http://192.168.1.1/#/advanced/reboot";
        const string logoutUri = "http://192.168.1.1/#/logout";
        const string advancedUri = "http://192.168.1.1/#/advanced";
        const string password = "router_admin_password";

        static void Main(string[] args)
        {
            Thread th = new Thread(() =>
            {
                WebBrowser wb = new WebBrowser();

                wb.AllowNavigation = true;
                wb.ScrollBarsEnabled = false;
                wb.ScriptErrorsSuppressed = true;

                wb.DocumentCompleted += PageCompleted;
                wb.Navigate(new Uri(loginUri));

                // DocumentCompleted handler for reboot page 
                // Not sure why, but this doesn't work without this additional DocumentCompleted handler
                wb.DocumentCompleted += PageCompleted;

                Application.Run();
            });
            th.SetApartmentState(ApartmentState.STA);
            th.Start();
        }

        private static void PageCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
        {
            string classname;
            string type;
            string action;

            bool loggedIn = false;
            bool rebooted = false;
            bool loggedOut = false;

            WebBrowser wb = ((WebBrowser)sender);
            HtmlDocument document = wb.Document;    

            if (document.Url.ToString() == loginUri)
            {
                while (!loggedIn)
                {
                    foreach (HtmlElement input in document.GetElementsByTagName("input"))
                    {
                        classname = input.GetAttribute("className");
                        type = input.GetAttribute("type");
                        if (classname.Contains("ie11loginW") & type == "password")
                        {
                            input.InnerText = password;

                            // Does not work without this Application.DoEvents().  Not sure why.
                            Application.DoEvents();

                            foreach (HtmlElement btn in document.GetElementsByTagName("button"))
                            {
                                classname = btn.GetAttribute("className");
                                action = btn.GetAttribute("ng-click");

                                if (classname.Contains("bhr5PriBtn") & action == "login()")
                                {
                                    btn.InvokeMember("Click");
                                    Application.DoEvents();
                                    loggedIn = true;

                                    // Wait for navigation to main page after logging in
                                    while (document.Url.ToString() == loginUri)
                                    {
                                        document = wb.Document;
                                        Application.DoEvents();
                                    }

                                    break;
                                }
                            }

                            break;
                        }
                    }

             ,       // If we're here, document elements may not yet be available (haven't yet been created by javascript).
                    // Wait for document elements to be created by javascript and try again.
                    Application.DoEvents();
                }
            }
            else if (document.Url.ToString() == mainUri)
            {
                // Now that we're on the main page, navigate to the reboot page
                wb.Navigate(new Uri(rebootUri));
            }
            else if (document.Url.ToString() == rebootUri)
            {
                while (!rebooted & !loggedOut)
                {
                    if (production)
                    {
                        foreach (HtmlElement btn in document.GetElementsByTagName("button"))
                        {
                            classname = btn.GetAttribute("className");
                            action = btn.GetAttribute("ng-click");

                            if (classname.Contains("bhr5PriBtn") & action == "reboot()")
                            {
                                btn.InvokeMember("Click");
                                Application.DoEvents();

                                rebooted = true;
                                Application.ExitThread();
                                break;
                            }
                        }
                    }
                    else
                    {
                        // we're testing, so click cancel button and logout
                        foreach (HtmlElement a1 in document.GetElementsByTagName("a"))
                        {
                            classname = a1.GetAttribute("className");
                            if (classname.Contains("bhr5SecBtn") & a1.InnerText == "Cancel")
                            {
                                a1.InvokeMember("Click");
                                Application.DoEvents();

                                // Wait for cancel to cause navigation back to Advanced page
                                while (document.Url.ToString() != advancedUri)
                                {
                                    document = wb.Document;
                                    Application.DoEvents();
                                }

                                // Now click the logout button
                                foreach (HtmlElement a2 in document.GetElementsByTagName("a"))
                                {
                                    classname = a2.GetAttribute("className");
                                    if (classname.Contains("bhr5SecBtn") & a2.InnerText == "Logout")
                                    {
                                        a2.InvokeMember("Click");
                                        Application.DoEvents();

                                        // Wait for logout to cause navigation logout page
                                        while (document.Url.ToString() != logoutUri)
                                        {
                                            document = wb.Document;
                                            Application.DoEvents();
                                        }

                                        loggedOut = true;
                                        Application.ExitThread();
                                        break;
                                    }
                                }

                                break;
                            }
                        }
                    }

                    // Wait for document elements to be created by javascript
                    Application.DoEvents();
                }
            }
            else if (document.Url.ToString() == logoutUri)
            {
                // Placeholder for logging
            }
            else
            {
                // Should never get here.  Unknown state.
                MessageBox.Show("Unknown State: " + document.Url.ToString());
            }
       }
    }
}

questionAnswers(0)

yourAnswerToTheQuestion