Inquiridor
c# aplicacao web logando em site e baixando arquivo

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?
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.
-
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!
-
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.
-
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 -
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
-
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.
-
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