Páginas

quarta-feira, 24 de dezembro de 2008

Operador yield no C#

Hoje encontrei um operador no C# que desconhecia, o yield.

Ele serve para manter estado quando se percorre uma coleção de objetos, e está intimente ligado à implementação do pattern Iterator dentro do C#. Na prática, ele pode ser aplicado quando temos métodos que retornam um IEnumerable.

No exemplo abaixo, eu tenho um método que percorre as datas de finais de semana (Sábado e Domingo) dado um ano. Veja que este método é chamado dentro de um foreach, e cada iteração ele exibe uma data na tela. Não estou preocupado, dentro do foreach, em saber qual foi a última data que foi exibida, isso é controlado internamente durante a iteração, que vai mantendo o loop "ativo" através do operador yield.

Feliz Natal e até a próxima!

using System;
using System.Collections.Generic;

namespace TesteYield
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Finais de semana de 2009:");
            foreach (DateTime data in ObterFinaisDeSemana(2009))
                Console.WriteLine("{0:dd/MM/yyyy}", data);
            Console.ReadKey(true);
        }

        private static IEnumerable<DateTime>ObterFinaisDeSemana(int ano)
        {
            DateTime pivo = new DateTime(ano, 1, 1);
            while (pivo.Year == ano)
            {
                if (pivo.DayOfWeek == DayOfWeek.Sunday  pivo.DayOfWeek == DayOfWeek.Saturday)
                    yield return pivo;
                pivo = pivo.AddDays(1);
            }
        }
    }
}

terça-feira, 2 de dezembro de 2008

Barbarismo

Estou escrevendo um texto sobre classes customizadas para a leitura de configurações no .NET..., mas senti que a palavra "customizadas", apesar de muito utilizada nas empresas e em especial na área de informática, não soa legal...

Customizar vem da palavra "customize" e que vem de "customer", "cliente" em inglês, ou seja, construir, alterar ou reformar conforme especificações individuais. Pode ser um estrangeirismo, o ato de adotar uma palavra de outra língua se não tivermos uma correspondente. Se tiver uma correspondente, é chamado de barbarismo.

Então, para não correr o risco de um barbarismo, resolvi colocar a palavra "personalizar". Melhor, não?

Senão vou começar a usar termos como "deployar" em vez de "implantar", "buildar" em vez de "compilar", etc..., aí não dá certo, rs.

[]'s

sábado, 29 de novembro de 2008

Erro de 404 com ASP.NET em Windows 2003 Server (IIS6)

Você criou um novo diretório virtual em um novo servidor Windows 2003 (IIS6), colocou uma aplicação ASP.NET nele, e quando foi acessá-lo, eis que aparece o erro 404! E o engraçado, quando você acessa páginas HTML, elas abrem sem problemas! Estranho? Não, diria que a mensagem é que não é clara. Provavelmente o ASP.NET não está habilitado nas Web Service Extensions. É só colocá-los como Allowed que seu site irá funcionar.


[]'s

sábado, 1 de novembro de 2008

Artigo de PostSharp .NET Magazine

Este mês foi publicado um artigo que fiz para a .NET Magazine, sobre PostSharp.

http://www.devmedia.com.br/space.asp?id=206189

Quem quiser prestigiar meu humilde artigo, pode comprar a versão online da revista no link acima, ou a impressa na banca de revistas de sua preferência!

[]'s

domingo, 10 de agosto de 2008

Como informações dentro do CallContext são passadas entre threads?

Estes dias tenho feito testes para uma prova de conceito de uma infra que estou desenvolvendo, para instrumentar chamadas de métodos.

Nela, a idéia é ir armazenando informações do contexto da chamada (parâmetros, tempo de chamada, usuário, máquina, etc), para se ter a rastreabilidade do que ocorre na execução dos sistemas.

Cheguei na conclusão que o uso da classe CallContext é uma boa para manter essas informações, pois o que é armazenado nela é trafegado entre threads e appdomains, durante o contexto da execução (lembrando que os objetos nela armazenados devem implementar ILogicalThreadAffinative, para que funcione como desejado).

