Mostrando postagens com marcador Registry. Mostrar todas as postagens
Mostrando postagens com marcador Registry. Mostrar todas as postagens

3 de abril de 2012

Preparando aplicações Delphi para requerer incremento no Nível de Execução

Desde o Windows XP, a Microsoft vem implementando medidas que dificultam o acesso não autorizado a certos recursos do sistema, como o Registry, por exemplo. O intuito é incrementar a segurança do sistema operacional, evitando seu comprometimento ou até mesmo o roubo de informações. Esse esforço foi mais notado no Windows Vista, quando foi introduzido o UAC (User Account Control) para solicitar ao usuário permissão para acessar os recursos.

Com essa mudança, programas que antes liam tranquilamente o registro do Windows deixaram de funcionar. Dependendo de como o programa foi implementado, a exceção levantada pela falta de privilégio de acesso ao recurso pode até mesmo derrubar a aplicação com mensagens de erro pouco amistosas. O quadro abaixo traz um exemplo de código em Delphi que executa sem problemas no XP mas que não funcionará no Vista e no Win7 - a menos que o usuário comande a execução como Administrador:
procedure TForm1.BitBtn1Click(Sender: TObject);
var lReg: TRegistry;
begin
lReg := TRegistry.Create();

try
lReg.RootKey := HKEY_LOCAL_MACHINE;
lReg.OpenKey('Software\empresa', true);
lReg.WriteString('TipoImpressora', '0');
Application.MessageBox('Opção gravada com sucesso', 'Aviso', MB_OK);
except
on Erro: Exception do
Application.ShowException(Erro);
end;

lReg.Free;
end;
Felizmente, há um meio de informar ao sistema operacional que uma operação dessa natureza vai ocorrer e que, portanto, o usuário necessitará obrigatoriamente de privilégios de administrador para executar o programa. Esse processo é chamado de Requisição de Elevação do Nível de Execução e é feito através de um arquivo de manifesto que deve ser linkado junto com a aplicação.

O manifesto é um arquivo XML com estrutura bem definida, como a mostrada no quadro abaixo:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<assemblyIdentity
name="ABC71.TesteManifest"
processorArchitecture="x86"
version="1.0.0.0"
type="win32"/>
<v3:trustInfo xmlns:v3="urn:schemas-microsoft-com:asm.v3">
<v3:security>
<v3:requestedPrivileges>
<v3:requestedExecutionLevel level="requireAdministrator" uiAccess="false"/>
</v3:requestedPrivileges>
</v3:security>
</v3:trustInfo>
<description>TesteManifest</description>
</assembly>
O manifesto é composto de duas partes obrigatórias. O assembly é o nó raiz do XML, usado para aninhar as demais tags com as configurações em si. A tag interna assemblyIdentity identifica nossa aplicação, armazenando um nome único para ela e informando sua versão e a arquitetura para a qual ela foi desenhada. No exemplo, vemos que a nossa aplicação é Win32 e roda em processadores x86.

As outras tags são opcionais mas o nosso exemplo inclui também a tag v3:trustInfo, que é onde registramos a requisição do incremento de nível de execução. Tal requisição é feita no parâmetro level da tag requestedExecutionLevel, seguindo a estrutura mostrada acima. Quando informamos o valor requireAdministrator em level estamos dizendo ao Windows que o programa só pode executar se tiver privilégios de administrador. Então, antes de executá-lo, o Windows apresentará a tela para que o usuário forneça as credenciais do administrador - nome e senha - e só prosseguirá se elas estiverem corretas.

Para que essa configuração tenha efeito, precisamos criar um arquivo de recursos que aponta o manifesto e então, linká-lo ao programa Delphi. Um arquivo de recursos é um repositório onde são indicadas informações a serem agregadas a um programa, permitindo adicionar desde ícones e cursores até blocos de texto e dados binários para uso da aplicação. O arquivo de recurso pode ter extensão RC (quando é somente um texto) ou RES (resultado da compilação do RC). Supondo que o arquivo de manifesto se chame manifesto.manifest, um arquivo RC pode ser montado assim:
#define MANIFEST_RESOURCE_ID 1
MANIFEST_RESOURCE_ID 24 manifesto.manifest
O número 24 nesse arquivo indica ao Windows que o recurso em questão é um arquivo de manifesto. O arquivo RC deve ser adicionado ao projeto do Delphi e o arquivo de manifesto deve estar disponível na mesma pasta. Lembre-se que o Delphi cria automaticamente um arquivo RES com o mesmo nome do projeto; então, escolha um nome diferente do projeto para o RC extra.

