quarta-feira, 30 de dezembro de 2009

SharePoint: Acesso negado ao acrescentar um servidor na farm

Ao rodar o Assistente de Configuração de Produtos e Tecnologias do SharePoint para acrescentar um servidor a uma farm, recebi o erro "Acesso Negado":

Task configdb has failed with an unknown exception
Exception:
System.Security.SecurityException: Access Denied.

Achei num post perdido no site da M$ que uma possível causa disto é versões diferentes de service packs entre os servidores. E realmente o primeiro servidor da farm estava com o SP1, e o servidor que eu estava acrescentando estava com o SP2. Instalei o SP2 no primeiro servidor, executei novamente o Assistente para acrescentar o segundo servidor à farm, e o erro não voltou a ocorrer. Algumas observações importantes no processo:
  • Para instalar o SP em um servidor com o MOSS, você tem que instalar o SP de mesma versão do WSS. O SP do MOSS *não* é cumulativo.
  • Para descobrir qual a versão do SharePoint instalado, no Painel de Controle selecione Adicionar/Remover Programas, selecione o produto (MOSS ou WSS), e clique no link Click here for support. Não encontrei no site da Microsoft uma lista de números de versões (tem aos quilos por aí), mas basta verificar se eles são iguais ou não.

terça-feira, 29 de dezembro de 2009

Windows Virtual PC: Onde está?

O Windows Virtual PC é a nova versão do Microsoft Virtual PC. Roda no Windows 7, mas não vem no Windows 7 - você tem que baixar uma atualização para instalá-lo. A página de download é http://www.microsoft.com/windows/virtual-pc/download.aspx, apesar de o título da página ser "Download Windows XP Mode". Você preenche as duas dropdowns com edição e idioma do seu Windows 7 e, caso você não queira o Windows XP Mode, selecione o segundo link para instalar só o Windows Virtual PC.

Antes de instalar o Windows Virtual PC, você tem que saber se o seu processador suporta tecnologia de virtualização de hardware (dê uma olhada nos links da Intel e AMD no artigo). A maioria dos processadores já tem VT, ou virtualization technology. Alguns não, como p.e. o T6670 do meu Vostro 1310 da Dell :-P. A Microsoft publicou uma ferramenta chamada Hardware-Assisted Virtualization Detection Tool que detecta se o seu processador suporta VT. Se ele não suportar, use o Virtual PC 2007, a versão anterior ao Windows Virtual PC. Tem menos funcionalidades, mas os discos das VM's criadas no Virtual PC 2007 tem o mesmo formato dos discos do Windows VPC.

quarta-feira, 23 de dezembro de 2009

Virtual PC: Acesso ao disco do host

Estou mexendo com máquinas virtuais no Windows 7, que vem com uma nova versão do Virtual PC: o Windows Virtual PC. Um recurso interessante, que não sei se havia na versão anterior, são os "Recursos de Integração", que permitem você capturar vários hardwares da máquina host, mas o mais legal é a possibilidade de estabelecer uma conexão com o HD do host:


[clique na imagem para o tamanho original]

Isto permite que você acesse o HD do host para, p.e., rodar instaladores de software na máquina virtual, sem ter que configurar a rede entre VM e host.

sexta-feira, 18 de dezembro de 2009

SELECT * FROM Tabela JOIN ListBox

Essa foi legal. Tava correndo num projeto de ASP.NET e me deparei com a seguinte situação: tenho uma ListBox que permite a seleção de várias linhas (propriedade SelectionMode = Multiple). Ela mostrava as linhas de uma tabela de domínio (lado 1 de um relacionamento 1-N). Quando o usuário selecionasse algumas linhas na listbox, eu tinha que carregar as linhas relacionadas aos valores selecionados na listbox. P.e., trabalhando no banco Northwind (um dos bancos de exemplo do SQL Server), na listbox aparecem todas as categorias; quando o usuário seleciona algumas categorias, temos que mostrar en um grid todos os produtos das categorias selecionadas:


O projeto usado é uma ASP.NET Web Application do Visual Studio 2010 Beta 2. Criei um Entity Data Model em cima do banco Northwind e importei as tabelas Products e Categories. A listbox carrega a tabela de categorias. O botão de carregar tem o seguinte código:

1    Protected Sub LinkButton1_Click(ByVal sender As Object, ByVal e As EventArgs) Handles LinkButton1.Click

2 Dim dados As New NorthwindEntities

3 Dim produtosDasCategoriasSelecionadas As New List(Of Products)

4 produtosDasCategoriasSelecionadas = _

5 (From linha As Products In dados.Products

6 Join item As Integer In (From x In ListBox1.Items Where x.Selected = True Select x.value)

7 On linha.CategoryID Equals item
8 Select linha).ToList()
9 GridView1.DataSource = produtosDasCategoriasSelecionadas

10 GridView1.DataBind()
11 End Sub

Olha só que MASSA é esse tal de Linq:
  • Linha 5: defino que a consulta vai retornar objetos da classe "Products", ou seja, produtos da tabela Products (a classe Products foi gerada pelo Entity Data Model do banco Northwind).
  • Linha 6, parte 1: Join item As Integer - faço um join entre a tabela Products e uma lista de inteiros que conterá as chaves das categorias selecionadas na listbox. Legal, né? Linq vê uma lista e faz as consultas em cima, não interessa se as listas são conjuntos de registros em uma tabela no banco, ou conjuntos de inteiros em memória.
  • Linha 6, parte 2: item As Integer In (From x In ListBox1.Items Where x.Selected = True Select x.value) Digo que a lista de inteiros (item As Integer) vai vir da listbox chamada ListBox1 (ListBox1.Items), mas só quero os inteiros para as opções selecionadas (Where x.Selected = True), e digo que estes inteiros corresponderão aos valores das opções da listbox (Select x.value). Em resumo, fiz um SELECT em cima dos itens de uma listbox, com cláusula WHERE e tudo!!!

  • Linha 7: é a condição de ligação do join, que filtra os produtos pela lista de chaves produzidas pela consulta à ListBox.

Poizé! Uma consulta Linq que traz dados de uma tabela, mas só para as linhas da tabela "relacionadas" com as opções selecionadas em uma listbox. Ou seja, um join entre uma tabela e uma listbox... :-) esse Linq é muito divertido mesmo...

segunda-feira, 9 de novembro de 2009

Como compilar projetos do Visual Studio para diferentes versões do .NET Framework

Estamos criando uma aplicação WPF no Visual Studio 2010 (beta 1), mas o Blend 3 não carrega assemblies compilados para .NET Framework 4.0. Então na máquina do nosso designer (chique hein), que é quem usa o Blend, tivemos que compilar uma versão do projeto para o Framework 3.5.
Um parêntesis: na nossa equipe temos um designer, um gerente de produto e um gerente de projetos. QUEM É QUE CODIFICA, meu Deus? Depois os cara ficam surpreso porque o projeto está atrasado…
Achamos um artigo falando sobre uma opção do MSBuild – o engine de compilação automatizada da Microsoft – para gerar código para uma versão específica do .NET Framework: /toolsversion. Eu achava que o MSBuild (de uma breve experiência anterior) era uma ferramenta super difícil de se trabalhar, mas a integração dele com projetos do Visual Studio tornou a tarefa ridiculamente fácil. Criamos um .bat que recompila todos os projetos da solução. Um trecho dele está a seguir:
msbuild StorageClient\StorageClient.csproj /toolsversion:3.5 /verbosity:quiet
if ERRORLEVEL 1 goto erro
O MSBuild reconhece arquivos de projeto do Visual Studio, e já ativa o compilador correspondente. A opção /toolsversion indica para qual Framework o código deve ser gerado (valores permitidos: 2.0, 3.0, 3.5 e 4.0), e sobrepõe a definição no arquivo de projeto. O if seguinte checa se a saída do MSBuild foi 1 – o que sinaliza erro. Desta forma você pode abortar a compilação dos outros projetos da solução (usando o bom (?) e velho goto).
Também vamos usar esta solução na geração das tabelas no Azure Development Storage, pois o DevTableGen – o utilitário que gera as tabelas – não suporta assemblies do Framework 4.0.
O diretório do MSBuild não está no path default de uma janela de linha de comando, então use o Visual Studio 2010 Command Prompt (grupo de programas do VS 2010 > Visual Studio 2010 Tools), que já tem o MSBuild no seu path.

sexta-feira, 6 de novembro de 2009

Chave Duplicada no Azure Table Storage

Mais uma da série “Azure: Pense Numas Mensagenzinhas de Erro RUINS”. Como testar por tentativa de inserção de linhas duplicadas no Azure Table Storage?

