<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-6417510629495760768</id><updated>2011-11-27T21:34:35.600-02:00</updated><category term='download'/><category term='response.end'/><category term='Natal'/><title type='text'>Código dá Trinta</title><subtitle type='html'>Source Safe, C#, Asp.net, SQL Server, EPM, MOSS e tudo o mais que você não achou por aí.</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://edsdias.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6417510629495760768/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://edsdias.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Edson Dias</name><uri>http://www.blogger.com/profile/07682303487677182742</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='http://3.bp.blogspot.com/_qOeTjL8L_18/STcN86W-3lI/AAAAAAAAAyQ/xKLNn5ppc3E/S220/DSC01469.JPG'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>5</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-6417510629495760768.post-2439398602639428738</id><published>2009-02-03T15:46:00.001-02:00</published><updated>2009-02-03T15:46:30.665-02:00</updated><title type='text'>Debugando windows services</title><content type='html'>&lt;p&gt;&lt;br&gt;&lt;/p&gt; &lt;p&gt;&lt;strong&gt;"Cannot start service from the command line or a debugger."&lt;br&gt;&lt;br&gt;&lt;/strong&gt;Fazia tempo que não via essa mensagem.&lt;br&gt;Precisei debugar um windows service num projeto esses dias e lembrei que uma coisa interessante: o nosso amigo F5 não funciona !&lt;br&gt;Simplesmente não adianta botar uns breakpoints e apertar F5 como acontece com os projetos Windows, Web, etc.&lt;br&gt;O Windows Service funciona como um serviço, portanto é necessário compila-lo, depois instala-lo,etc.&lt;br&gt;Se você tentar executar um serviço com o F5, a seguinte mensagem aparecerá:&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;a href="http://lh3.ggpht.com/_qOeTjL8L_18/SYiC46XjDEI/AAAAAAAAA1A/DU0wHXkiUTc/s1600-h/debug-servicos-2005%5B3%5D.jpg"&gt;&lt;img title="debug-servicos-2005" style="border-right: 0px; border-top: 0px; display: inline; border-left: 0px; border-bottom: 0px" height="95" alt="debug-servicos-2005" src="http://lh5.ggpht.com/_qOeTjL8L_18/SYiC8VHHKfI/AAAAAAAAA1E/Hi4bndthaPw/debug-servicos-2005_thumb%5B1%5D.jpg?imgmax=800" width="507" border="0"&gt;&lt;/a&gt; &lt;br&gt;&lt;br&gt;"Incomodada ficava sua avó!"&lt;br&gt;&lt;br&gt;Nas buscas pela web a solução para debugar windows services é quase sempre colocar seu breakpoint no visual studio, rodar seu serviço (via windows) e "attachar" seu debugger ao processo.&lt;br&gt;&lt;br&gt;Nem sempre funciona.&lt;br&gt;&lt;br&gt;Quase todo serviço windows funciona a base de thread que rodam periodicamente.&lt;br&gt;Um serviço, quando iniciado, roda automaticamente o metodo OnStart(), onde normalmente se criam outras threads de monitoramento e/ou eventos periódicos.&lt;br&gt;Dai que enquanto você está tentando attachar o seu processo, o evento já pode ter passado !&lt;br&gt;Outras soluções incluem criar um aplicativo Windows de teste para executar os métodos principais do seu windows services, ou então invocar o Debugger programaticamente via System.Diagnostics.Debugger.Break()&amp;nbsp; ou System.Diagnostics.Debugger.Launch().&lt;br&gt;Ai lembrei que já tinha feito algo parecido no framework 1 ainda com o falecido Visual Studio 2003.&lt;br&gt;&lt;br&gt;A estrutura básica de um windows service contem os métodos OnStart(), OnStop(),etc&lt;br&gt;&lt;br&gt;Sendo que a chamada principal se parece com isso.&lt;br&gt;&lt;br&gt;&lt;br&gt;Program.cs &lt;br&gt;&lt;br&gt;&lt;/p&gt;&lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;static&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; Main()&lt;br /&gt;    {           &lt;br /&gt;    ServiceBase[] ServicesToRun;&lt;br /&gt;    ServicesToRun = &lt;span class="kwrd"&gt;new&lt;/span&gt; ServiceBase[] { &lt;span class="kwrd"&gt;new&lt;/span&gt; MeuServicoWindows() };&lt;br /&gt;    ServiceBase.Run(ServicesToRun);&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br&gt;&lt;br&gt;E a classe do serviço:&amp;nbsp; MeuServicoWindows.cs&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; MeuServicoWindows : ServiceBase&lt;br /&gt;{&lt;br /&gt;  &lt;span class="kwrd"&gt;public&lt;/span&gt; MeuServicoWindows()&lt;br /&gt;  {         &lt;br /&gt;  }&lt;br /&gt;  &lt;span class="kwrd"&gt;protected&lt;/span&gt; &lt;span class="kwrd"&gt;override&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; OnStart(&lt;span class="kwrd"&gt;string&lt;/span&gt;[] args)&lt;br /&gt;  {&lt;br /&gt;     &lt;span class="rem"&gt;// faça-se o trampo !!&lt;/span&gt;&lt;br /&gt;  }&lt;br /&gt;  &lt;span class="kwrd"&gt;protected&lt;/span&gt; &lt;span class="kwrd"&gt;override&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; OnStop()&lt;br /&gt;  {&lt;br /&gt;     &lt;span class="rem"&gt;// Simon diz, pare-se.&lt;/span&gt;&lt;br /&gt;   }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;A solução ideal é criar um meio termo. &lt;br&gt;Como a chamada principal do Windows Service é sempre a Main() e depois a OnStart() da classe do Servico, a solução para o simples F5 seria&lt;br&gt;&lt;br&gt;&lt;br&gt;1) Criar um metodo na classe do serviço&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;pre class="csharpcode"&gt;&lt;span class="preproc"&gt;#if&lt;/span&gt; DEBUG&lt;br /&gt;&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; StartDebug(&lt;span class="kwrd"&gt;string&lt;/span&gt;[] args)&lt;br /&gt;{&lt;br /&gt;   OnStart(args);   &lt;span class="rem"&gt;// simplesmente chama a rotina principal da classe&lt;/span&gt;&lt;br /&gt;}    &lt;br /&gt;&lt;span class="preproc"&gt;#endif&lt;/span&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br&gt;&lt;br&gt;2) Substituir o&amp;nbsp; o metodo principal Main()&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;static&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; Main()&lt;br /&gt;{           &lt;br /&gt;  &lt;span class="rem"&gt;// se estiver debugando, simula a execução do serviço...&lt;/span&gt;&lt;br /&gt;  &lt;span class="kwrd"&gt;if&lt;/span&gt; (System.Diagnostics.Debugger.IsAttached)&lt;br /&gt;  {                            &lt;br /&gt;    &lt;span class="preproc"&gt;#if&lt;/span&gt; DEBUG   &lt;span class="rem"&gt;// debugando como DEBUG&lt;/span&gt;&lt;br /&gt;       MeuServicoWindows service = &lt;span class="kwrd"&gt;new&lt;/span&gt; MeuServicoWindows();&lt;br /&gt;       service.StartDebug(&lt;span class="kwrd"&gt;new&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt;[2]);&lt;br /&gt;       System.Threading.Thread.Sleep(System.Threading.Timeout.Infinite);&lt;br /&gt;     &lt;span class="preproc"&gt;#else&lt;/span&gt;   &lt;span class="rem"&gt;// debugando como Release &lt;/span&gt;&lt;br /&gt;       ServiceBase[] ServicesToRun;&lt;br /&gt;       ServicesToRun = &lt;span class="kwrd"&gt;new&lt;/span&gt; ServiceBase[] { &lt;span class="kwrd"&gt;new&lt;/span&gt; MeuServicoWindows() };&lt;br /&gt;       ServiceBase.Run(ServicesToRun);&lt;br /&gt;    &lt;span class="preproc"&gt;#endif&lt;/span&gt;            &lt;br /&gt; } &lt;br /&gt;  &lt;span class="kwrd"&gt;else&lt;/span&gt;   &lt;span class="rem"&gt;// codigo original&lt;/span&gt;&lt;br /&gt;  {&lt;br /&gt;   ServiceBase[] ServicesToRun;&lt;br /&gt;   ServicesToRun = &lt;span class="kwrd"&gt;new&lt;/span&gt; ServiceBase[] { &lt;span class="kwrd"&gt;new&lt;/span&gt; MeuServicoWindows() };&lt;br /&gt;   ServiceBase.Run(ServicesToRun);&lt;br /&gt;  }       &lt;br /&gt;} &lt;/pre&gt;&lt;br /&gt;&lt;p&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;Pontos de interesse da solução:&lt;br&gt;1) É possível debugar em ambiente de desenvolvimento;&lt;br&gt;2) É possível colocar uma versão de debug em produção&lt;br&gt;3) É possível colocar uma versão de release em produção&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6417510629495760768-2439398602639428738?l=edsdias.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://edsdias.blogspot.com/feeds/2439398602639428738/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6417510629495760768&amp;postID=2439398602639428738' title='0 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6417510629495760768/posts/default/2439398602639428738'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6417510629495760768/posts/default/2439398602639428738'/><link rel='alternate' type='text/html' href='http://edsdias.blogspot.com/2009/02/debugando-windows-services.html' title='Debugando windows services'/><author><name>Edson Dias</name><uri>http://www.blogger.com/profile/07682303487677182742</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='http://3.bp.blogspot.com/_qOeTjL8L_18/STcN86W-3lI/AAAAAAAAAyQ/xKLNn5ppc3E/S220/DSC01469.JPG'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://lh5.ggpht.com/_qOeTjL8L_18/SYiC8VHHKfI/AAAAAAAAA1E/Hi4bndthaPw/s72-c/debug-servicos-2005_thumb%5B1%5D.jpg?imgmax=800' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6417510629495760768.post-2237560109878990826</id><published>2008-12-23T11:44:00.002-02:00</published><updated>2008-12-23T11:50:05.374-02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Natal'/><title type='text'>Feliz Natal</title><content type='html'>while (    TheEarth.IsRunning() &amp;amp;&amp;amp;&lt;br /&gt;                ThereIsHope &amp;amp;&amp;amp;&lt;br /&gt;                DateTime.Today.Day.Equals(25) &amp;amp;&amp;amp;&lt;br /&gt;                DateTime.Today.Month.Equals(12))&lt;br /&gt; {&lt;br /&gt;      Console.WriteLine("Feliz Natal");&lt;br /&gt;}&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6417510629495760768-2237560109878990826?l=edsdias.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://edsdias.blogspot.com/feeds/2237560109878990826/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6417510629495760768&amp;postID=2237560109878990826' title='0 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6417510629495760768/posts/default/2237560109878990826'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6417510629495760768/posts/default/2237560109878990826'/><link rel='alternate' type='text/html' href='http://edsdias.blogspot.com/2008/12/feliz-natal.html' title='Feliz Natal'/><author><name>Edson Dias</name><uri>http://www.blogger.com/profile/07682303487677182742</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='http://3.bp.blogspot.com/_qOeTjL8L_18/STcN86W-3lI/AAAAAAAAAyQ/xKLNn5ppc3E/S220/DSC01469.JPG'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6417510629495760768.post-9181794693835210393</id><published>2008-12-06T23:08:00.001-02:00</published><updated>2008-12-06T23:08:19.271-02:00</updated><title type='text'>Feriados móveis</title><content type='html'>&lt;p&gt;Estava abrindo minhas correspondências essa semana e achei um envelope do meu contador, que recebo todo ano em Dezembro, um calendário do ano seguinte (e um boleto bancário do 13º, óbvio).&lt;/p&gt; &lt;p&gt;Daí comecei a ver os feriados do ano que vem, e que são muitos.&lt;br&gt;Lembrei de uma coisa interessante, que nem todo mundo sabe: como calcular feriados móveis.&lt;br&gt;&lt;br&gt;Apenas por curiosidade, os calendários são baseados em eventos astrológicos, e obviamente a mudança dos feriados móveis também é baseada em cálculos astrológicos.&lt;br&gt;&lt;br&gt;Muita gente se pergunta porque o Carnaval sempre cai num dia diferente todo ano, as vezes até em outro mês.&lt;br&gt;&lt;br&gt;A base de todos feriados móveis é a data da Páscoa.&lt;br&gt;&lt;br&gt;Carnaval = Páscoa – 47 dias&lt;br&gt;Sexta Feira Santa = Páscoa – 2 dias&lt;br&gt;CorpusChristi =&amp;nbsp;&amp;nbsp; Páscoa + 60 dias&lt;br&gt;&lt;br&gt;A data também é móvel e é calculada através de uma fórmula muito doida.&lt;br&gt;Encontrei uns documentos antigos na minha pesquisa e fiz uma rotina em Visual Basic há muito tempo (no mínimo uns 10 anos).&lt;br&gt;Hoje resolvei convertê-la pra C# para utilizar em um sistema que estou trabalhando.&lt;br&gt;&lt;br&gt;Vamos ao código:&lt;/p&gt;&lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;static&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; Main(&lt;span class="kwrd"&gt;string&lt;/span&gt;[] args)&lt;br /&gt;{&lt;br /&gt;  DateTime dtPascoa = DataPascoa(2009);&lt;br /&gt;  DateTime dtCarnaval = dtPascoa.AddDays(-47);&lt;br /&gt;  DateTime dtSextaSanta = dtPascoa.AddDays(-2);&lt;br /&gt;  DateTime dtCorpusChristi = dtPascoa.AddDays(60);&lt;br /&gt;  Console.WriteLine(&lt;span class="kwrd"&gt;string&lt;/span&gt;.Format(&lt;span class="str"&gt;"Páscoa: {0}"&lt;/span&gt;, dtPascoa.ToLongDateString()));&lt;br /&gt;  Console.WriteLine(&lt;span class="kwrd"&gt;string&lt;/span&gt;.Format(&lt;span class="str"&gt;"Carnaval: {0}"&lt;/span&gt;, dtCarnaval.ToLongDateString()));&lt;br /&gt;  Console.WriteLine(&lt;span class="kwrd"&gt;string&lt;/span&gt;.Format(&lt;span class="str"&gt;"Sexta-Feira Santa: {0}"&lt;/span&gt;, dtSextaSanta.ToLongDateString()));&lt;br /&gt;  Console.WriteLine(&lt;span class="kwrd"&gt;string&lt;/span&gt;.Format(&lt;span class="str"&gt;"Corpus Christi: {0}"&lt;/span&gt;, dtCorpusChristi.ToLongDateString()));&lt;br /&gt;  Console.ReadKey();&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;O código do cálculo da Páscoa&lt;br&gt;&lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;static&lt;/span&gt; DateTime DataPascoa(&lt;span class="kwrd"&gt;int&lt;/span&gt; nYear)&lt;br /&gt;{&lt;br /&gt;    &lt;span class="kwrd"&gt;int&lt;/span&gt; nGold = 0;&lt;br /&gt;    &lt;span class="kwrd"&gt;int&lt;/span&gt; nCent = 0;&lt;br /&gt;    &lt;span class="kwrd"&gt;int&lt;/span&gt; nCorx = 0;&lt;br /&gt;    &lt;span class="kwrd"&gt;int&lt;/span&gt; nCorz = 0;&lt;br /&gt;    &lt;span class="kwrd"&gt;int&lt;/span&gt; nSunday = 0;&lt;br /&gt;    &lt;span class="kwrd"&gt;int&lt;/span&gt; nEpact = 0;&lt;br /&gt;    &lt;span class="kwrd"&gt;int&lt;/span&gt; nMoon = 0;&lt;br /&gt;    &lt;span class="kwrd"&gt;int&lt;/span&gt; nMonth = 0;&lt;br /&gt;    &lt;span class="kwrd"&gt;int&lt;/span&gt; nDay = 0;&lt;br /&gt;&lt;br /&gt;    &lt;span class="rem"&gt;// nGold, é o Golden number&lt;/span&gt;&lt;br /&gt;    nGold = (nYear % 19) + 1; &lt;br /&gt;&lt;br /&gt;    &lt;span class="rem"&gt;// nCent é o Século&lt;/span&gt;&lt;br /&gt;    nCent = (nYear / 100) + 1;&lt;br /&gt;&lt;br /&gt;    &lt;span class="rem"&gt;// nCorx é o número de anos em que o bissexto foi retirado para sincronizar&lt;/span&gt;&lt;br /&gt;    nCorx = ((3 * nCent) / 4 - 12);&lt;br /&gt;&lt;br /&gt;    &lt;span class="rem"&gt;// nCorz é uma correção para sincronizar a Páscoa com a órbita da Lua&lt;/span&gt;&lt;br /&gt;    nCorz = ((8 * nCent + 5) / 25 - 5);&lt;br /&gt;    nSunday = ((5 * nYear) / 4 - nCorx - 10);&lt;br /&gt;&lt;br /&gt;    &lt;span class="rem"&gt;// nEpact é a ocorrencia de uma Lua cheia&lt;/span&gt;&lt;br /&gt;    nEpact = ((11 * nGold + 20 + nCorz - nCorx) % 30);&lt;br /&gt;&lt;br /&gt;    &lt;span class="kwrd"&gt;if&lt;/span&gt; (nEpact &amp;lt; 0)&lt;br /&gt;        nEpact = nEpact + 30;&lt;br /&gt;    &lt;br /&gt;    &lt;span class="kwrd"&gt;if&lt;/span&gt; (((nEpact == 25) &amp;amp;&amp;amp; (nGold &amp;gt; 11)) || (nEpact == 24))&lt;br /&gt;        nEpact = nEpact + 1;&lt;br /&gt;&lt;br /&gt;    &lt;span class="rem"&gt;// Lua cheia - a n ésima lua de Março é o calendário da lua cheia&lt;/span&gt;&lt;br /&gt;    nMoon = 44 - nEpact;&lt;br /&gt;&lt;br /&gt;    &lt;span class="kwrd"&gt;if&lt;/span&gt; (nMoon &amp;lt; 21)&lt;br /&gt;        nMoon = nMoon + 30;&lt;br /&gt;    &lt;br /&gt;    &lt;span class="rem"&gt;// Avança ao domingo&lt;/span&gt;&lt;br /&gt;    nMoon = (nMoon + 7 - ((nSunday + nMoon) % 7));&lt;br /&gt;&lt;br /&gt;    &lt;span class="rem"&gt;// obtém o mês e o dia&lt;/span&gt;&lt;br /&gt;    &lt;span class="kwrd"&gt;if&lt;/span&gt; (nMoon &amp;gt; 31)&lt;br /&gt;    {&lt;br /&gt;        nMonth = 4;&lt;br /&gt;        nDay = nMoon - 31;&lt;br /&gt;    }&lt;br /&gt;    &lt;span class="kwrd"&gt;else&lt;/span&gt;&lt;br /&gt;    {&lt;br /&gt;        nMonth = 3;&lt;br /&gt;        nDay = nMoon;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    &lt;span class="kwrd"&gt;return&lt;/span&gt; &lt;span class="kwrd"&gt;new&lt;/span&gt; DateTime(nYear, nMonth, nDay);&lt;br /&gt;&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;&lt;div class="wlWriterEditableSmartContent" id="scid:0767317B-992E-4b12-91E0-4F059A8CECA8:fb46500f-9507-4285-afec-ddd7ae324058" style="padding-right: 0px; display: inline; padding-left: 0px; float: none; padding-bottom: 0px; margin: 0px; padding-top: 0px"&gt;Technorati Tags: &lt;a href="http://technorati.com/tags/Feriados" rel="tag"&gt;Feriados&lt;/a&gt;,&lt;a href="http://technorati.com/tags/P%c3%a1scoa" rel="tag"&gt;P&amp;#225;scoa&lt;/a&gt;,&lt;a href="http://technorati.com/tags/Carnaval" rel="tag"&gt;Carnaval&lt;/a&gt;&lt;/div&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6417510629495760768-9181794693835210393?l=edsdias.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://edsdias.blogspot.com/feeds/9181794693835210393/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6417510629495760768&amp;postID=9181794693835210393' title='1 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6417510629495760768/posts/default/9181794693835210393'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6417510629495760768/posts/default/9181794693835210393'/><link rel='alternate' type='text/html' href='http://edsdias.blogspot.com/2008/12/feriados-mveis.html' title='Feriados móveis'/><author><name>Edson Dias</name><uri>http://www.blogger.com/profile/07682303487677182742</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='http://3.bp.blogspot.com/_qOeTjL8L_18/STcN86W-3lI/AAAAAAAAAyQ/xKLNn5ppc3E/S220/DSC01469.JPG'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6417510629495760768.post-3032638523111204386</id><published>2008-12-05T18:46:00.003-02:00</published><updated>2008-12-05T21:38:56.986-02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='download'/><category scheme='http://www.blogger.com/atom/ns#' term='response.end'/><title type='text'>Download de arquivos dinâmicos</title><content type='html'>Download de arquivos gerados dinamicamente é uma rotina comum em muitos sites.  &lt;p&gt;Já precisei fazer isso diversas vezes e o código normalmente se parece com isso: &lt;br&gt;&lt;/p&gt;&lt;pre class="csharpcode"&gt;Response.AddHeader(&lt;span class="str"&gt;"Content-Size"&lt;/span&gt;, bytArq.Length.ToString());&lt;br /&gt;Response.AddHeader(&lt;span class="str"&gt;"Content-Disposition"&lt;/span&gt;, &lt;span class="str"&gt;"attachment; filename="&lt;/span&gt; + &lt;br&gt;NomeArquivo);&lt;br /&gt;Response.OutputStream.Write(bytArq, 0, bytArq.Length);Response.End();&lt;/pre&gt;onde: &lt;pre&gt;&lt;/pre&gt;&lt;pre&gt;&lt;strong&gt;byteArq &lt;/strong&gt;é um byte [] do conteudo do arquivo, sendo ele texto ou binário &lt;br&gt;&lt;strong&gt;NomeArquivo&lt;/strong&gt; é a o nome padrão sugerido pelo browser ao gravar o arquivo. &lt;/pre&gt;Até aí nenhuma novidade, mas vamos aos desafios. &lt;br&gt;Qual o problema do código acima ? &lt;br&gt;Se eu quisesse fazer o download do arquivo e logo em seguida atualizar algum campo na página, como por exemplo um label "&lt;em&gt;Arquivo enviado com sucesso&lt;/em&gt;" ? &lt;br /&gt;&lt;p&gt;Com o código acima, não seria possível. &lt;/p&gt;&lt;br /&gt;&lt;p&gt;A linha &lt;strong&gt;Response.End()&lt;/strong&gt;, interrompe a execução da página, e faz com que qualquer código logo após seja ignorado (pelo menos código que gere html de retorno).&lt;/p&gt;&lt;br /&gt;&lt;p&gt;Por quê essa linha é necessária ? &lt;/p&gt;&lt;br /&gt;&lt;p&gt;Porque sem ela o código no .cs seria executado e logo após o browser iria redenderizar a execução do aspx, o que faria com que o resultado gerado seria a combinação do arquivo mais o html, corrompendo o arquivo. &lt;/p&gt;&lt;br /&gt;&lt;p&gt;Na prática não é possível enviar 2 conteúdos ao browser simultaneamente, ou seja, ou eu envio o html, ou envio o arquivo. &lt;br&gt;&lt;br&gt;Vamos aos workarounds:&lt;br&gt;&lt;br&gt;E se ao invés de escrever os bytes do arquivo, eu abrisse uma janela, onde lá sim, escreveria o byte array, e na minha página principal continuaria meu código? &lt;/p&gt;A solução seria: &lt;br&gt;&lt;br /&gt;&lt;p&gt;&lt;strong&gt;pagina.aspx&lt;/strong&gt;, onde faria a chamada do download do arquivo &lt;br&gt;&lt;strong&gt;download.aspx&lt;/strong&gt;, um arquivo sem html no aspx &lt;/p&gt;&lt;br /&gt;&lt;p&gt;No código na pagina.aspx: &lt;br&gt;Um método para escrever abrir a página de download &lt;br&gt;&lt;/p&gt;&lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;void&lt;/span&gt; DownloadArquivo(Page p, &lt;span class="kwrd"&gt;byte&lt;/span&gt;[] bytArq, &lt;span class="kwrd"&gt;string&lt;/span&gt; NomeArquivo)&lt;br /&gt;{  &lt;br&gt;  Session[&lt;span class="str"&gt;"downloadBytes"&lt;/span&gt;] = bytArq;  &lt;br&gt;  Session[&lt;span class="str"&gt;"downloadName"&lt;/span&gt;] = NomeArquivo;  &lt;br&gt;  System.Text.StringBuilder s = &lt;span class="kwrd"&gt;new&lt;/span&gt; System.Text.StringBuilder();&lt;br&gt;  s.Append(&lt;span class="str"&gt;"\n&amp;lt;SCRIPT LANGUAGE='JavaScript'&amp;gt;\n"&lt;/span&gt;);&lt;br&gt;  s.Append(&lt;span class="str"&gt;"function download()"&lt;/span&gt;);&lt;br&gt;  s.Append(&lt;span class="str"&gt;"{\n"&lt;/span&gt;);&lt;br&gt;  s.Append(&lt;span class="str"&gt;" window.open('download.aspx', 'Download', 'toolbar=no, &lt;br&gt;location=no, directories=no, status=yes, menubar=no, scrollbars=no, &lt;br&gt;resizable=no, titlebar=no, copyhistory=no, width=100, height=100, left=0, &lt;br&gt;top=0');\n"&lt;/span&gt;);&lt;br&gt;  s.Append(&lt;span class="str"&gt;"}\n"&lt;/span&gt;);&lt;br&gt;  s.Append(&lt;span class="str"&gt;"window.onload = download;\n"&lt;/span&gt;);&lt;br&gt;  s.Append(&lt;span class="str"&gt;"&amp;lt;/SCRIPT&amp;gt;"&lt;/span&gt;);&lt;br&gt;  p.RegisterClientScriptBlock(&lt;span class="str"&gt;"download"&lt;/span&gt;, s.ToString());&lt;br&gt;} &lt;/pre&gt;&lt;br /&gt;&lt;p&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;A chamada desse método é bem simples, em qualquer botão de processamento e download seria: &lt;br&gt;&lt;/p&gt;&lt;pre class="csharpcode"&gt;&lt;span class="rem"&gt;// chame seu metodo que gere o arquivo &lt;span class="rem"&gt;ou pegue-o do banco de dados &lt;/span&gt;&lt;/span&gt;&lt;span class="kwrd"&gt;&lt;br&gt;byte&lt;/span&gt; [] arq =  GeraSeuArquivo();   &lt;br&gt;DownloadArquivo(&lt;span class="kwrd"&gt;this&lt;/span&gt;, arq, &lt;span class="str"&gt;"meuarquivo.ext"&lt;/span&gt;);&lt;br&gt;lblMeuLabel.Text = &lt;span class="str"&gt;"Pronto o arquivo foi enviado para o browser"&lt;/span&gt;; &lt;/pre&gt;&lt;br /&gt;&lt;p&gt;&lt;/p&gt;No código no download.aspx, apenas o minimo necessário &lt;br /&gt;&lt;p&gt;&amp;lt;%@ Page Language="C#" AutoEventWireup="true" CodeBehind="download.aspx.cs" Inherits="download" Title="Download..." %&amp;gt; &lt;/p&gt;O código no codebehind dessa página teria apenas o método Page_Load() &lt;pre class="csharpcode"&gt;&lt;span class="kwrd"&gt;protected&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; Page_Load(&lt;span class="kwrd"&gt;object&lt;/span&gt; sender, EventArgs e)&lt;br&gt;{&lt;br&gt;&lt;span class="kwrd"&gt; byte&lt;/span&gt;[] bytArq; &lt;br&gt;&lt;span class="kwrd"&gt; string&lt;/span&gt; NomeArquivo;&lt;br&gt;&lt;span class="kwrd"&gt; if&lt;/span&gt; (Session[&lt;span class="str"&gt;"downloadBytes"&lt;/span&gt;] != &lt;span class="kwrd"&gt;null&lt;/span&gt;)&lt;br&gt; {&lt;br&gt;   bytArq = (&lt;span class="kwrd"&gt;byte&lt;/span&gt;[])Session[&lt;span class="str"&gt;"downloadBytes"&lt;/span&gt;];&lt;br&gt;   &lt;span class="kwrd"&gt;if&lt;/span&gt; (bytArq.Length &amp;gt; 0)&lt;br&gt;   {&lt;br&gt;     NomeArquivo = (&lt;span class="kwrd"&gt;string&lt;/span&gt;)Session[&lt;span class="str"&gt;"downloadName"&lt;/span&gt;];&lt;br&gt;     Session[&lt;span class="str"&gt;"downloadBytes"&lt;/span&gt;] = &lt;span class="kwrd"&gt;null&lt;/span&gt;;&lt;br&gt;     Session[&lt;span class="str"&gt;"downloadName"&lt;/span&gt;] = &lt;span class="kwrd"&gt;null&lt;/span&gt;;&lt;br&gt;     Response.AddHeader(&lt;span class="str"&gt;"Content-Disposition"&lt;/span&gt;, &lt;span class="str"&gt;"attachment; filename="&lt;/span&gt; + &lt;br&gt;NomeArquivo);&lt;br&gt;     Response.AddHeader(&lt;span class="str"&gt;"Content-Type"&lt;/span&gt;, &lt;span class="str"&gt;"application/force-download"&lt;/span&gt;);&lt;br&gt;     Response.AddHeader(&lt;span class="str"&gt;"Content-Type"&lt;/span&gt;, &lt;span class="str"&gt;"application/octet-stream"&lt;/span&gt;);&lt;br&gt;     Response.AddHeader(&lt;span class="str"&gt;"Content-Type"&lt;/span&gt;, &lt;span class="str"&gt;"application/download"&lt;/span&gt;);&lt;br&gt;     Response.AddHeader(&lt;span class="str"&gt;"Content-Description"&lt;/span&gt;, &lt;span class="str"&gt;"File Transfer"&lt;/span&gt;);&lt;br&gt;     Response.OutputStream.Write(bytArq, 0, bytArq.Length);&lt;br&gt;   }&lt;br&gt;   Response.End();&lt;br&gt;  }&lt;br&gt;&lt;br&gt;}&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;Como funciona a mágica: &lt;/p&gt;&lt;br /&gt;&lt;p&gt;A página irá gerar o arquivo (byte array) e renderizará um código javascript que abrirá um popup. &lt;/p&gt;&lt;br /&gt;&lt;p&gt;Antes de terminar a execução da &lt;em&gt;pagina.aspx &lt;/em&gt;ela irá armazenar o conteudo desse arquivo na Session. &lt;/p&gt;&lt;br /&gt;&lt;p&gt;Ao termino da execução, o popup irá começar e executará o Page_Load &lt;/p&gt;&lt;br /&gt;&lt;p&gt;Nesse método, o download.aspx irá recuperar esse arquivo, removê-lo da Session e renderizá-lo no browser.&lt;br&gt;&lt;br&gt;Simples e direto. &lt;br&gt;&lt;br&gt;&lt;strong&gt;Limitações&lt;/strong&gt;: &lt;/p&gt;&lt;br /&gt;&lt;p&gt;A solução funciona, mas tem suas limitações: como a transferência de conteúdo é feita através da Session, durante essa transferência, o servidor irá ocupar esse espaço de memória (mesmo que removendo logo em seguida), o que na prática quer dizer que se for transferido um arquivo muito grande, poderá ocorrer um OutOfMemory Exception. &lt;/p&gt;&lt;br /&gt;&lt;p&gt;Taí, duvido vocês testarem.&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6417510629495760768-3032638523111204386?l=edsdias.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://edsdias.blogspot.com/feeds/3032638523111204386/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6417510629495760768&amp;postID=3032638523111204386' title='0 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6417510629495760768/posts/default/3032638523111204386'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6417510629495760768/posts/default/3032638523111204386'/><link rel='alternate' type='text/html' href='http://edsdias.blogspot.com/2008/12/download-de-arquivos-dinmicos.html' title='Download de arquivos dinâmicos'/><author><name>Edson Dias</name><uri>http://www.blogger.com/profile/07682303487677182742</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='http://3.bp.blogspot.com/_qOeTjL8L_18/STcN86W-3lI/AAAAAAAAAyQ/xKLNn5ppc3E/S220/DSC01469.JPG'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6417510629495760768.post-5669827350136675636</id><published>2008-12-05T10:36:00.003-02:00</published><updated>2008-12-05T10:46:05.056-02:00</updated><title type='text'>O porquê de um blog</title><content type='html'>Estava aqui pensando comigo, o porquê de se criar um blog e, conversando com meu colega &lt;a href="http://viniciuscanto.blogspot.com"&gt;Vinicius Canto&lt;/a&gt;, achei um motivo, e dos bons.&lt;br /&gt;Backup das minhas idéias !&lt;br /&gt;Show de bola.&lt;br /&gt;&lt;br /&gt;Sempre fico doido quando quero fazer uma simples rotina que já fiz em outro projeto ou outra empresa e nunca lembro onde guardei aquele pedaço de código.&lt;br /&gt;Agora sim, meus problemas acabaram !&lt;br /&gt;Simplesmente vou guardar tudo online.&lt;br /&gt;&lt;br /&gt;Estava querendo escrever há um bom tempo, mas nunca há tempo.&lt;br /&gt;Já recebi convites para escrever para revistas, mas o problema, como sempre é o tempo.&lt;br /&gt;A vantagem do blog nessa hora é justamente essa. Numa revista existe a "obrigatoriedade" de ter um artigo regular numa coluna, e num blog não, vou escrevendo quando der.&lt;br /&gt;Sem contar que o alcance é maior.&lt;br /&gt;&lt;br /&gt;Taí, gostei da idéia.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6417510629495760768-5669827350136675636?l=edsdias.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://edsdias.blogspot.com/feeds/5669827350136675636/comments/default' title='Postar comentários'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6417510629495760768&amp;postID=5669827350136675636' title='6 Comentários'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6417510629495760768/posts/default/5669827350136675636'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6417510629495760768/posts/default/5669827350136675636'/><link rel='alternate' type='text/html' href='http://edsdias.blogspot.com/2008/12/o-porqu-de-um-blog.html' title='O porquê de um blog'/><author><name>Edson Dias</name><uri>http://www.blogger.com/profile/07682303487677182742</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='http://3.bp.blogspot.com/_qOeTjL8L_18/STcN86W-3lI/AAAAAAAAAyQ/xKLNn5ppc3E/S220/DSC01469.JPG'/></author><thr:total>6</thr:total></entry></feed>