Essa requisição de elevação de nível é especialmente útil em programas para configuração ou instalação de sistemas, situações que geralmente exigem privilégios mais altos para acesso a recursos protegidos, mais sensíveis. Na verdade, arquivos de manifesto são mais complexos do que o que foi apresentado aqui, servindo também para indicar se uma aplicação utilizará temas do Windows, se essa aplicação tem dependências de bibliotecas externas, entre outras coisas. O MSDN documenta o conteúdo permitido para esses arquivos neste link.

Versões mais recentes do Delphi permitem utilizar temas na criação de aplicações e, por isso, elas embutem automaticamente um manifesto em cada projeto. Assim, para conseguir inserir a requisição de incremento do nível de execução nestas versões, é preciso modificar a configuração do projeto, pedindo que se considere um arquivo de manifesto externo ao invés daquele que vem por padrão. Na página de configuração da aplicação - a mesma onde se muda o ícone do seu programa, selecione a opção "Use Custom Manifest" na caixa Runtime Themes. Depois, informe o caminho do seu arquivo de manifesto na caixa Custom Manifest, logo abaixo.

18 de junho de 2010

Registrando automaticamente uma fonte de dados para acesso ODBC

Muitas aplicações que trabalham com banco de dados ainda fazem o acesso através de uma fonte de dados ODBC. Isso normalmente exige que se faça uma configuração através das Ferramentas Administrativas do Painel de Controle do Windows em cada estação que fará uso da aplicação em questão.

A ABC71 usa o ADO com OleDB na maioria de suas aplicações para acessar banco de dados. Os poucos módulos que necessitam ter uma configuração ODBC externa são os relacionados à Qualidade (Metrologia e Inspeção da Qualidade), que já estão sendo revistos e também deverão adotar o ADO em breve.