Uma dúvida tinha ficado no ar... Como são mantidas as informações quando o contexto da execução passa para outras threads, por exemplo, via ThreadPool?

A resposta está na classe ExecutionContext. Cada thread possui uma instância desse objeto associada, e é nessa instância que são armazenadas informações como contexto de segurança e sincronização. E também é onde se coloca o CallContext.

Durante a instancia uma nova classe Thread, é pego o ExecutionContext da thread atual, copiado e passado para a nova thread. É dessa maneira que as informações passam de uma thread para a nova.

Vale lembrar que isso funciona apenas no .NET Framework 2.0 e superiores, pois no 1.x não funciona dessa maneira.

[]'s

quinta-feira, 26 de junho de 2008

MySQL error number 1005 Can’t create table ‘.\mydb\#sql-328_45.frm’ (errno: 150)

Tenho trabalhado em um projeto freelancer que utiliza base de dados MySQL. Fiz uma alteração em um modelo de dados, e entre as alterações tive que criar uma nova FK entre duas tabelas, sendo que a tabela pai antes não existia.

Na hora de executar o script que cria a FK, me deparei com um erro, a primeira vista, complicado de resolver. A execução do script retornava:
MySQL Error Number 1005Can’t create table ‘.\mydb\#sql-328_45.frm’ (errno: 150)

Após buscar um pouco no Google (o oráculo de todos os desenvolvedores!), encontrei uma página que explicava este erro. A página, em inglês, é http://www.verysimple.com/blog/2006/10/22/mysql-error-number-1005-cant-create-table-mydbsql-328_45frm-errno-150/.

Basicamente e neste caso, este erro ocorre porque os pré-requisitos para a criação de uma FK não foram atendidos.

Para conferir se todos os itens necessários para a FK foram atendidos, é só seguir a checklist abaixo:
  1. Os campos da tabela pai e da tabela filho são do mesmo tipo e tamanho? De início pode parecer besta a sugestão, mas o Query Browser considera como tipo INTEGER tanto o INT(10) quanto o INT(11). Além disso, é preciso conferir se o campo é SIGNED ou UNSIGNED. Para conferir essas informações, o melhor é comparar o resultado do comando SHOW CREATE TABLE .
  2. O(s) campo(s) que você quer referenciar devem ser chaves primárias ou pelo menos possuir um índice.
  3. Verifique se você não está querendo criar uma FK com um nome que já existe.
  4. Verifique se as tabelas usam o InnoDB. Se estiverem com MyISAM, não vai funcionar.
  5. Verifique se o Charset e o Collate estão iguais nos campos referenciados.
  6. Verifique se você não está especificando um valor default na FK.
  7. Está especificado um SET NULL para o DELETE cascade, mas a coluna é do tipo NOT NULL. Para arrumar isso, ou remova esse SET NULL, ou permita valores NULL neste campo.
  8. E finalizando, veja se o seu ALTER TABLE não tem algum erro de sintaxe!

Este post foi muito útil para mim, e me ajudou a identificar que minhas tabelas estava com MyISAM e alguns campos estavam marcados como UNSIGNED e outros não...

[]'s

terça-feira, 27 de maio de 2008

PostSharp

Estou entusiasmado com uma ferramenta chamada PostSharp.

Ela trabalha no conceito de programação orientada a aspectos (AOP), e diferente do Spring.NET ou Policy Injection App Block, ela altera o código IL das dll's geradas para inserir o código que faz a interceptação das chamadas.

Acho que estou indo rápido demais, rs, mas hoje só vou colocar o link dessa ferramenta. Lá existe um ótimo tutorial de como usá-la http://www.postsharp.org/.

Depois eu coloco mais coisas sobre ela, conforme for descobrindo.

[]'s

quarta-feira, 30 de abril de 2008

Artigos "perdidos" na Internet

Olá!

Tive a curiosidade de procurar meu nome no Google. Encontrei algumas coisas "esquecidas": dois artigos que escrevi faz tempo, e que nem lembrava que ainda estavam disponíveis na Internet.

Um bem básico, quando estava começando a mexer com ASP.NET, que publiquei no site Asp4Developers (do Rubens Farias): http://rubensfarias.blogspot.com/2004/01/aspnet-user-controls_04.html.

