none
c# aplicacao web logando em site e baixando arquivo RRS feed

  • Pergunta

  • Boa tarde!

    Estou precisando desenvolver uma aplicação em C# que precisa logar em um site e depois baixar umas arquivos em CSV. Para isso gostaria de saber qual a melhor forma de desenvolver essa aplicação. Fiz uns protótipos usando windows forms, mas gostaria de usar uma forma mais automática, sem a necessidade do usuário apertar botoes ou entrar com dados. É melhor eu continuar usando windows forms ou utilizar outra forma? 

    quinta-feira, 13 de julho de 2017 17:37

Todas as Respostas

  • Não entendi a dúvida entre continuar usando Windows Forms ou "outra forma". Você não conseguiu alcançar o objetivo de baixar o arquivo? 

    O tipo de projeto não influencia no que precisa fazer.


    Juliano Nunes - http://linkedin.com/in/julianonunes

    Lembre-se de clicar em "Votar como útil" e "Marcar como Resposta" caso tenha respondido sua dúvida.

    Remember to "Vote as Helpful" and "Mark as Answer" if your question has been answered.

    quinta-feira, 13 de julho de 2017 18:25
  • Em relacao a outra forma seria: Console application, apsx, etc. 

    Segue o codigo da aplicacao abaixo:

    using System;
    using EAGetMail;
    using System.IO;
    using System.Windows.Forms;
    
    namespace webBrowser
    {
        public partial class Menu : Form
        {
            public Menu()
            {
                InitializeComponent();
            }
    
            private void Menu_Load(object sender, EventArgs e)
            {
                webBrowser1.Navigate("https://scde.ccee.org.br");
            }
    
            private void Login_Click(object sender, EventArgs e)
            {
                HtmlElementCollection pagina = webBrowser1.Document.GetElementsByTagName("input");
                HtmlElement usuario = pagina[0];
                HtmlElement senha = pagina[1];
    
                if (usuario != null)
                {
                    usuario.SetAttribute("value", "XXXXXXXX");
                }
                if (senha != null)
                {
                    senha.SetAttribute("value", "XXXXXXXX");
                }
                HtmlElementCollection paginaLogin = webBrowser1.Document.GetElementsByTagName("button");
                paginaLogin[0].InvokeMember("click"); 
            }
    
            private void Autenticar_Click(object sender, EventArgs e)
            {
                HtmlElementCollection pagina = webBrowser1.Document.GetElementsByTagName("input");
                HtmlElement viaEmail = pagina[1];
    
                if (viaEmail != null)
                {
                    pagina[1].InvokeMember("click");
                }
                string codigo = pegandoSenhaEmail();
    
                HtmlElementCollection pagina2 = webBrowser1.Document.GetElementsByTagName("token");
            }
    
            private void Executar_Click(object sender, EventArgs e)
            {
                
            }
            string pegandoSenhaEmail()
            {
    
                string curpath = Directory.GetCurrentDirectory();
                string mailbox = String.Format("{0}\\inbox", curpath);
    
                if (!Directory.Exists(mailbox))
                {
                    Directory.CreateDirectory(mailbox);
                }
    
                MailServer oServer = new MailServer("outlook.office365.com", "paulo@XXXXXX.com.br", "XXXXXXXXXX", ServerProtocol.Imap4);
                MailClient oClient = new MailClient("TryIt");
    
                oServer.SSLConnection = true;
    
                oServer.Port = 993;
    
                try
                {
                    oClient.Connect(oServer);
                    MailInfo[] infos = oClient.GetMailInfos();
    
                    for (int i = infos.Length - 1; i > infos.Length - 5; i--)
                    {
                        MailInfo info = infos[i];
    
                        
                        Mail oMail = oClient.GetMail(info);
    
                       
                        System.DateTime d = System.DateTime.Now;
                        System.Globalization.CultureInfo cur = new System.Globalization.CultureInfo("en-US");
                        string sdate = d.ToString("yyyyMMddHHmmss", cur);
                        string fileName = String.Format("{0}\\{1}{2}{3}.eml", mailbox, sdate, d.Millisecond.ToString("d3"), i);
    
                        oMail.SaveAs(fileName, true);
                    }
                    for (int i = infos.Length - 1; i > infos.Length - 5; i--)
                    {
                        MailInfo info = infos[i];
                        Mail aux = oClient.GetMail(info);
    
                        if(aux.Subject == "ENC: [CCEE] Codigo de autorizacao (Trial Version)")
                        {
                            int pos = aux.TextBody.IndexOf("Codigo de autorizacao: ");
                            string codigo = aux.TextBody.Substring(pos + 23, 6);
                            return codigo;
                        }
                    }
                    oClient.Quit();
                }
                catch (Exception ep)
                {
                    Console.WriteLine(ep.Message);
                }
                return null;
            }
        }
    }

    Explicando como funciona a aplicação: A aplicação ira entra na URL mostrada e ira preencher os campos login e senha com os dados informados na aplicação. Em seguida ela ira dar um submit e ira ser redirecionada para outra pagina. Nessa outra pagina existem 2 botoes que irão enviar uma senha ou por SMS ou por email para que ela seja inserida em um campo para que o login seja finalizado. Para isso optei pela opção de enviar a senha por email. Utilizando o protocolo IMAP, eu logo no email e procuro o email com o assunto especifico da senha enviada. Pego a senha e mando inserir no campo. 

    Os problemas que estão me incomodando e que eu preciso utilizar 3 botoes forms para navegar pelo site, pois o webBrowser não atualiza, somente quando um dos botoes e clicado que o webBrowser e atualizado. E fora que ao apertar alguns botoes um erro e gerado perguntando ao usuário se ele deseja continuar executando o script na pagina atual. Sendo necessário ele apertar em SIM para que o programa continue funcionando.

    Gostaria de nao ter que ficar utilizando botoes para realizar cada tarefa e sim que tudo fosse automatico e que nao gera-se erros.

    Muito obrigado pela resposta rapida!

    quinta-feira, 13 de julho de 2017 18:41
  • Você depende do controle WebBrowser se a autenticação do site depende de cookies para ser validada a cada página que você navega. Este controle usa a engine do Internet Explorer, portanto teste o processo através do IE e veja se os mesmos erros acontecem.

    Se o único problema com os erros está relacionado com as mensagens que aparecem, você pode tentar desabilitar usando:

    webBrowser.ScriptErrorsSuppressed = true;

    Uma opção é utilizar um componente que incorpora o Chromium (projeto open source em que o Chrome se baseia). Não é tão simples quanto WebBrowser, mas as vezes vale a pena migrar pra ele.

    https://github.com/cefsharp/CefSharp


    Juliano Nunes - http://linkedin.com/in/julianonunes

    Lembre-se de clicar em "Votar como útil" e "Marcar como Resposta" caso tenha respondido sua dúvida.

    Remember to "Vote as Helpful" and "Mark as Answer" if your question has been answered.

    quinta-feira, 13 de julho de 2017 19:53
  • Andrew

    Se o arquivo estiver na Internet fica fácil. Para abrir, basta pegar o arquivo ou então abrir usando o browser.

    Basta baixar o arquivo utilizando HTTP Stream ou qualquer tipo de framework que faz download de arquivo.

    Veja o link abaixo que poderá te ajudar.

    https://ecode10.com/Pesquisar?q=download


    Espero ter ajudado. Se ajudei, favor marcar no fórum falando que foi útil.

    Mauricio Junior - Comunidade www.ecode10.com

    sexta-feira, 14 de julho de 2017 07:41
  • Vou tentar desabilitar os erros. Agora com relação ao outro problema. Por exemplo durante a execução do botão abaixo:

    private void Autenticar_Click(object sender, EventArgs e)
            {
                HtmlElementCollection pagina = webBrowser1.Document.GetElementsByTagName("input");
                HtmlElement viaEmail = pagina[1];
    
                if (viaEmail != null)
                {
                    pagina[1].InvokeMember("click");
                }
                string codigo = pegandoSenhaEmail();
    
                HtmlElementCollection pagina2 = webBrowser1.Document.GetElementsByTagName("token");
            }
    
    Ao executar o comando: pagina[1].InvokeMember("click"); a pagina e redirecionada para outra. Contudo ao executar a linha seguinte: 
    HtmlElementCollection pagina2 = webBrowser1.Document.GetElementsByTagName("token");
    a variavel pagina2 pega o html da pagina que estava antes de ser redirecionada. Gostaria que ela pega o html da nova pagina, pois e nessa nova pagina que possui o elemento com a tag "token" que preciso. Existe algum comando para fazer isso? A forma que usei para contornar isso (nao foi das melhores) foi separar cada acao por botao, pois apos executar um botao a pagina ja estava carregada e o programa conseguia pegar o novo html

    sexta-feira, 14 de julho de 2017 17:11
  • Se ocorre navegação para outra página, você precisa tratar no seu código qual a página atual (ou qual visualização atual), utilizando o evento DocumentCompleted pra identificar quando a página terminou de ser carregada e variáveis auxiliares para indicar qual é a página atual (ou pela URL).

    Se logo depois do comando que gerou o redirecionamento você executar mais códigos, não estará lendo os dados da página no status esperado.


    Juliano Nunes - http://linkedin.com/in/julianonunes

    Lembre-se de clicar em "Votar como útil" e "Marcar como Resposta" caso tenha respondido sua dúvida.

    Remember to "Vote as Helpful" and "Mark as Answer" if your question has been answered.

    sexta-feira, 14 de julho de 2017 17:43
  • Acredito que a solucao para todos os meus problemas seria usar o evento que voce citou (DocumentCompleted). Procurei na documentacao para saber como usa-lo e cheguei a isso:

    private void Autenticar_Click(object sender, EventArgs e)
            {
                HtmlElementCollection paginaToda = webBrowser1.Document.All;
                HtmlElementCollection pagina = webBrowser1.Document.GetElementsByTagName("input");
                HtmlElement viaEmail = pagina[1];
    
                if (viaEmail != null)
                {
                    pagina[1].InvokeMember("click");
                }
                //HtmlElementCollection paginaLogin = webBrowser1.Document.GetElementsByTagName("button");
                //paginaLogin[0].InvokeMember("click");
                string codigo = pegandoSenhaEmail();
    
                webBrowser1.DocumentCompleted += new WebBrowserDocumentCompletedEventHandler(carregarPagina);
            }
            private void carregarPagina(object sender, WebBrowserDocumentCompletedEventArgs e)
            {
                HtmlElementCollection paginaToda2 = webBrowser1.Document.All;
                HtmlElementCollection pagina2 = webBrowser1.Document.GetElementsByTagName("token");
            }

    Contudo ao Debuggar o código notei que os objetos paginaToda e paginaToda2 (inseridos apenas para ver se as paginas estavam diferentes) estão iguais. É como se o código executa-se antes de a pagina ser carregada completamente. O código não pode ser executado sem a pagina nova ter sido carregada.

    Outra coisa que notei que ao pressionar o botão autenticar o seguinte erro aparece e o programa fica travado ate umas das opções serem pressionadas (no caso para que ele continue funcionando e necessário pressionar o SIM, caso contrario o programa para por ali mesmo).

    (O forum nao deixou inserir imagem, portanto vou escrever o erro)

    Erro no script desta pagina.

    linha: 114

    caractere 13

    Erro: '$' não está definido

    Código 0

    URL: https://challenge.ccee.org.br/otp/coleta?request_id=7322592136253990772&CREDENTIAL_CONTEXT_DATA=USER_ACTION_COMMAND%

    Deseja continuar executando scripts nesta pagina?

    (opções SIM e NÃO em botoes)

    Obrigado pela sugestões e pela paciência elas me parecem bem promissoras e me deram ideias que me serão uteis caso esse problema seja resolvido

    sexta-feira, 14 de julho de 2017 18:59