Enquanto isso não acontece, incluimos no projeto desses módulos código para criar automaticamente as configurações, de modo que o usuário não precisa se preocupar com essa criação. Basicamente, configurar uma fonte de dados ODBC é criar algumas entradas no registry do Windows - a localização das chaves variará, dependendo se você quer disponibilizar a fonte só para o usuário atual do Windows ou para todos. Qualquer que seja o caso, a hierarquia de chaves é \\SOFTWARE\\ODBC\\ODBC.INI. Esta chave é onde são armazenados os drivers ODBC instalados no computador. Ai também fica a chave "ODBC Data Sources", que, como diz o nome, é onde o Windows armazena as fontes de dados para conexões ODBC. Veja abaixo um exemplo em C++ Builder para acessar essa chave. Para usar em Delphi, basta adaptar a sintaxe para Pascal.
void TWRegConfig::ConfigODBC (AnsiString ServerName)
{
AnsiString metrologia ("mt305w");
AnsiString sqlServer ("SQL Server");
AnsiString _OdbcIni = "\\SOFTWARE\\ODBC\\ODBC.INI\\";

TRegistry *_Reg = new TRegistry ();
_Reg->RootKey = HKEY_LOCAL_MACHINE;

_Reg->OpenKey (_OdbcIni + "ODBC Data Sources", true);
/* ... */
No código acima, é criada uma instância da classe TRegistry que encapsula o acesso ao registry do Windows. A raiz para o acesso (RootKey) no exemplo é o HKEY_LOCAL_MACHINE, indicando que acessaremos o local de armazenamento das fonte de dados disponíveis para todos os usuários do computador. Use HKEY_CURRENT_USER como RootKey para acessar apenas as fontes do usuário atual do Windows.

O comando OpenKey abre a chave especificada, preparando-a para manutenções (leitura e gravação). O segundo parâmetro da função OpenKey indica se a chave deve ser criada caso ainda não exista. Agora, podemos criar as entradas que configuram a fonte de dados ODBC:
/* ... */
if ( _Reg->KeyExists(_OdbcIni + metrologia) == false)
{
/* cria o nome da fonte de dados, indicando o tipo de banco de dados que será acessado */
_Reg->WriteString (metrologia, sqlServer);

/* efetivamente faz a configuração da fonte de dados */
_Reg->OpenKey (_OdbcIni + metrologia, true);
_Reg->WriteString ("driver", "C:\\WINDOWS\\System32\\SQLSRV32.dll");
_Reg->WriteString ("Description", metrologia);
_Reg->WriteString ("Server", ServerName);
_Reg->WriteString ("LastUser", metrologia);
}
delete _Reg;
Pelo exemplo acima, nota-se que há duas informações distintas a serem gravadas. A primeira é o nome da fonte de dados, isto é, o nome pelo qual referenciaremos a fonte de dados quando formos conectar via ODBC. Veja que é gravado o nome da fonte (Metrologia) e o tipo de banco de dados que desejamos (Sql Server). Os valores válidos para tipo de banco depende do que você tem instalado no computador. Este valor tem que corresponder a uma das entradas existentes na chave ODBCINST.INI.

A segunda informação é uma chave do Registry que deve ser criada como sub-chave do ODBC.INI com o mesmo nome da fonte de dados - no exemplo, este nome é Metrologia. A configuração propriamente dita é feita criando-se entradas dentro dessa nova sub-chave. Algumas informações são comuns a todos os tipos de banco de dados, como é o caso de driver e Description; outras, são específicas de cada tipo de banco. No exemplo aparecem as entradas necessárias para configurar um banco MS SQL Server.

A informação menos óbvia do exemplo é o driver. Essa entrada deve indicar o caminho da biblioteca do próprio fabricante; biblioteca esta que fará, em última análise, todo o acesso ao banco de dados. O valor correto pode ser facilmente encontrado dentro da chave ODBCINST.INI. Como dentro dela há uma chave para cada driver instalado, basta procurar o nome do driver desejado (SQL Server, por exemplo) e copiar o valor da entrada cujo nome é "Driver".

Uma forma de descobrir quais entradas devem ser criadas é criando uma fonte de dados manualmente através do painel de controle do Windows e depois analisar o resultado na hierarquia do ODBC.INI dentro do registry.

13 de agosto de 2009

Usando arquivos INF para manutenções no Registry

Outro dia eu vi no site da Info Online uma dica interessante ensinando a incluir o desfragmentador de disco no menu de contexto do Windows Explorer. Com isso, basta clicar com o botão direito do mouse numa unidade de disco e a opção para desfragmentá-lo aparecerá no menu suspenso.

A solução mostrada naquele post é bastante simples: um arquivo com extensão INF especifica a criação de entradas no Registry para configurar o menu suspenso. Foi o uso dos arquivos INF que me chamou a atenção. Eles constituem uma forma prática de dar manutenção no Registry, criando ou removendo chaves e valores específicos. Para executá-lo, basta clicar com o botão direito do mouse no arquivo e escolher Instalar no menu suspenso. Também é possível usar a API do Windows para automatizar essa execução.

Qual a diferença entre usar um arquivo INF ou um REG, já que ambos podem dar manutenção no Registry ? Ambos são arquivos texto e podem ser facilmente executados a partir do Windows Explorer mas os INF são mais flexíveis. Eles permitem criar sequências complexas para instalação de softwares. Permitem também remover valores específicos dentro do Registry, enquanto os REG só admitem a eliminação de chaves inteiras. Outras vantagens: os INF têm sintaxe para interagir com o menu de contexto do Explorer, aceitam a inclusão de comandos para desfazer o que quer que tenha sido feito com o INF e é mais fácil de ler pois sua sintaxe é mais simples.

Veja um exemplo simples, a própria instalação do desfragmentador de disco no menu suspenso do Explorer:
[version]
signature="$CHICAGO$"

[DefaultInstall]
AddReg=AddMe

[AddMe]
HKCR,"Drive\Shell\Desfragmentar\command",,,"DEFRAG.EXE %1"

O conteúdo do arquivo INF é organizado em seções, como nos arquivos INI. Cada seção tem uma função específica e contém uma ou mais instruções.

A seção [version] é obrigatória e deve ser a primeira do arquivo para sinalizar que se trata de um arquivo INF. Esta seção deve conter uma linha obrigatória com a chave signature assumindo o valor "$CHICAGO$" se o arquivo tiver comandos compatívels com versões iguais ou superiores ao Windows 95 ou "$Windows NT$" para o caso dos comandos serem específicos de Windows 32 bits, como o NT e as versões mais recentes.

A seção [DefaultInstall] contém as instruções a serem executadas quando o usuário seleciona a opção Install no menu suspenso do Windows Explorer. No exemplo, a chave AddReg instrui a instalação a acrescentar novas chaves e valores no Registry ou modificá-los, caso tais chaves já existam. Para remover uma chave inteira do Registry ou apenas um valor específico, crie na seção [DefaultInstall] uma chave com valor DelReg. Nos dois casos, o valor que vem depois do nome indica uma outra seção (cujo nome é você quem escolhe) onde estão efetivamente uma ou mais entradas a serem acrescidas (ou deletadas) do Registry. No exemplo, o nome escolhido foi AddMe e na seção com esse nome há apenas uma nova entrada para o Registry, que configura a opção de Desfragmentar um drive (unidade de disco). Para especificar uma entrada no Registry, use a sintaxe:
RAIZ,[chave],[valor],[flags],[dados]

onde:
RAIZ é um valor obrigatório que representa uma das chaves de nível mais alto do Registry, podendo assumir uma das seguintes opções: HKCR (para a raiz ser HKEY_CLASSES_ROOT), HKCU (para HKEY_CURRENT_USER), HKLM (para HKEY_LOCAL_MACHINE) ou HKU (para HKEY_USERS). É recomendável ler a documentação dessas chaves e também dos softwares com os quais pretende interagir para saber o quê e onde gravar valores para não desestabilizar o funcionamento do Windows.

chave é um valor opcional contendo o caminho completo da chave a ser criada/alterada dentro da Raiz informada. No exemplo, foi adicionada a chave Drive\Shell\Desfragmentar\command. A barra (\) indica uma subchave, da mesma forma que uma barra no caminho no Windows Explorer indica uma subpasta.

Valor é o nome de um valor a ser criado dentro da chave especificada. O tipo de dado para esse valor é estipulado pelo campo seguinte, flags, cujos valores mais comuns são 0x00000000 (para textos) e 0x00010001 (para números inteiros).

Em Dados você coloca o valor real associado ao nome de Valor estipulado acima. Se esse dado for um texto, escreva-o entre aspas. No caso de se omitir os parâmetros Valor e Flags (como no exemplo), a informação fornecida em Dados será associada como valor padrão (default) da chave.

Este post mostra apenas tarefas simples - apenas criação e remoção de entradas no Registry - mas as possibilidades permitidas pelos arquivos INF vão muito além disso, dispondo de métodos até mesmo para instalações complexas de softwares e drivers. Volto a falar nesse assunto em outro post, mostrando exemplo de como executar tarefas mais complexas.

22 de abril de 2009

Limpeza do Registro do Windows

Instalar novos softwares, atualizar softwares existentes com um nova versão, aplicar patches de atualização do Windows, aplicar security updates de uma série de softwares, etc. É grande a lista das coisas que você faz num computador com Windows que deixa o registry com inconsistências e uma montanha de lixo que só serve para ocupar espaço e deixar mais lenta a máquina.

Estive procurando por um bom programa que ajudasse a manter o registry limpo e há algum tempo venho usando um freeware chamado CCleaner. Ele é capaz de remover as entradas do registry que estão obsoletas, incluindo extensões não usadas de arquivos, controles ActiveX inexistentes, ClassIDs e ProgIDs inválidos, desinstaladores que não existem mais, bibliotecas DLL compatilhadas que não são mais usadas, fontes, arquivos de ajuda, caminhos apontando aplicações que não existem, ícones inválidos de aplicações, atalhos inválidos, etc. É possível selecionar quais dessas buscas serão realizadas e, antes do programa efetivamente remover as entradas, você pode marcar as que quer remover e as que quer manter. Também é dada a oportunidade de se fazer backup - a ser restaurado caso a remoção das entradas cause algum problema.

Na verdade, a função principal do CCleaner é auxiliar na limpeza de disco, removendo caches de softwares (navegadores, java, flash), cookies dos navegadores (há como informar uma lista daqueles que se deseja preservar), arquivos temporários de uma porção de aplicações (incluindo as atualizações do Windows), listas de arquivos abertos recentemente, etc. Há ainda funções avançadas para monitorar e editar a lista de programas que são iniciados junto com o Windows e para incluir pastas de usuário no algorítmo de limpeza – você informa o caminho e quais extensões de arquivo devem ser removidos.

Para quem quer radicalizar, a versão mais recente inclui uma opção que permite apagar também os espaços vazios, isto é, ele não remove só a entrada do aquivo na lista de arquivos do computador mas também os bytes que o compunham, impedindo que se veja rastro dos arquivos.

Mais Informações
Ferramenta CCleaner, registry (registro) do Windows, ambos em inglês.

9 de abril de 2009

Criando um applet para o Painel de Controle do Windows

Há certas ocasiões, quando construímos uma aplicação em qualquer linguagem, em que é interessante disponibilizarmos uma forma do usuário configurar tal aplicação através do método padrão do Windows : acessando um ícone no Painel de Controle.

Um exemplo é quando temos um Serviço no Windows. Como serviços não têm interface com o usuário, a melhor solução é permitir a configuração através do Painel de Controle.

Recentemente, tive que montar um Serviço usando Visual Studio e C#. Serviços no VS2008 são fáceis de montar : há um template. Mas não encontrei nenhum modelo de como montar um applet para o Painel de Controle nessa ferramenta. No C++ Builder da Borland, é criado um projeto de DLL cuja função de entrada (Entry Point) tem a seguinte assinatura :

__stdcall int CPlApplet(unsigned hwndCPl, unsigned uMsg, int lParam1, int lParam2);

E toda a tralha associada ao funcionamento do applet vai ai dentro.

Pesquisando no site da Microsoft sobre como criar isso no Visual Studio, me deparei com uma solução que me pareceu bem mais simples e completa. Mais simples porque envolve criar um executável normal, combinado com a criação de entradas no registry para configurar como o applet deve funcionar. E mais completa porque permite criar configurações mais apropriadas para o Painel de Controle no Windows Vista.

Mãos à obra com um exemplo básico :
1) Crie um executável qualquer com interface gráfica, usando a ferramenta de desenvolvimento que você preferir. No meu exemplo, criei como C++ Builder uma aplicação com o nome CONFIG.EXE