Outro sobre Generics, quando lançaram no .NET 2.0: http://www.linhadecodigo.com.br/Artigo.aspx?id=780.

Quem sabe me animo a voltar a escrever mais?

[]'s

sexta-feira, 25 de abril de 2008

Impressão de Etiquetas com Reporting Services

Encontrei um artigo muito legal sobre impressão de etiquetas usando o SQL Reporting Services.

http://altoonait.com/CS/blogs/lee/archive/2007/12/13/printing-labels-with-sql-server-reporting-services.aspx

Um item que usei diferente na minha implementação: no lugar de ter uma coluna no datasource que informa o índice de cada elemento do mesmo, usei a função RowNumber(Nothing), ao invés do que o autor sugeriu (=IIF(Fields!Rank.value mod 3=0,false,true)).

[]'s

Atualização 2012-08-24: O link original está quebrado, mas encontrei o artigo do blog em outro endereço: http://blog.altoonait.com/2011/02/printing-labels-with-ssrs-2005.html

sexta-feira, 28 de março de 2008

ASP.NET AJAX e a data da máquina

Primeiramente, PQP!

Pronto, já me revoltei do erro tosco que eu estava tendo.

Bom, estou desenvolvendo uma aplicação ASP.NET, com Visual Studio 2008 e AJAX, quando hoje o meu site começou a dar um erro estranho...
Ao tentar abrir páginas com controles como TreeView, TabControl, etc, a mesma não era carregada corretamente. Imagens e recursos (como arquivos JavaScript) faltando, o que acabava caindo no erro "Sys is undefined" (basicamente, este erro ocorre porque o browser não consegue carregar alguns scripts através do
ScriptResource.axd).

Fiquei chateado com o erro (para não dizer pré-desesperado, rs). Para idenficar melhor o que estava acontecendo, peguei uma das urls geradas pelo ScriptResource.axd ou WebResource.axd e testei ela no browser. Apareceu um outro erro: "Specified argument was out of the range of valid values. Parameter name: utcDate".

Google pra cá, Google prá lá, acabei encontrando algumas pessoas que tiveram esse problema quando a hora da máquina estava atrasada...

Olhei para meu relógio, e a "surpresa" é que ele estava 2 anos atrasado! Arrumei e tudo voltou a funcionar!

Agora porque estava atrasado? É que a bateria do meu computador deve estar zuada, e todo dia tenho que colocar a data e hora, e devo ter me enganado hoje...

Amanhã vou ver de ir comprar uma bateria nova...

terça-feira, 18 de março de 2008

Permissões para uso do EventLog - Windows 2003

Olá, pessoal!


Hoje vou falar sobre alguns problemas que tive que passar, a respeito do uso do EventLog, mais especificamente na gravação. São os erros:

System.Security.SecurityException: Requested registry access is not allowed.

Este erro ocorre quando uma aplicação tenta gravar um registro no EventLog, mas não possui permissões para gravar no registry do Windows. Isso acontece porque o os sources do EventLog ficam armazenados no registry, embaixo da seguinte chave: HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\Eventlog\Application (isso para os sources que ficam na no Application, ainda temos os do Security, System, e outros que você venha a criar). Quando se quer criar um source novo, deve-se escrever no registry.

O importante a notar aqui é que a conta que está tentando escrever no EventLog deve ter permissão de escrita nessas chaves do registry. Ou então esse source já deve estar criado, para que este problema não ocorra.

Obs. Esse problema de permissão pode ser verificado através do Regmon, verificando os erros de ACCESS DENIED que ocorrem.

Cannot open log for source {0}. You may not have write access.

Este outro erro foi mais chato de descobrir, e acontecia quando uma conta de usuário tentava gravar em um source já existente no servidor, criado por outro serviço. Mesmo executando o Filemon e o Regmon, não aparecia nada que pudesse indicar onde estava o problema. Primeiro tentei dar permissão ao usuário que tentava gravar tanto nas chaves do registry quanto no arquivo onde ficam armazenados os dados do EventLog (%WINDIR%\system32\config), mas sem sucesso.

