terça-feira, 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.

7 comentários:

  1. Segui exatamente a recomendação e não houve mudanças na execução de quais projetos, sejam, em andamento ou somente de teste.

    Não sei se tem a ver, mas o delphi eu abro sempre como administrador.

    Após efetuar as manipulações acima e executar o compile, ela não muda para aquele ícone diferenciado.

    Estou utilizando Delphi Xe2 no Windows 7 x64.

    Você testou esse método?

    ResponderExcluir
    Respostas
    1. Thiago

      O exemplo que aparece no post é extraído de um programa real que utilizamos na ABC71 e que está funcionando como esperado. Ele foi feito em XE2 mas ainda é Win32.

      Pelo seu comentário, vc está executando o programa a partir do ambiente do Delphi. Não me lembro com certeza mas acho que, por questões de depuração, o Delphi já passa as credenciais corretas para o programa executar.

      O ícone diferenciado não aparece quando vc olha pelo Windows Explorer o executável gerado ? Executando por fora do Delphi com um usuário comum as credenciais não são solicitadas ? Pode ser que o manifesto não tenha sido linkado corretamente. Vc pode verificar se o seu manifesto foi linkado ao executável fazendo a extração dos recursos embutidos nele com programas como o ResourcesExtract.

      []s

      Excluir
    2. Luís, obrigado pela disponibilidade na resposta.
      Eu realmente achei estranho o ocorrido, visto que além da sua técnica exposta, também verifiquei outras, mas aparentemente, no ambiente em que simulei e nos de testes, não tive muito sucesso.

      Mediante ao fato, começei a alguns questionamentos em questões de Update e afins. Analisei e tomei a decisão de na instalação da minha app já se faz a indentificação de escrita na pasta referida, mesmo ela estando em ProgramFiles. Assim sendo, não terei maiores problemas futuros relacionados a atualização de arquivos, scripts e afins.

      Desde já agradeço a sua atenção.

      Excluir
  2. Posso usar essa API em meu sistema deskTop e comercializa-lo sem pagar nada? É free.?

    ResponderExcluir
    Respostas
    1. Ribamar

      Esses recursos são parte integrante do Windows. Uma vez que uma versão do sistema opreacional foi adquirida, não é preciso pagar para usar a API em seu programa.

      []s

      Excluir
  3. Respostas
    1. Elizangelo

      O que não funcionou? Quais os sintomas?

      []s

      Excluir

OBS: Os comentários enviados a este Blog são submetidos a moderação. Por isso, eles serão publicados somente após aprovação.