2) Crie um GUID para identificar de forma única a sua aplicação. A Microsoft distribui junto com o Visual Studio uma ferramenta para isso : GUIDGen.exe. Para meu exemplo, usei o seguinte GUID : {5E86074E-1E92-4915-B7F8-4531F8DEAD94}

3) Usando o Regedit :
3.1) Localize a chave HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\ControlPanel\NameSpace e crie embaixo dela uma nova chave com o seu GUID. Coloque como valor padrão o nome de sua aplicação. Pode ser um nome qualquer, como por exemplo: Config.

3.2) Localize a chave HKEY_CLASSES_ROOT\CLSID e crie embaixo dela uma nova chave com o seu GUID. Nessa chave, edite o valor padrão (default) e informe aí o texto que deve aparecer no Painel de Controle. Pode ser o próprio nome da sua aplicação ou algo mais elaborado, se desejar.

3.3) Para fazer as outras configurações do seu applet, crie os seguintes valores embaixo do valor default do passo anterior :

Nome do valor Tipo do Valor
System.ApplicationName String
Um nome para a sua aplicação. A Microsoft chama isso de nome canônico e permite acessar seu applet a partir da linha de comando. Por exemplo, para um nome ABC71.Config, executar na linha de comando :

control.exe /name ABC71.Config