Como o Azure é REST-based, as mensagens de erro tem que seguir a semântica REST (falei um pouco sobre isto em outro post). Então quando você tenta inserir uma linha com chave (PartitionKey e RowKey, mas como elas identificam unicamente uma linha, vou chamá-las só de chave) idêntica a outra que já está armazenada no Table Storage do Azure, ele retorna um erro HTTP 409. De acordo com a definição do protocolo HHTP no site do W3C,

10.4.10 409 Conflict
The request could not be completed due to a conflict with the current state of the resource. This code is only allowed in situations where it is expected that the user might be able to resolve the conflict and resubmit the request.

Bem, o “recurso” – a tabela no Azure – está em um “estado” – já existe uma linha com a chave igual à linha que estou tentando inserir – que conflita com o “pedido” – o INSERT da linha com chave duplicada. Realmente, como no caso do erro 404 quando não localizo uma linha procurando pela chave (o outro post citado acima), faz sentido “de um ponto de vista REST”. Mas de novo, se estou incluindo uma linha em uma tabela, esperaria algo do tipo “Chave primária duplicada”, e não “HTTP 409 – Conflict”.

Mas como dizem aqui no cerrado, “Whatever”. O try/catch para interceptar esse erro é:

contexto.AddObject("Usuarios", novoUsuario);

try

{
contexto.SaveChanges();
}
catch (System.Data.Services.Client.DataServiceRequestException erro)
{
// DataServiceRequestException é só um wrapper para o "erro de verdade",
// que fica em DataServiceRequestException.InnerException
System.Data.Services.Client.DataServiceClientException erroMesmo =
erro.InnerException as System.Data.Services.Client.DataServiceClientException;
if ((erroMesmo != null) && (erroMesmo.StatusCode == 409))
{
// HTTP status code 409: Conflict. Na criação de uma nova linha em uma tabela
// do Table Storage do Azure, se a linha sendo incluída tem Partition Key e
// Row Key identicas a uma linha já existente, é retornado o erro 409.
throw new Exception(string.Format("Já existe uma linha com a chave ({0},{1})",
novoUsuario.PartitionKey, novoUsuario.RowKey));
}
else
throw; // Outro erro – joga a batata quente pra cima
}

sábado, 24 de outubro de 2009

Mudar PartitionKey e RowKey? "NÃO", diz o Azure SDK

Table Storage do Azure. Criamos uma classe "Usuario", pra ser armazenada "lá" (na(s) nuvem(ns)). Baseando o código num dos exemplos que encontramos por aí, tudo rodou ok.

"Beleza", digo eu. "Vamos codificar na vera agora". Bem, estávamos usando o identificador da empresa como Partition Key, e o e-mail do usuário como Row Key. Só que meu código estava meio torto. Por exemplo, pra acessar o e-mail do usuário a gente escrevia

string email = Usuario.RowKey; // Usuario.RowKey???

Pra acessar a empresa:

int codigoEmpresa = Usuario.PartitionKey; // Hã?

Obviamente, quero usar Usuario.EMail e Usuario.CodigoEmpresa. Aí começou meu quebra-pau com o Azure.

Quando a gente cria uma classe que representa as entidades (= linhas) de uma tabela (= tabela) no Table Storage do Azure, esta classe tem que ser marcada com o atributo DataServiceKeys. No exemplo de código que pegamos, a classe estava marcada com