Neste caso, o que acontece é que no Windows 2003 Server, a permissão de gravação fica armazenada em uma chave no registry, chamada CustomSD (Custom Security Description). É ela que define quem pode gravar, ler e demais opções, dentro do EvenLog.

Essa chave fica em HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\Eventlog\Application\CustomSD, e seu valor é uma string a primeira vista muito confusa:
O:BAG:SYD:(D;;0xf0007;;;AN)(D;;0xf0007;;;BG)(A;;0xf0007;;;SY)(A;;0x7;;;BA) (A;;0x7;;;SO)(A;;0x3;;;IU)(A;;0x3;;;SU)(A;;0x3;;;S-1-5-3)

Muita calma nessa hora, o que cada coisa quer dizer? Vamos quebrar essa string por partes, para entender:

O:BA A letra O indica que se está especificando o owner do objeto, no caso o grupo de administradores da máquina (Built-in Admin - BA).
G:SY A letra G indica que está sendo especificado o primary group, no caso System (SY).
D: Indica que é uma DACL, ao inves de uma entrada de auditoria ou SACL.
(D;;0xf0007;;;AN) Nega o acesso totalmente para o Anonymous (Deny para AN).
(D;;0xf0007;;;BG) Nega o acesso totalmente ao Built-in Guests (Deny para BG) .
(A;;0xf0005;;;SY) Permite que o System leia e limpe (incluindo DELETE, READ_CONTROL, WRITE_DAC, e WRITE_OWNER, indicado pelo 0xf0000).
(A;;0x7;;;BA) Permite READ, WRITE e CLEAR para o Built-in Admin (BA).
(A;;0x7;;;SO) Permite READ, WRITE e CLEAR para Server Operators (SO).
(A;;0x3;;;IU) Permite READ e WRITE para Interactive Users (IU).
(A;;0x3;;;SU) Permite READ e WRITE para Service accounts (SU).
(A;;0x3;;;S-1-5-3) Permite READ e WRITE para Batch accounts (S-1-5-3).

O valor 0x3 indica que é permitido leitura e escrita, pois ele é composto através da soma de ELF_LOGFILE_READ (0x0001) e ELF_LOGFILE_WRITE (0x0002). Outro valor que pode ser combinado é ELF_LOGFILE_CLEAR (0x0004).

Com isso, podemos dar as permissões necessárias, informando o que cada usuário pode fazer.

No meu caso, esse problema aconteceu quando um web service com impersonate ligado estava tentando gravar no registry. Os usuários autenticados não tinham permissão para gravar, então dava o erro. Foi adicionado o (A;;0x3;;;AU), e o problema foi corrigido!

E se eu quisesse dar permissão para o NETWORK SERVICE, que é a conta que o ASP.NET roda no Windows 2003, colocaria (A;;0x3;;;NS).