InfoTip Expandable String
Uma descrição para sua aplicação. Ela aparecerá na forma de um "tooltip" quando você estaciona o mouse sobre o ícone de sua aplicação.
System.ControlPanel.Category String
A lista de categorias do Painel de Controle onde sua aplicação deve aparecer. Se seu applet deve aparecer em mais de uma categoria, separe os números com uma vírgula. Alguns exemplos : 1 (aparência e temas), 5 (performance e manutenção), etc. A lista completa pode ser encontrada aqui.


Mais informações sobre esses valores podem ser encontrado aqui.

3.4) Para associar um ícone, certifique-se que sua aplicação possua um ícone embutido nela. Então, crie uma nova chave embaixo do seu GUID em HKEY_CLASSES_ROOT\CLSID com o nome de DefaultIcon. No valor default dessa chave, inclua o caminho completo para a aplicação que contem o ícone que você deseja e, separado por uma vírgula, o índice de um ícone dessa aplicação. Por exemplo, o valor :
c:\appps\config.exe,0
indica que deve ser usada a aplicação config.exe como fonte e que deve ser exibido o primeiro ícone incluido como recurso no executável (como fazer isso pode valer outro post).
3.5) Por fim, devemos informar qual é a aplicação que dever executada quando o usuário der um clique duplo sobre nosso ícone no painel de controle. Para isso, crie uma nova chave, no mesmo nível do DefaultIcon com o nome de Shell. Embaixo dessa chave, crie uma nova chave, Open. E, para encerrar, nova chave de nome Command e com valor default apontando o camimnho completo da aplicação. Exemplo : c:\appps\config.exe.

Pareceu complicado ? Na verdade é mais trabalhoso do que complicado. Uma vez compreendido o processo, fica fácil de automatizar essa criação na instalação da Solução completa ou através de um arquivo de configuração do registro (extensão .Reg).

Até a próxima !