[DataServiceKeys("PartitionKey", "RowKey"]
public class Usuario
{
int PartitionKey { get; set; }
string RowKey { get; set; }
//... Resto do código
}

"Simples", penso eu. "É só especificar o nome das propriedades que serão as Partition e Row Keys naquele atributo". Rá. Ledo engano. (Não sei o que é "ledo", mas sempre que você está totalmente enganado, o engano é um "ledo engano"). Mudei o nome das propriedades PartitionKey e RowKey para CodigoEmpresa e EMail. Renomeei as propriedades no código. Recompilei. Tudo ok.

[DataServiceKeys("CodigoEmpresa ", "EMail "]
public class Usuario{
int CodigoEmpresa { get; set; }
string EMail { get; set; }
//... Resto do código
}

Aí fui rodar o DevTableGen para gerar as tabelas no Development Storage. A tabela de usuários não foi gerada.

Peculiaridade nº 1: Se o atributo DataServiceKeys não recebe literalmente as strings "PartitionKey" e "RowKey" como parâmetro, o DevTableGen não gera a tabela.

"OME", digo eu. "Oh My Egg". Vamos então manter as propriedades PartitionKey e RowKey na minha classe, mas vamos pelo menos criar propriedades que fazem mais sentido:
[DataServiceKeys("PartitionKey", "RowKey"]
public class Usuario{
int PartitionKey { get; set; } // aqui vai ficar o código da empresa
string RowKey { get; set; } // aqui vai ficar o e-mail do usuário
// Por aqui eu leio o código da empresa
int CodigoEmpresa {
get { return PartitionKey; }
}
// Por aqui eu leio o e-mail do usuário
string EMail {
get { return RowKey; }
}
//... Resto do código
}

Coloquei propriedades read-only somente para poder dar acesso às informações que estão em PartitionKey e RowKey, mas com nomes que fazem mais sentido para a minha classe ("mais de acordo com o domínio do problema", como diriam os cientificamente corretos). Só que o DevTableGen não gerou a tabela Usuario, pois (peculiaridade nº 2) ele se recusa a gerar a tabela se há propriedades read-only na classe.

"OMLE", pensei. "Oh My Left Egg". Já cansado desta discussão e sem pensar direito, coloquei então o set das propriedades CodigoEmpresa e EMail:

[DataServiceKeys("PartitionKey", "RowKey"]
public class Usuario
{
int PartitionKey { get; set; } // aqui vai ficar o código da empresa
string RowKey { get; set; } // aqui vai ficar o e-mail do usuário
// Por aqui eu leio o código da empresa
int CodigoEmpresa {
get { return PartitionKey; }
set { PartitionKey = value; }
}
// Por aqui eu leio o e-mail do usuário
string EMail {
get { return RowKey; }
set { RowKey = value; }
}
//... Resto do código
}

A consequência (óbvia, por sinal) é que o DevTableGen gerou a tabela com ambos os pares de propriedades: agora eu tinha uma tabela de usuários que guardava o código da empresa em PartitionKey e CodigoEmpresa, e o e-mail em RowKey e EMail. Não interessa para ele se a propriedade é só uma "acessora" (accessor) a valores armazenados em outro lugar; a propriedade existe, então ele gera uma coluna pra ela.

Ainda fiz mais algumas tentativas, mas no final das contas acabei com a classe Usuario guardando o código da empresa em PartitionKey e o e-mail do usuário em RowKey, e acrescentando outra sugestão no Connect, pra ver se a Microsoft dá um jeito nisto.

A resposta foi "Obrigado por reportar esta situação. Vamos mandar para o time e blablabla vão ver se implementam para a próxima versão". Hum. Quero só ver...

domingo, 18 de outubro de 2009

AdventureWorks: Só o MDF!!!

"Pra quê simplificar se você pode complicar". Criaram um projeto no Codeplex pra instalação dos bancos AventureWorks, um conjunto de exemplos que a Microsoft começou a distribuir com o SQL Server 2005. Baixei o "troço". Tem lista de pré-requisitos - pra instalar uns BD´s de exemplo!!! E tem que ter "FILESTREAM" habilitada, o que - depois de muito apanhar - eu fiquei sabendo que não tem como habilitar na minha instalação: um SQL Server 2008 Express 32 bits em um sistema operacional de 64 bits. "By design", dizia um post no blog de um cara do time do SQL Server da M$. FILESTREAM não roda em WoW - Windows On Windows, i.e., aplicações de 32 bits rodando sobre uma emulação de um Windows 32 bits num Windows de 64 bits. A pergunta óbvia, já que existe uma versão 64 bits do SQL Server Express, é por que eu não instalei essa versão. Sei lá. Tava com sono. Tava distraído. Tava trocando a fralda da Júlia enquanto baixava o SQL Server Express.

Bem, precisei do "troço", aí baixei e instalei. O "troço" cria um monte de sub-diretório, instala uns scripts que criam a estrutura do banco, vazia, e depois carregam - via o tal de FILESTREAM - um monte de arquivos CSV nas tabelas do banco. Caraca, isso é que é complicar o que é simples. E um .BAK com um backup do banco, ou um MDF pra poder anexar o banco ao servidor, nada.

Acho que o tal do time que tá trabalhando no projeto do Codeplex deve ter alguma ótima razão pra criar um projeto de setup pra isso (tomara!!!). Mas depois de perder a paciência com esse "troço", resolvi dar um chute: baixei, lá do Codeplex mesmo, o projeto de setup do AdventureWorks da versão *2005* do SQl Server. Um MSI que tem dentro os arquivos MDF e LDF do banco AdventureWorks. Pronto! Simples. Descompactei o MSI, e anexei o BD ao meu SQL Server Express, que apesar de ser 2008, lê perfeitamente os arquivos do SQL 2005.

Pra baixar o MSI com o banco, vá em http://www.codeplex.com/MSFTDBProdSamples/Release/ProjectReleases.aspx?ReleaseId=4004. A opção é o "AdventureWorksDB.msi".

Pra descompactar o MSI, rode em um command prompt o seguinte comando:
msiexec -a NomeArquivo.MSI -qb TARGETDIR=caminho_completo_local_descompactação
Pra anexar o BD, abra o Management Studio e, no Object Browser, clique com o botão direito em "Databases" e selecione "Attach..".

Precisa de um projeto de setup pra isso???

sábado, 17 de outubro de 2009

INSERT em bloco de transação

Geek que é geek se fascina com essas coisas. Estou eu neste sábado *desesperado* estudando para o curso de SQL Server que vou começar a dar na segunda. Olhando o capítulo sobre execução de consultas no Inside SQL Server 2005: Query Tunning and Optimization, o cara (não foi a Delaney que escreveu esse capítulo - ela agora está "sub-contratando" autores pra série Inside...) me solta essa sem nem um comentariozinho sobre o código:

O cara tá fazendo uma sequência de 250.000 INSERT´s. Pra otimizar, ele abre uma transação antes do laço, e a cada 1.000 INSERT's dá um COMMIT e abre outra transação. Isso evita que seja feita uma transação pra cada comando INSERT executado. (Sim, Gafanhoto. Quando você não faz BEGIN TRAN, o SQL Server abre automaticamente uma transação pros comandos executados fora de uma transação. Isso permite, p.e., que você se arrependa e dê um ROLLBACK dentro de um trigger, mesmo sem aparentemente haver uma transação aberta).

Usando esse bloco de transações, ele roda os INSERT's em 250 transações, em vez de 250 mil transações. Lindo. Simplesmente lindo.

E acho que não precisa nem dizer, mas sim: sou geek. :-)

domingo, 11 de outubro de 2009

Tratador de Erros Global para ASP.NET e Windows Forms

Você não deve deixar *nenhuma* parte da sua aplicação sem tratamento de erro. Mas isto não significa que você terá que espalhar blocos try/catch em todo o seu código. Tanto aplicações Windows Forms quanto aplicações ASP.NET oferecem a possibilidade de criação de um tratador de erro global, que será ativado sempre que uma exceção não tratada (i.e., uma exceção que ocorreu fora de um bloco try/catch) acontecer.

Windows Forms

Como sempre, as coisas são mais fáceis em aplicações Windows Forms do que em ASP.NET. Windows Forms provê para o desenvolvedor o objeto Application que, dentre outas coisas, tem o evento ThreadException. Basicamente, devemos adicionar um tratador de eventos a este evento, e o tradador de erros global da nossa aplicação estará pronto.

Crie um novo projeto VB.NET Windows Forms e adicione um botão no formulário Form1. Depois, substitua seu código pelo seguinte:


Imports System.Diagnostics

Public Class Form1

Const NOME_FONTE_EVENTOS As String = "Minha Aplicação"

Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
' Cria a fonte de eventos no Log de Aplicação do Windows
' Isto só precisa ser feito uma vez (p.e. no setup da aplicação)
If Not EventLog.SourceExists(NOME_FONTE_EVENTOS) Then
EventLog.CreateEventSource(NOME_FONTE_EVENTOS, "Application")
End If
' Define o tratador de errors global
AddHandler Application.ThreadException, AddressOf Me.TratadorErros
End Sub

Sub TratadorErros(ByVal sender As Object, ByVal e As Threading.ThreadExceptionEventArgs)
' Acesso à exceção ocorrida
Dim erro As Exception = e.Exception
' Escreve dados da exceção no Log de Aplicação
EventLog.WriteEntry(NOME_FONTE_EVENTOS, _
"Erro não tratado: " + vbNewLine + erro.ToString(), _
EventLogEntryType.Error)
' Mostra mensagem de erro não-técnica ao usuário
MsgBox("Um erro inesperado ocorreu. Por favor entre em contato com o administrador do sistema.", _
MsgBoxStyle.Critical)
End Sub

Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
' Simula uma exceção não tratada
Throw New Exception("Oh oh Erro acessando o banco de dados")
End Sub
End Class

Clique no botão para simular uma exceção não tradada. Uma mensagem será mostrada e se você olhar o Log de Aplicação do Windows no Visualizador de Eventos (Iniciar > Executar > ebentvwr.msc), lá estará a exceção.

ASP.NET

ASP.NET disponibiliza o evento de aplição Application_Error, que é disparado sempre que uma exceção não tratada ocorre. Este tratador de evento pertence à classe de aplicação global (global application class), como o Visual Studio a chama. O código da classe de aplicação global fica no arquivo Global.asax. As aplicações ASP.NET, por default, não tem um arquivo Global.asax. Você pode adicionar um indo no menu Project e selecionando Add New Item > Global Application Class.

No tratador de evento Application_Error, você terá que usar dois métodos especiais:
  • Server.GetLastError(), que dá acesso à exceção ocorrida.
  • Server.ClearError(), que evita que o ASP.NET mostre a página com a mensagem de erro default.
Crie um novo projeto ASP.NET Web Application, adicione um arquivo Global.asax, e substitua o seu código com o seguinte:


Imports System.Web.SessionState
Imports System.Diagnostics

Public Class Global_asax
Inherits System.Web.HttpApplication

Const NOME_FONTE_EVENTOS As String = "Minha Aplicação"

Sub Application_Start(ByVal sender As Object, ByVal e As EventArgs)
' Cria a fonte de eventos no Log de Aplicação do Windows
' Isto só precisa ser feito uma vez (p.e. no setup da aplicação)
If Not EventLog.SourceExists(NOME_FONTE_EVENTOS) Then
EventLog.CreateEventSource(NOME_FONTE_EVENTOS, "Application")
End If
End Sub

Sub Application_Error(ByVal sender As Object, ByVal e As EventArgs)
' Acessa a exceção ocorrida
Dim erro As Exception = Server.GetLastError()
' Instrui o Framework a não mostrar a mensagem de erro default
Server.ClearError()
' Escreve dados da exceção no Log de Aplicação
EventLog.WriteEntry(NOME_FONTE_EVENTOS, _
"Erro não tratado: " + vbNewLine + erro.ToString(), _
EventLogEntryType.Error)
' Redireciona usuário para página com mensagem de erro não-técnica
Response.Redirect("/erro.aspx")
End Sub

End Class

Crie uma página chamada "erro.aspx"; esta é a página para a qual os usuário serão redirecionados quando da ocorrência de uma exceção não tratada.

Por último, adicione um botão à página Default.aspx, e substitua seu código com o seguinte:


Partial Public Class _Default
Inherits System.Web.UI.Page

Protected Sub Button1_Click(ByVal sender As Object, ByVal e As EventArgs) Handles Button1.Click
' Simula uma exceção não tratada
Throw New Exception("Oh oh Aquele erro de acesso ao banco de novo")
End Sub
End Class

Clique no botão e você será redirecionado para a página erro.aspx, e um evento será logado no Log de Aplicação com a informação da exceção.



UPDATE: O código no evento Application_Start vai falhar no Windows Vista e Windows 7, devido à segurança mais restrita destes sistemas operacionais. O código tenta criar uma fonte de eventos no Log de Aplicação para logar os erros nesta fonte. Os métodos EventLog.SourceExists() e EventLog.Create() tentam varrer os logs do Windows para verificar se a fonte especificada já existe. Isto causa o erro, pois por default não é permitido o acesso ao Log de Segurançapor aplicações ASP.NET. Há várias maneiras de se solucionar isto, mas uma solução simples e rápida é criar a fonte "na mão": crie no Registry a seguinte chave: HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\eventlog\Application\NOME_APLICACAO, trocando NOME_APLICACAO pelo nome da fonte de eventos que você quer criar. Um caminho "mais correto" seria p.e. criar uma aplicação console que executasse o código do evento Application_Start, e empacotar esta aplicação em no pacote de setup do seu site, para ser executada ao final do setup.

quinta-feira, 8 de outubro de 2009

Hã? Silverlight?

Para quem está iniciando no desenvolvimento em Silverlight, tem uma série de artigos do Tim Heuer (Gerente de Programa da Microsoft para o Silverlight) que são bastante didáticos e dão um empurrão bom em quem ainda está na linha de partida:

http://timheuer.com/blog/articles/getting-started-with-silverlight-development.aspx

O investimento de tempo vale a pena!

SQL Server Compact is not intended for ASP.NET development

O SQL Server Compact é uma versão do SQL Server bastante restrita em termos de recursos, mas que roda in-process, ou seja, não roda como um serviço. Desta forma, aplicações que o usam não precisam de direitos daministrativos na sua instalação, o deploy destas aplicações é simplificado (em relação a instalar outras edições do SQL Server), e o uso de recursos é baixo. Roda até em Windows Mobile!

Bem, tentei usar um banco do SQL Server Compact Edition em um site ASP.NET de teste que estava fazendo pra dar aula. Aí apareceu a mensagem de erro "SQL Server Compact is not intended for ASP.NET development". Isto porque, como a mensagem diz, o SQL Server Compact não foi projetado para desenvolvimento ASP.NET. Algo a ver com problemas de acesso multi-usuário. Mas se você quiser usá-lo só para um teste rápido, basta colocar no seu Global.Asax o seguinte código:


Sub Application_Start(ByVal sender As Object, ByVal e As EventArgs
AppDomain.CurrentDomain.SetData("SQLServerCompactEditionUnderWebHosting", True)
End Sub

Desta forma você "está se responsabilizando" pelo uso do SQL CE na sua aplicação ASP.NET, e o erro não volta a ocorrer.

quarta-feira, 7 de outubro de 2009

www.whatismyip.org

Ao procurar um gerador de hashes SHA-1 pra strings, esbarrei com este site: www.whatismyip.org. O gerador de hashes fica em http://www.whatsmyip.org/hash_generator/. Tem outras ferramentas úteis, como um codificador/decodificador de strings base-64 e um contador de caracteres.

domingo, 4 de outubro de 2009

Não consigo subir VM no Virtual Server

As VM's instaladas pelo Virtual Server são disparadas pelo Virtual Server Administration Website. Só que quando eu tentava iniciar uma VM, e também em algumas outras opções (ex: troca do tipo de disco de IDE para SCSI), a tela HTML do Vitual Server Administration Website simplesmente não respondia. E ainda aparecia na barra de status do IE: "Error on page", que nem quando você acessa uma página com erro de JavaScript. Bem, não sei o que estava acontecendo, mas se você clicar naquele botãozinho de "Modo de Exibição de Compatibilidade" do IE8, a página funciona normalmente.

LINQ to SQL x LINQ to Entities

Este anúncio tem quase 1 ano, mas só esbarrei com ele agora, ao começar a estudar LINQ To SQL para o curso 2310. O Program Manager para LINQ to SQL e LINQ to Entities anunciou no blog da equipe do ADO.NET que "a partir do .NET Framework 4.0 [Visual Studio 2010], LINQ to Entities será a solução recomendada [pela Microsoft] de acesso a dados com LINQ em cenários relacionais". LINQ to SQL será mantido, mas pelo jeito, não será mais evoluído.

sexta-feira, 2 de outubro de 2009

400 Bad Request acessando o Blob Storage do Azure

Rapidinha que já perdi MUITO tempo com esse erro imbecil. Fui acessar o Blob Storage do Azure e qualquer operação que eu chamava retornava "400 - Bad Request". Depois de 3 horas virando, revirando e testando mil coisas, descobrimos que o erro era que na hora que eu ia instanciar um objeto da classe BlobStorage, através de BlobStorage.Create(), eu passava as credenciais do Table Storage, em vez das credenciais do Blob Storage.

Código errado:
BlobStorage blobs = BlobStorage.Create(
StorageAccountInfo.GetDefaultTableStorageAccountFromConfiguration());
Código certo:
BlobStorage blobs = BlobStorage.Create(
StorageAccountInfo.GetDefaultBlobStorageAccountFromConfiguration());
Tem 3 métodos de recuperação de credenciais: GetDefaultTableStorageAccountFromConfiguration(), GetDefaultBlobStorageAccountFromConfiguration(), e GetDefaultQueueStorageAccountFromConfiguration(). Cada um correspondendo ao storage do Azure que você quer acessar. Ok, eu chamei o método errado. Mas "Bad Request"??? Sinceramente, as mensagens de erro do Azure estão precisando de uma revisada...

quarta-feira, 30 de setembro de 2009

404 Resource Not Found For Segment acessando o Table Storage do Azure

Essa tem algo a ver com o acesso ao Azure ser baseado em REST (Representational State Transfer). Devo confessar minha ignorância, pois li um pouco sobre REST mas não entendi quase nada. Mas pelo que entendi, é uma forma de arquitetura para softwares distribuídos. Engraçado que foi criado baseado em uma análise da Internet como software, e parece criar uma teoria bastante complicada em cima de algo que já usamos e, de certa forma, já dominamos.

Bem, o négocio é o seguinte: fui procurar um item em uma tabela no Table Storage do Azure. Inicialmente, a impressão que dava é que o erro retornado - 404 Resource Not Found for Segment 'Nome da Tabela' - aparecia aleatoriamente. Depois vimos que ele aparecia quando a tabela na qual fazíamos a procura estava vazia. E na verdade, um comentário de Andrew Conrad, que participa do projeto de Linq To REST da Microsoft, indica que este erro aparece quando o item é procurado por sua chave e não é encontrado na lista. Isto porque, segundo REST, as aplicações distribuídas são compostas de clientes e servidores, e os servidores fornecem recursos aos clientes - como os arquivos de um servidor Web. Então, quando uma consulta REST procura um recurso específico - como p.e., uma consulta Linq em uma tabela no Table Storage do Azure, e este recurso não é encontrado, é retornado o erro "Resource Not Found" - como o erro 404 em HTTP.

Este erro parece obedecer à teoria do REST, mas realmente, quando você trabalha com algo chamado *Table* Storage, a primeira coisa que vem na cabeça é algo semelhante ao acesso a um BD, e não um acesso a um recurso REST. Então quando algo não é encontrado, a gente espera um resultset vazio, e não um erro. Pelo comentário do Andrew Conrad citado acima, eles já estão cientes desta, digamos, "peculiaridade" do Azure, e planejam fazer algo mais intuitivo na próxima versão.

Por enquanto a solução é envolver seu código em um Try/Catch nada elegante:
try
{
var elemento =
(for item in contextoAzure.MinhaTabela
where item.PartitionKey = '...' and item.RowKey = '...'
select item).FirstOrDefault();
}
catch (DataServiceQueryException erro)
{
if(erro.Response.StatusCode == 404)
// elemento não foi encontrado
}

segunda-feira, 28 de setembro de 2009

Check-outs Múltiplos no TFS

Equipe de geeks (2: eu e o Luti). Instalamos o Visual Studio 2010 (beta, of course, que geek que se preza não trabalha em software estável), com o Team Foundation Server, e criamos nosso primeiro projeto. Depois de algum estudo do Azure, começamos a codificar. Criamos nossas primeiras classes.

"Editei o ContextoDados.cs. Tenta editar ele aí", diz o Luti. Nem sei de onde ele tirou a idéia de testar o TFS SCC (Source Code Control - o Controle de Código Fonte - do TFS, sucessor do Visual SourceSafe). Bem, fiz aquela cara de ai-meu-saco-tenho-mais-o-que-fazer-e-claro-que-vai-funcionar-tudo, e fui fazer o check-out. "Uai", sai sem querer a exclamação mineira, depois de 20+ anos aqui no DF. "Não é que checkautô?". O Luti faz aquela cara de toma-seu-mané. "Fiz check-in. Altera alguma coisa aê e faz check-in também", ele diz. Eu faço uma alteração e, na hora que tento fazer check-in, aparece uma tela de resolução de conflitos de edição. Auto-Merge, Merge Manually, Changed, Deleted, Next, Previous... Tudo pronto pra causar uma boa confusão. Uai de novo. Isso já não funcionava redondo no Visual SourceSafe?

O TFS SCC vem com duas modificações radicais nas suas configurações default, em relação ao SourceSafe:

  • A primeira: check-outs múltiplos são permitidos por default. No VSS, o check-out múltiplo podia ser habilitado, mas o default era check-out simples: somente um desenvolvedor pode travar um dado arquivo para edição. Se outro desenvolvedor tentasse travar o mesmo arquivo (o check-out), ele receberia uma mensagem e não conseguiria editar o arquivo.

Esta até que não chega a ser tão problemática assim. Da primeira vez que houvesse um check-out múltiplo, apareceria a tela de resolução de conflitos de edição, e alguém falaria "Opa! O check-out múltiplo está habilitado". Aí é só desabilitá-lo e tudo ok.

  • O problema sério é a segunda modificação. Quando um desenvolvedor faz um check-out, ele *não* recebe a última versão do arquivo armazenada no servidor!!! Isto significa que, se você tem uma versão antiga de um arquivo na sua máquina,e faz check-out deste arquivo, você vai editá-lo sem receber as modificações já feitas por outros desenvolvedores.

Ok, quando você fizer check-in, vão aparecer conflitos para todas estas modificações; mas somente pela quantidade de conflitos caso sua versão seja muito antiga, e pela proximidade do botão "Next", há um grande potencial para que modificações sejam perdidas. De fato, ao pesquisar sobre o assunto, encontrei relatos de equipes que, em apenas algumas semanas de trabalho, já estavam experimentando este tipo de problema.

As configurações default do Visual SourceSafe evitavam estes dois problemas. No VSS, o check-out múltiplo era desabilitado por default, ou seja, só um desenvolvedor pode trabalhar em um arquivo em um determinado momento. E quando você fazia o check-out, você rebebia a última versão do arquivo. Isto podia quebrar a sua compilação local, por o seu código não estar de acordo com as modificações mais recentes feitas no arquivo recebido durante o check-out. Mas isto obrigava você a manter o seu código atualizado. E evitava que seu check-in sobrescrevesse coisas que outros já tinham feito.

Se você, como eu, a torcida do Vascão e a maioria dos desenvolvedores prefere o esquema do VSS, basta abrir o projeto no Team Explorer, fazer duplo-clique no item Source Control, e no menu Team, selecionar a opção Team Projet Settings > Source Control. Em seguida, inverta a seleção de opções:

Desta forma o SCC do TFS irá trabalhar como o VSS, quanto às suas configurações de check-out.

sábado, 26 de setembro de 2009

Visualizar Arquivos - Conversor para PDF online

Precisei visualizar um arquivo .PUB (Microsoft Publisher) e esbarrei com este cara. BCL Premium PDF Online Service permite que você envie um arquivo ao site e, se ele for de uma das 300 extensões cadastradas, o site converte o arquivo para PDF e disponibiliza o PDF para download por até 24h. Consegui desta maneira visualizar o conteúdo de um arquivo do Publisher sem o dito cujo na máquina - já que o viewer do Publisher é o próprio software - você instala o trial e após o período de trial ele só permite visualização (o que despertou a fúria da galera na Internet, no blog On Microsoft Publisher And More da MSDN).

segunda-feira, 14 de setembro de 2009

Access Denied: stsadm no Windows 2008 (como Administrador!!!)

Well, well... Sei lá. A Microsoft introduziu o UAC (User Access Control) no Windows Vista e no Windows 2008. O objetivo é evitar que você se descuide e faça alguma besteira em algum lugar importante (p.e., num servidor). As aplicações tem agora dados de access control. A idéia é que aplicações sensíveis só possam ser executadas em "modo administrador". De acordo com o UAC Guide na TechNet, mesmo um usuário administrador, ao logar, recebe dois conjuntos de credenciais de segurança: um como usuário "normal" e outro de administrador. Quando uma aplicação marcada com access control que pede por um usuário administrador é executada, o Windows pede confirmação para executar a aplicação como administrador e, caso sua conta não tenha este direito, ainda abre uma janela de logon para vocês especificar uma conta administrativa.

É uma idéia legal, pois desde criancinha a gente aprende a não dar direitos administrativos para contas de usuários "normais"; nossos pais sempre dizem "crie uma conta administrativa, trabalhe com sua conta de usuário normal, e quando for fazer alguma tarefa mais privilegiada, logue com a conta administrativa". O UAC permite isto, pois exige uma interação explicita do usuário para confirmar que você quer rodar uma aplicação como administrador.



O problema é quando a aplicação exige direitos de administrador e não aparece a janelinha acima. Por exemplo, rodando a ferramenta de linha de comando de administração do SharePoint, o stsadm. Você loga no servidor como administrador, abre um prompt de comando, muda pro diretório do stsadm, roda um comando qualquer de administração do SharePoint e... Access denied. Roda só o help do stsadm: stsadm -?. Access denied. Pô, acesso negado no help? Eita programa seguro. Na verdade, o stsadm precisa de que você o rode com direitos administrativos em relação ao UAC, então mesmo logado como administrador, você precisa abrir o prompt de comando no qual o stsadm será executado como administrador:



Como a aplicação que irá disparar o stsadm (o prompt de comando) já foi aberto com as credenciais de administrador perante o UAC, então, e só então, o stsadm roda.

Ou você pode desabilitar o UAC no servidor. Mas não conta pra ninguém que eu sugeri isto. Sorriso

Não Adiantou Mas Foi Legal

Coloquei uma sugestão pra poder inserir uma opção de menu no Team Explorer 2010 que excluísse um projeto do TFS. Foi educadamente recusada pela Microsoft, mas pelo menos foi bom ver que não foi um auto-reply que gerou a resposta; foi alguém que conhecia do produto. O link pra sugestão está em http://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=488149. Legal esse Connect.

quinta-feira, 10 de setembro de 2009

Could not load file or assembly CrystalDecisions.CrystalReports.Engine

Se você desenvolveu uma aplicação ASP.NET no Visual Studio 2008, e usou o Crystal Reports 2008 Basic (a versão do Crystal que vem com o Visual Studio 2008), ao tentar rodar a aplicação em um IIS "pelado", será gerada a mensagem de erro "Could not load file or assembly 'CrystalDecisions.CrystalReports.Engine, Version=10.5.3700.0" etc etc etc. Isto porque o site precisa do runtime do Crystal Reports para poder rodar. Um pacote de instalação MSI com este runtime está no diretório C:\Program Files (x86)\Microsoft SDKs\Windows\v6.0A\Bootstrapper\Packages\CrystalReports10_5 da máquina aonde o Visual Studio está instalado. Basta instalar este MSI no servidor web aonde sua aplicação rodará, e o erro será solucionado.

ASP.NET 3.5 não aparece no IIS

Ao configurar um site ASP.NET no IIS Manager, quando vamos na página de propriedades do site (ou do diretório virtual), existe uma aba para selecionar a versão do ASP.NET. Mas na lista "ASP.NET version", não aparece a versão 3.5 (nem a 3.51, nem a 3.51 SP1):



Bem, de acordo com um post de Vijayshinva Karnure (!!!), no seu blog no site da MSDN, este é o comportamento esperado, pois as versões 3.x não são frameworks "completos", como as versões 1.0, 1.1 e 2.0 - são enriquecimento de funcionalidades em cima da versão 2. Novos controles, novas bibliotecas, mas a "infraestrutura" usada é a da versão 2. Então se você está instalando uma aplicação ASP.NET feita no Visual Studio 2008, ao criar o site no IIS Manager, selecione a versão 2.0 na lista de versões do ASP.NET. Se a máquina tiver instalado o Framework 3.5, a configuração do site estará correta.

terça-feira, 8 de setembro de 2009

Chatices do Windows 2008 Para Desenvolvedores

Bem, um resumo do que descobri sobre o Windows 2008. Podemos chamar de "Chatices do Windows 2008 Para Desenvolvedores", ou "Como Perder Um Dia Tentanto Usar o Windows 2008 Em Ambiente Virtualizado".

  1. Você começa a pesquisar o Windows 2008 e descobre que tem uma versão nova dele: o Windows 2008 R2. "Legal", pensa você. "Vou baixar ela e instalar numa VM do Virtual PC". Tome-lhe 3,2Gb de donwload.
A consequência do item 1 é que Windows 2008 R2 em VM só se seu sistema operacional já for o Windows 2008, para rodar a VM no Hyper-V, ou se você usar um dos produtos VMWare - o mais barato é o VMWare Server, que é gratuito, mas tome-lhe 0,5Gb de download.
  1. Para rodar um sistema operacional de 64 bits dentro de uma VM, o seu processador precisar suportar tecnologia de virtualização.
    • Processadores Intel: deve haver suporte à Intel VT - Intel Virtualization Technology, ou Intel Vanderpool Technology. Tem uma lista de suporte a VT em http://ark.intel.com/VTList.aspx. E tem uma ferramenta de identificar o processador em http://www.intel.com/support/processors/tools/piu/sb/cs-014921.htm.
    • Cuidado com o PC Wizard: a versão 2008 reconheceu erroneamente meu processador como o Intel mobile T7100, que suporta VT. A versão 2009 reconheceu o processador corretamente como o T5670, que não suporta VT.
Resumo da opera, verifique se seu processador tem suporte a tecnologia de virtualização. Geralmente isto pode ser visto como uma opção no setup da BIOS. Tem um programinha chamado SecurAble, em http://www.grc.com/securable.htm, que verifica isto.
  1. Ok. Tem que ser o Windows 2008 de 32 bits. Só que aí você descobre o tal de "Windows 2008 Server Core", que requer aproximadamente 1/3 dos recursos de hadware do Windows 2008 "normal". Ótima pedida pra uma VM!!!
    • O Windows 2008 Server Core requer menos recursos que as edições "normais" porque, dentre outros componentes, não tem a GUI (inteface gráfica) - é tudo linha de comando, até o sistema operacional estar todo configurado, quando ele poderá ser acessado via TS ou MMC.
    • Uma instalação Server Core pode exercer um dentre vários "papéis" (roles), dentre os quais está o IIS.
    • Infelizmente, dentre os componentes que estão faltando, está o .NET Framework. Ou seja, ASP.NET: esquece. SQL Server 2005 ou superior: esquece também.
    • Felizmente, no Windows 2008 *R2* o papel IIS de uma instalação Server Core vem com o .NET Framework. Ou seja, ASP.NET: roda. SQL Server 2005: roda, mas "não suportado": http://www.nullsession.com/2009/06/02/sql-server-2008-on-server-core-2008-r2/.
    • Infelizmente, meu processador não suporta o diacho da Intel VM. Então, nada de Windows 2008 R2. E nada de Server Core com menos consumo de máquina.
Bem, como é pra ambiente de desenvolvimento, a escolha é baixar o Windows 2008 Web Edition 32 bits (tome-lhe mais 3,2Gb de download). Infelizmente, os links de trial pras versões de 32 bits parecem estar sendo desativados pela M$. Então ou você tem uma assinatura da MSDN ou TechNet, pra baixar as versões de 32 bits, ou você vai ter que comprar um processador que tenha a tecnologia de virtualização, pra poder usar as de 64 bits.

Você tem aí, em poucos minutos, o que levei um dia inteiro para descobrir. Basicamente, se você vai montar uma VM com Windows 2008 para ambiente de desenvolvimento ASP.NET, é o seguinte:

  1. Se seu processador suporta tecnologia de virtualização, você pode baixar a versão nova do Windows 2008, que é a R2.
    • A vantagem é tentar instalar um Windows 2008 Server Core com ASP.NET e SQL Server, que em teoria consome menos máquina que uma instalação normal do Windows 2008. Não tentei ainda, só encontrei links falando que dá pra fazer.
    • Pra rodar essa VM, só no VMWare. O Virtual PC e o Virtual Server não suportam VM´s com sistemas operacionais de 64 bits. Ou vc instala o W2008 na sua máquina e roda a VM no Hyper-V.
  2. Se o seu processador não suporta virtualização, baixe uma versão 32-bits do Windows 2008.
    • Roda no VMWare ou no Virtual PC/Virtual Server.
    • O Server Core não roda ASP.NET nem SQL Server, então tem que ser uma das edições "normais". Vou tentar a Web Edition.
É isso. Haja detalhe....





Um update: Se você chegou até aqui, é que está tentando montar uma máquina de testes usando o Virtual PC, ou o Hyper-V, ou outro trem desses. Se você usa Windows 7 ou Windows 2008, tem uma opção *espetacular* pra montar máquinas de teste: dar boot através de um VHD. Dá uma olhada nesse post: Máquina de Testes usando Boot de um VHD.

[]s,

GB

Vostro 1310 Não Roda VM com Guest de 64 bits

Poizé. Fui tentar instalar uma VM no Virtual PC pra testar o Windows 2008. Baixei o ISO do W2008 64 bits (2.8Gb de download num link ADSL de 1Mb - haja saco). Apanhei um pouco até descobrir que o Virtual PC não roda sistema operacional guest de 64 bits. "Usa o VMWare", a Internet recomendava. Baixei o VMWare Server: mais 0.5Gb de download no mesmo link lerdo, e ainda com a esposa desligando o disjuntor aonde o modem tava na metade dele - e não sei porque diabos o site da VMWare não dá suporte a gerenciador de downloads. SACO!!! Mas o mesmo erro de instalação aparecia: "attempting to load a 64-bit application however this cpu is not compatible with 64-bit mode". Uai. O PC Wizard (2008) relata meu processador como sendo o "Intel Core 2 Duo Mobile T7100", que, de acordo com o site da Intel, suporta a Virtualization Technology, necessária para a execução de sistemas operacionais de 64 bits virtualizados. Depois de rodar bastante na tal da Internet, encontrei o SecurAble, em http://www.grc.com/securable.htm, que de acordo com o site detecta as 3 principais tecnologias de segurança em termos de hardware (64 bits, DEP e VT - Tecnologia de Virtualização). E ele relatou minha CPU como sendo o T5670, que não tem suporte a virtualização. Mostrando a língua Depois de um dia inteiro tentando instalar o Windows 2008 64 bits, vou ter que caçar uma versão de 32 bits pra poder fazer meus testes.

Saco.



Um update: veja mais sobre o assunto no post seguinte a este: Chatices do Windows 2008 Para Desenvolvedores.

sexta-feira, 4 de setembro de 2009

Como Excluir um Projeto do TFS

Vai entender. Pra você criar um projeto no Team Foundation Server, a Microsoft disponibilizou um wizard com interface gráfica muito fácil de usar. Agora pra excluir um projeto (team project, no jagão do TFS), tem que entrar em ferramenta de linha de comando. No grupo de programas do Visual Studio (estou usando o 2010, mas deve servir para 2005 e 2008 também), tem uma pasta chamada "Visual Studio Tools". Entre na opção "Visual Studio 2010 Command Prompt", e digite o seguinte comando:

tfsDeleteProject /server:url_do_tfs nome_projeto

O primeiro parâmetro, url_do_tfs, deve ser a URL aonde seu Team Foundation Server está instalado. Cuidado neste parâmetro, ele deve ser a URL exata do TFS, incluindo número de porta e caminho completo. P.e., no meu servidor, a URL usada é http://srv07:8080/tfs. O segundo parâmetro é o nome do projeto (deve estar entre aspas duplas caso o nome do projeto contenha espaços).

No Team Explorer tem uma opção "Remover", que remove o projeto do Team Explorer, mas sem apagar ele do TFS. Por que não colocar uma opção "Excluir" também??? Vou sugerir lá no Connect...

terça-feira, 25 de agosto de 2009

Perdi a senha do Admin no VSS

Achei um utilitário para limpar a senha do usuário Admin de uma instalação de Visual SourceSafe 6.0. Basta descompactar e rodar este arquivo aqui em um prompt de comando no diretório VSS\Data da sua instalação, renomear um arquivo (aparece na tela qual o arquivo a renomear), e pronto. Foi fácil achar - foi o terceiro resultado da pesquisa no Google -, mas esse treco é tão velho que é melhor guardar em algum canto.

segunda-feira, 24 de agosto de 2009

RSAT para Windows 7

A Microsoft disponibiliza um pacote de ferramentas administrativa muito útil chamado RSAT – Remote Server Administration Tools. Foi lançada uma versão beta para Windows 7, já que a versão do RSAT para Windows Vista não funciona no W7. Só que na Internet tem vários links incorretos para a página de download do RSAT para W7. E além disto, aparentemente a MS se esqueceu de colocar a string “RSAT” na página que descreve o download da ferramenta em download.microsoft.com, pois uma procurar por RSAT lá não lista o RSAT para W7 (será que é por que a procura é “Bing-based”? ;-). Só consegui localizar o pacote procurando por remote tools windows 7. O endereço do qual consegui fazer o download é http://www.microsoft.com/downloads/details.aspx?displaylang=en&FamilyID=7d2f6ad7-656b-4313-a005-4e344e43997d. Aproveitem!

segunda-feira, 17 de agosto de 2009

MSN não minimiza mais!!!

No Windows 7, O MSN não minimiza mais para a área de notificação (system tray ou "bandeja do sistema", aqueles ícones na parte direita da barra de tarefas do Windows). Ficam sempre um ou dois botões na barra de tarefas, e se você tenta fechá-los, acaba fechando o MSN. Se você deseja o comportamento antigo do MSN no Vista, basta selecionar o ícone do MSN no Menu Iniciar do Windows, botão direito > Propriedades, e na tab "Compatibilidade", selecionar na lista "Rodar este programa em modo de compatibilidade com" o valor "Windows Vista". Pronto, o MSN minimiza "normalmente" agora...

sexta-feira, 14 de agosto de 2009

Desenvolver Ou Não Desenvolver, Eis a Questão

Estava fuçando o Twitter e pensei: como faço pra ver os tweets da galera que estou acompanhando, de forma fácil? Aí tive a idéia de implementar um gadget pra Barra Lateral do Windows Vista que mostrasse os tweets de algumas contas que eu configurasse. Comecei a estudar como desenvolver um gadget pra Barra Lateral do Vista, e encontrei alguma material sobre isto no MSDN (Windows Sidebar: Introdução aos Gadgets, Developers Guide e Reference).

Em resumo, os gadgets nada mais são do que código HTML mostrados em janelas que são instâncias aparentemente restritas do Internet Explorer (restritas pois tentei mostrar um objeto em Flash e não rolou). Peguei o código HTML pra mostrar meus tweets em uma página HTML, coloquei em um gadget, e apareceu lá. Nice...

Bem, feita a "prova de conceito", vamos desenvolver o gadget todo. Quero alguma coisa que dê para eu configurar quais contas no Twitter eu quero visualizar. Tem que ser mostrados os tweets mais recentes de todas as contas configuradas. Ok. Tenho que criar um tela de configuração pra que sejam fornecidas as contas que quero acompanhar. Tenho que bolar algum jeito de mostrar os tweets recentes de todas essas contas, algo como recarregar a tela de x em x segundos com os tweets da próxima conta da lista que defini, ou talvez uma barra de rolagem... Hummm, fazer isso em JavaScript (eca)....

No final usei o gadget de vizualizar RSS do Vista, acrescentei uma instância pra o RSS de cada conta do Tweeter que queria acompanhar e fui gastar meu tempo em algo mais "nobre". Moral da estória é que às vezes a solução não sai exatamente como desejamos (ou até mesmo longe do ideal), mas para o nosso cliente, na grande maioria das vezes, a solução parcial atende totalmente às suas necessidades, mesmo que uma solução mais completa "atendesse mais".

Isto é terrível pra um desenvolvedor que gosta de desenvolver. É a mesma coisa que jogar um osso pra um cachorro e falar "Ó, morde só um pouquinho e depois me devolve". E geralmente nós, desenvolvedores, reagimos como cachorros - algumas rosnadas e até uma eventual mordida Sorriso. Mas nós temos que lembrar que o objetivo último de nossa profissão é atender às necessidades do cliente. E tem como se divertir trabalhando assim também. Versionamento, entregas curtas e outros conceitos semelhantes permitem que nós organizemos nosso trabalho para fazer isto. É só se esforçar um pouquinho pra "dividir o osso" com nosso cliente - afinal de contas, às vezes a gente esquece, mas ele também quer usar a solução... Wink

quinta-feira, 6 de agosto de 2009

WCF, Parte 2: Análise de uma Aplicação WCF

Esta é a parte 2 de uma série de posts sobre WCF. Leia a parte 1.

Depois da introdução sobre WCF na parte 1 desta série, vamos examinar quais os processos envolvidos na solicitação e na execução de um serviço, e depois examinaremos como modelar um sistema que seja dividos nestes processos. Na parte 3 finalmente iremos codificar e analisar o código de cada um dos processos em questão. Este post está dividido nas seguintes sessões:

Hello WCF: Arquitetura de Processos: quais são as aplicações que compõem nossa aplicação distribuída, e como elas se comunicam.
Hello WCF: Arquitetura do Código: Como está organizado o código destas aplicações.

Hello WCF: Arquitetura de Processos

Vamos primeiro entender quais são os processos envolvidos na nossa primeira aplicação WCF. Estamos disponibilizando um serviço na rede que executa a espetacular operação de gerar a string Hello WCF!!! toda vez que é invocado. Um dos requisitos do nosso serviço é que ele possa ser invocado de qualquer máquina da nossa rede, então pelo menos duas máquinas estarão envolvidas no processamento: o cliente e o hospedeiro (mas vou chamar esta última de host porque “hospedeiro” doeu fundo no ouvido ;-). O cliente é a máquina que solicita o serviço, e o host é a máquina aonde o serviço é executado.


Fig.1 – As máquinas cliente e host.

Na verdade, não são máquinas que se comunicam, mas sim processos rodando nestas máquinas. Facilita o entendimento pensar como sendo dois processos em máquinas diferentes (Fig. 2), mas neste nosso teste ambos os processos, cliente e host, estarão rodando na mesma máquina.


Fig.2 – Os processos cliente e host.

WCF torna a comunicação entre os processos envolvidos o mais transparente possível. Neste caso, iremos usar o protocolo HTTP para a comunicação entre clientes e host. Ao usarmos WCF na nossa aplicação host, os objetos do namespace System.ServiceModel já provêem quase tudo que é necessário para que o host receba pedidos de execução de serviços provenientes de HTTP.SYS, que é o componente do IIS que recebe os pedidos de comunicação HTTP e os despacha para o “processo certo”. Você verá no código do host como ele avisa ao IIS que está esperando pedidos de acesso, e aonde ele está esperando – é o conceito de endpoint, que é o ponto de chegada de pedidos de acesso a um serviço WCF.


Fig.3 – Ao usar HTTP, o endpoint é gerenciado por HTTP.SYS, que envia o pedido de acesso ao serviço para o processo host.

Como a escolha do protocolo de comunicação é um detalhe de implementação, na próxima figura vamos retirar HTTP.SYS do esquema. A figura 4 retrata as trocas de mensagens entre cliente e host, e como o serviço é disponibilizado:

  • É criada uma classe na aplicação host que representa o serviço (ServicoHelloWCF);
  • Este serviço disponibiliza uma série de operações, que são os métodos da classe que implementa o serviço. Neste caso, nosso serviço tem apenas uma operação, cuja assinatura é: string HelloWCF() – ou seja, uma operação chamada HelloWCF, que não recebe parâmetros e retorna uma string.
  • O cliente envia uma mensagem de execução de uma operação ao processo host; o processo instancia a classe que implementa o serviço, executa o método que corresponde à operação desejada, e retorna o resultado para o cliente.


Fig.4 – A execução de uma operação de um serviço WCF.

Hello WCF: Arquitetura do Código

O código de nossa aplicação exemplo será dividido em 3 projetos: duas aplicações Console e uma Class Library.

As aplicações Console representam o cliente e o host, os dois processos se comunicando. A aplicação Class Library representa o contrato do serviço. O contrato do serviço é uma descrição – atenção meninos, descrição, e não implementação – do serviço oferecido pelo host. Já comentamos antes que um serviço WCF é um conjunto de operações, sendo o serviço implementado por uma classe, e as operações implementadas pelos métodos desta classe. O contrato do serviço descreve esta classe e seus métodos, mas não os implementa. Tanto o cliente quanto o host tem que conhecer os detalhes do serviço sendo invocado. O cliente tem que saber quais operações ele pode invocar, e como elas devem ser invocadas. O host tem que implementar exatamente o que o cliente espera invocar. Ou seja, ambos, cliente e host, tem que conhecer e obedecer à descrição do serviço. Desta forma, aparece o terceiro projeto na nossa solução, que nada mais é do que uma Class Library compartilhada entre cliente e host, que contém uma interface que define o contrato do serviço: quais as operações que cada serviço oferecido deve implementar.


Fig.5 – Usaremos uma Class Library para compartilhar uma interface (ITesteWCF) que descreve o service contract.

Veja que ambos os projetos, o Cliente e o Host, usam a interface ITesteWCF que contém o contrato do serviço. O Cliente usa a inteface para saber como chamar o serviço; e o Host a utiliza criando uma classe que implementa esta interface, desta forma criando uma classe que implementa o serviço oferecido.

No próximo post veremos o código de cada um destes projetos: o contrato do serviço, o host e o cliente.

Update: Apesar de esta postagem ser antiga, notei que recentemente o acesso a ela tem aumentado. Infelizmente, o envolvimento em outros projetos parou meu estudo de WCF. Por isto, não escrevi a sequência de artigos sobre WCF que iria se iniciar com este post. Espero que quando entrarmos em um projeto que use WCF eu volte para esta série.

Atenciosamente,

GB

terça-feira, 4 de agosto de 2009

"Executar Como..." no Vista

Precisei logo depois do Management Studio Express, pra poder executar ele com a minha conta de administração de rede:
ShellRunas provides functionality similar to that of Runas to launch programs as a different user via a convenient shell context-menu entry.
Descompacte e execute com o parâmetro /reg. Isto cria a entrada "Run as different user" no menu de contexto dos link e executáveis.

SQL Server Management Studio Express

(Aposto que muita gente já conhece, mas como estive fora da área por muito tempo, aí vai)

Prático e gratuito:
http://www.microsoft.com/downloadS/details.aspx?familyid=C243A5AE-4BD1-4E3D-94B8-5A0F62BF7796&displaylang=en
Microsoft SQL Server Management Studio Express (SSMSE) is a free, easy-to-use graphical management tool for managing SQL Server 2005 Express Edition and SQL Server 2005 Express Edition with Advanced Services.



Só um update, tem pro SQL 2008 também: http://www.microsoft.com/Downloads/details.aspx?familyid=08E52AC2-1D62-45F6-9A4A-4B76A8564A2B&displaylang=pt-br

sexta-feira, 10 de julho de 2009

Fonte Para Desenvolvedores: Anonymous True Type

Agora que voltei a por a mão na massa, desenterrei uma velha favorita minha: a fonte Anonymous True Type. Ela é uma fonte feita para desenvolvedores e foi disponibilizada gratuitamente na Internet pelo seu autor, Mark Simonson (http://www.ms-studio.com). "Feita para desenvolvedores" significa uma fonte de tamanho fixo, de fácil leitura, e com representações bem distintas para caracteres que podem causar confusão, como "0" e "O" (zero e "o" maiúsculo), "1" e "l" e "I" (um e a letra "L" minúscula e a letra "i" maiúscula), e outros.



A fonte pode ser baixada aqui: Anonymous TT.zip. Obrigado ao autor pelo presente!

segunda-feira, 6 de julho de 2009

Teste Geek

Tava arrumando meu HD e encontrei algumas piadinhas infames de geek. Veja as imagens a seguir e selecione uma opção:

  1. Só entendi as das calcinhas
    Hummmm... Você tá mais pra usuário do que pra geek.

  2. Legal as das calcinhas, e a do HTML também!
    Iiihh... Tu é geek.

  3. Caraca! Entendi todas!
    Master Geek!

E se você não entendeu nenhuma, tá desculpado, deve ser só um curioso de passagem... :-)

Teste de Concentração

A receita é a seguinte:
  1. Tenha uma filha chamada Sacola Atômica, e outra chamada Fundo Froxo.

    Sacola Atômica e Fundo Froxo

  2. Tenha uma terceira filha chamada Tonel de Baba.

    Tonel de Baba

  3. Coloque Fundo Froxo, que fala besteira pelos cotovelos, de castigo no seu escritório enquanto você estuda.

  4. Coloque Tonel de Baba no bercinho bem atrás da sua cadeira.

  5. Coloque Sacola Atômica para fora do escritório, mandando ela ir para a sala ver TV.

  6. Leia um livro em inglês enquanto ouve Fundo Frouxo falar 450 frases por minuto, sendo 75% delas sem o menor sentido, ao mesmo tempo em que Tonel de Baba chora de sono atrás da sua cadeira.

  7. Responda educadamente pela 34a vez para Fundo Froxo que ela está de castigo porque não arrumou o quarto de brinquedos e ainda fez xixi no chão do quarto quando você colocou ela lá pra poder arrumar a bagunça.

  8. Receba uma carta de Sacola Atômica dizendo que você anda muito brabo.

Se o seu estudo render alguma coisa, parabéns. Sua concentração está excelente.

domingo, 28 de junho de 2009

WCF, Parte 1: SOA e WCF

Bom Dia Galera! Depois de algum tempo como gerente, só mexendo em Outlook e Excel, senti falta da área técnica. Peguei uma pilha de material com o Luti pra me atualizar (http://luticm.blogspot.com - o menino é o cara de SQL e até acha que joga futebol), e a primeira leitura está sendo o livro Learning WCF.



Parte 1 da Parte 1 - SOA

Bem, o livro começa falando sobre SOA. Se você ler esta primeira parte, aposto que você irá pensar assim: "Uai, mas isso eu já fiz!". Aposto que você irá reconhecer a arquitetura que você bolou para alguns sistemas. Todo bom arquiteto de software se preocupa com modularização e reuso das funcionalidades que serão implementadas, e SOA é o terceiro degrau na escada de paradigmas para isto.
O primeiro degrau é OOA – Arquitetura Orientada a Objetos. O uso de orientação a objetos em uma aplicação permite que código seja modularizado e reutilizado através do encapsulamento fornecido pelo uso de classes – você cria funcionalidade dentro de uma classe, e reutiliza este código em várias partes da aplicação sendo desenvolvida. Por exemplo, podemos criar uma classe que manipule o Estoque da empresa, para ser chamada sempre que for necessário qualquer operação de consulta ou modificação do estoque.


Fig.1 – Aplicação com arquitetura orientada a objetos.

O segundo degrau é COA – Arquitetura Orientada a Componentes. Nosso time de desenvolvimento do exemplo anterior, ao partir para a próxima aplicação a ser construída, precisou novamente de realizar operações no estoque. “Oras Bolas!”, pensa o arquiteto. “Macacos me mordam!”, fala ele com seus botões. “Com mil demônios!”, grita ele alto J. O que o deixou tão empolgado é que este código já está pronto – só que atualmente faz parte da primeira aplicação desenvolvida. Ele então reestrutura a aplicação para separar a classe de Estoque dentro de um projeto Class Library, o que permite que a classe Estoque compilada seja compartilhada pelas aplicações – em vez de colocar o código da classe dentro da segunda aplicação, o que seria péssimo, e não preciso nem dizer porquê. Ao compartilhar código binário entre aplicações, nosso arquiteto usou uma arquitetura orientada a componentes – agora ambas as aplicações usam um componente dedicado a autenticar usuários.


Fig.2 – Aplicações com arquitetura orientada a componentes.

E agora, naturalmente, todas as aplicações da empresa irão usar este mesmo mecanismo de manipulação do estoque. Só que algumas aplicações Web estão na DMZ, do lado de fora do firewall, e o “povo de infra” disse que não vai abrir a porta 1433 no firewall para o componente conseguir falar com o SQL Server na LAN. Além disso, outras aplicações, em vez de estarem escritas em ASP.NET, estão escritas em Java! E pra completar, a empresa ainda fez um acordo com outra empresa através do qual esta outra empresa poderá fazer solicitações aos sistemas corporativos – o que implicitamente envoverá disponibilizar as operações de manipulação de estoque para sistemas rodando na Internet.


Fig.3 – Aplicações com arquitetura orientada a serviços.

E isto é SOA. Apesar de não ser esta a definição formal, o objetivo de uma aplicação com arquitetura orientada a serviços é permitir que funcionalidade, geralmente da camada de negócio, seja exposta para outras aplicações, independente do local e da plataforma destas aplicações. Estas “aplicações clientes” podem estar na mesma máquina que o serviço (a funcionalidade exposta), em outra máquina dentro da mesma rede, ou até mesmo fora da rede aonde o serviço está; e não necessariamente tem que estar escrita na mesma plataforma de desenvolvimento do serviço.

Parte 2 da Parte 1 – E o WCF?
Windows Communication Foundation é a mais recente tecnologia da Microsoft para facilitar a vida de quem quer desenvolver uma aplicação SOA. Ela é a última em uma “linha de evolução” de tecnologias para suporte a aplicações distribuídas – porque no núcleo da idéia de SOA está o conceito de aplicação distribuída, como fica evidente na figura 3. Estas tecnologias, em ordem (mais ou menos) cronológica, são:
  • DCOM, ou Distributed COM. O Component Object Model (só COM, sem o "D") permitia que lá no Visual Basic 6 você colocasse uma referência a um componente e reutilizasse código entre aplicações (fig.2). Logo depois, apareceu o DCOM, para permitir que isto pudesse ser feito mesmo que o componente estivesse em outra máquina. Legal, não? Só que só funciona para Windows, tem protocolo de comunicação proprietário e é uma programação chata, pois há vários… ahn… cuidados que devem ser tomados, para que programas escritos em uma liguagem possam chamar componentes escritos em outra. Desde o Windows 2000 o DCOM vem “escondido” dentro do Component Services, um pedaço do Windows que se dedica a facilitar a construção de aplicações com arquitetura orientada a componentes.
  • Enterprise Services: um namespace do .NET Framework que expõe o Componet Services para aplicações .NET.
  • .NET Remoting: outro namespace do .NET Framework dedicado à programação distribuída. Ele permite que aplicações clientes ativem objetos remotos – que vivem em outro processo, outra máquina ou até mesmo outra rede.
  • Web Services: o .NET Framework tem um namespace para implementação de Web Services, mas esta tecnologia não é proprietária da Microsoft. Ela visa a ativação de um objeto remoto, como no .NET Remoting, mas utilizando-se de protocolos Web padrão para comunicação, e baseada em um contrato de ativação do objeto, que descreve (em uma linguagem formal chamada WSDL) como o objeto deve ser invocado, e qual é o formato da resposta à cada possível chamada. Isto permite interoperabilidade quase que completamente transparente entre plataformas.

Cada uma destas tem suas vantagens e suas limitações, mas todas com o objetivo de fornecer uma forma o mais transparente possível de implementar programação distribuída, independente do local e da plataforma das aplicações envolvidas. Cada uma procurava aumentar esta independência, e ao mesmo tempo facilitar o seu uso pelo desenvolvedor, desta forma melhorando a produtividade. WCF é o mais recente passo nesta direção, e o objetivo da Microsoft com ela é fornecer uma tecnologia de proramação distribuída que possa substituir todas as anteriores, e desta forma fornecer um único modelo de programação orientada a serviços. É esta tecnologia que iremos explorar nesta série de artigos.

Update: Apesar de esta postagem ser antiga (aliás, a postagem mais antiga do meu blog), notei que recentemente o acesso a ela tem aumentado. Infelizmente, o envolvimento em outros projetos parou meu estudo de WCF. Por isto, não escrevi a sequência de artigos sobre WCF que iria se iniciar com este post. Espero que quando entrarmos em um projeto que use WCF eu volte para esta série.

Atenciosamente,

GB