Espero que este post seja útil para mim tanto quanto os posts de outros blogs me foram, para resolver este problema (http://support.microsoft.com/kb/329291, http://www.leastprivilege.com/EventLogACLsInWindows2003.aspx e http://www.jameskovacs.com/blog/PermaLink.aspx?guid=cd6e5f6e-7107-48bc-8563-f5669706fcdc). É incrível como, se você perquisar no Google as mensagens de erro, acaba encontrando tantas threads de fóruns que citam este problema, mas não dão a resolução.

[]'s

sábado, 15 de março de 2008

Document-Level Templates no VSTO 2005 SE

Tenho dois computadores, um que uso durante a semana, e outro que fica na casa dos meus pais que eu uso no final de semana.

Esse segundo computador, por ser uma configuração menos privilegiada que o primeiro, tem o Windows XP, Office 2003 e Visual Studio 2005 (o outro está com oVista, Office 2007 e Visual Studio 2008).

Bom, como estou estudando VSTO, decidi instalá-lo neste computador. Baixe o "Microsoft Visual Studio 2005 Tools for the 2007 Microsoft Office System" em http://www.microsoft.com/downloads/details.aspx?FamilyId=5E86CAB3-6FD6-4955-B979-E1676DB6B3CB&displaylang=en, mas quando instalei e fui abrir um projeto de documento (estou lendo sobre smart tags e action pane, que estão disponíveis apenas para documentos, e não add-ins), não encontrei nenhum template!

Ao ler os detalhes do download do VSTO 2005 SE, vi que esses templates não estão disponíveis na versão do Visual Studio que eu tenho instalada (2005 Professional). Apenas para as versões:
  • Visual Studio 2005 Team Suite
  • Visual Studio 2005 Team Edition for Software Architects
  • Visual Studio 2005 Team Edition for Software Developers
  • Visual Studio 2005 Team Edition for Software Testers
  • Visual Studio 2005 Tools for the Microsoft Office System
Então, o jeito é estudar essas customizações do VSTO apenas no computador que uso durante a semana...

sábado, 8 de março de 2008

Log do VSTO

Nas últimas semanas, estive trabalhando em um projeto que utiliza o VSTO (Visual Studio Tools for Office). Aprendi algumas coisas legais. E como a gente aprende com nossos erros, aqui vai uma coisa que aprendi hoje.

Criei um addin Excel, que deveria ser carregado toda vez que o Excel é utilizado. Pois bem, isso não estava acontecendo... Quando eu abria o Excel, nada acontecia. Visualizando o addin COM no Excel, vi que o mesmo não estava sendo carregado (dava um erro). Mas o por que ficava vago...

Procurando na Internet, descobri algumas variáveis de ambiente que precisam ser ajustadas, para que então seja gerado um log dos erros que ocorrem com o VSTO.

Essas variáveis são:
VSTO_SUPPRESSDISPLAYALERTS (0 ou 1) - define se as mensagens de erro serão exibidas em uma MessageBox. O padrão é 1, indicando que as mesmas não devem ser exibidas. VSTO_LOGALERTS (0 ou 1) - define se os erros serão logados. Caso ligado (valor 1), os erros do VSTO são gravados em disco, com informações relevantes para que seja possível descobrir a causa deles. No caso, os arquivos ficam juntos do arquivo de manifesto da dll do VSTO (bom, vai estar tudo na pasta que você instalou o addin).

Obs 1. No meu caso, o erro era que a dll não carregava por falta de permissão. O VSTO exige que a segurança do .NET Framework seja configurada para uso (caspol). Minhas dll's não estavam nas configurações, então as coloquei nas configurações de segurança, verificando os assemblies que possuiam determinado strong name.

Obs 2. Para o meu caso, era um addin Excel 2003. Os itens que a máquina do usuário final necessitam ter são:
  • Office 2003 Update: Redistributable Primary Interop Assemblies
  • Microsoft Visual Studio 2005 Tools for Office Second Edition Runtime (build 8.0.50272.940) (x86)
  • Microsoft .NET Framework Version 2.0 Redistributable Package (x86)

Segue o link onde encontrei informações muito interessantes sobre o deplyment de uma solução VSTO Office 2003: http://blogs.msdn.com/vsto/archive/2008/02/19/deploying-prerequisites-for-your-visual-studio-tools-for-office-solution.aspx.

[]'s

quinta-feira, 6 de março de 2008

Finalmente Blog!

Finalmente estou escrevendo alguma coisa neste blog! Espero que de agora em diante, eu passe por aqui mais vezes...

A minha idéia em fazer um blog vem da vontade de compartilhar algumas coisas que aprendo no dia-a-dia do trabalho. É como um agradecimento aos vários blogs onde já encontrei coisas interessantes, importantes e que salvaram várias horas do meu tempo e da minha paciência. Coisas que eu poderia estar até agora pesquisando e "batendo cabeça".

Trabalho com desenvolvimento de sistema há algum tempo, e acredito que as coisas que vou descobrindo a cada dia podem ser úteis à outras pessoas. Artigos interessantes, dicas e links farão parte deste diário. E de preferência textos curtos, porque eu me conheço: se for escrever alguma coisa longa, vou acabar desistindo no meio do caminho!

Também vou aproveitar este espaço para falar um pouco dos lugares que conheço, das idéias que tenho, etc.

Enfim, o que todo mundo faz num blog, rs.

Vou ficando por aqui, até breve!