UAC – это Контроль Учетных Записей (
Wikipedia), используется для повышения привилегий в том случае если вашему приложению это необходимо. Появился в Windows Vista и присутствует Windows 7, 8, 10. Необходимо убедится в том, что UAC включен. В Windows 7 это можно проверить, открыв «Панель управления» - «Учетные записи пользователей» - «Изменение параметров контроля учетных записей» - убедится, что установлен уровень «По умолчанию» (Смотрите рисунок 1).
Рисунок 1. Включение UAC в Windows 7
Создадим тестовое приложение, которое будет писать в реестр Windows выбираемые из списка значения, правда путь куда мы будем записывать значения требуют повышения привилегий. Откроем Delphi 7 и создадим новый проект. Присвоим ему имя p12.dpr. Сохраним основной модуль под именем p12_unit.pas. Чтобы научить наше приложение работать с UAC, необходимо создать в папке проекта файл манифеста, назовём его Win7UAC.manifest. Содержимое файла следующее:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<assemblyIdentity type="win32" name="App" version="3.1.0.0" processorArchitecture="*"/>
<dependency>
<dependentAssembly>
<assemblyIdentity type="win32" name="Microsoft.Windows.Common-Controls" version="6.0.0.0" publicKeyToken="6595b64144ccf1df" language="*" processorArchitecture="*"/>
</dependentAssembly>
</dependency>
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
<security>
<requestedPrivileges>
<requestedExecutionLevel level="requireAdministrator" uiAccess="false"/>
</requestedPrivileges>
</security>
</trustInfo>
<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
<application>
<!--The ID below indicates application support for Windows Vista -->
<supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}"/>
<!--The ID below indicates application support for Windows 7 -->
<supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}"/>
<!--The ID below indicates application support for Windows 8 -->
<supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}"/>
<!--The ID below indicates application support for Windows 8.1 -->
<supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}"/>
<!--The ID below indicates application support for Windows 10 -->
<supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}"/>
</application>
</compatibility></assembly>
Основным, важным моментом в файле манифеста является строчка кода:
<requestedPrivileges>
<requestedExecutionLevel level="requireAdministrator" uiAccess="false"/>
</requestedPrivileges>
Параметр level со значением requireAdministrator указывает на то, что нашему приложению для работы требуются права администратора. Следующими строчками кода мы указываем с какими операционными системами наше приложение будет совместимо:
<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
<application>
<!--The ID below indicates application support for Windows Vista -->
<supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}"/>
<!--The ID below indicates application support for Windows 7 -->
<supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}"/>
<!--The ID below indicates application support for Windows 8 -->
<supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}"/>
<!--The ID below indicates application support for Windows 8.1 -->
<supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}"/>
<!--The ID below indicates application support for Windows 10 -->
<supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}"/>
</application>
</compatibility>
Далее нам необходимо в каталоге проекта создать файл ресурсов компиляции с именем Win7UAC.rc. Содержимое файла компиляции будет следующее:
1 24 "Win7UAC.manifest"
То есть мы в качестве ресурсов нашего приложения указываем наш файл манифеста.
Файл ресурсов компиляции Win7UAC.rc необходимо скомпилировать при помощи компилятора ресурсов brcc32.exe, этот компилятор ресурсов расположен в каталоге, где расположены бинарные файлы Delphi, у меня это каталог D:\Programs\Delphi7\Files\Delphi7\Bin. Убедитесь, что данный каталог добавлен в переменную окружения Path. Запустите командную строку Windows, перейдите в каталог проекта и выполните команду компиляции ресурсов (Смотрите рисунок 2).
Рисунок 2. Запуск компилятора ресурсов
brcc32.exe Win7UAC.rc
В качестве результата в каталоге проекта вы получите файл ресурсов Win7UAC.RES, который необходимо в файле проекта p12.dpr подключить. Смотрите код ниже:
program p12;
uses
Forms,
p12_unit1 in 'p12_unit1.pas' {Form1};
{$R 'Win7UAC.RES'}
begin
Application.Initialize;
Application.CreateForm(TForm1, Form1);
Application.Run;
end.
Вынесите на форму с именем Form1 одну кнопку Button1 и один список ComboBox1 (Смотрите рисунок 3).
Рисунок 3. Создания формы приложения
Добавьте в свойства Items списка ComboBox1 две строки DOMAIN\User1 и DOMAIN\User2 (Смотрите рисунок 4). Эти строки у нас будут выбираться в ComboBox1. Также поменяйте свойства Style для списка ComboBox1 на csOwnerDraw.
Рисунок 4. Формирование списка ComboBox
Переходим к написанию кода. Рассмотрим обработчик показа формы Form1, это следующий код:
procedure TForm1.FormShow(Sender: TObject);
begin
Combobox1.ItemIndex := Combobox1.Items.IndexOf('DOMAIN\User1');
end;
В данном обработчике мы присваиваем списку ComboBox1 значение по умолчанию значение DOMAIN\User1.
Рассмотрим обработчик нажатия кнопки Button1, это следующий код:
procedure TForm1.Button1Click(Sender: TObject);
var
R: TRegistry;
openResult: Boolean;
const
SubKey : String = 'SOFTWARE\Microsoft\Windows\CurrentVersion\Authentication\LogonUI';
begin
strSetRegValue := ComboBox1.Text;
if (strSetRegValue <> '') then
begin
R := TRegistry.Create(KEY_READ);
R.RootKey := HKEY_LOCAL_MACHINE;
if (R.KeyExists(SubKey)) then
begin
With R do
begin
Access := KEY_WRITE OR $0100;
openResult := OpenKey(SubKey, False);
if (not openResult = True) Then
begin
MessageDlg('Unable to create key! Exiting.', mtError, mbOKCancel, 0);
end;
WriteString('LastLoggedOnSAMUser', strSetRegValue);
WriteString('LastLoggedOnUser', strSetRegValue);
CloseKey();
Free;
end;
end;
ShowMessage('Done! Recorded in the registry.');
strSetRegValue := '';
end;
end;
В данном обработчике мы указываем путь в реестре Windows куда будем писать значения, это переменная типа String c именем SubKey. Смотрите код:
SubKey : String = 'SOFTWARE\Microsoft\Windows\CurrentVersion\Authentication\LogonUI';
Далее берем выбранное значение ComboBox1 и присваиваем его переменной strSetRegValue. Смотрите код:
strSetRegValue := ComboBox1.Text;
Если переменная strSetRegValue не пуста, то начинаем писать в реестр Windows. Работать будем в корневом разделе HKEY_LOCAL_MACHINE. Смотрите код:
if (strSetRegValue <> '') then
begin
R := TRegistry.Create(KEY_READ);
R.RootKey := HKEY_LOCAL_MACHINE;
Далее проверяем существует ли путь в реестре SOFTWARE\Microsoft\Windows\CurrentVersion\Authentication\LogonUI. Также открываем подраздел реестра на запись для Windows 7 32 bit и 64 bit, следующая строчка:
Access := KEY_WRITE OR $0100;
Смотрите следующий код:
if (R.KeyExists(SubKey)) then
begin
With R do
begin
Access := KEY_WRITE OR $0100;
openResult := OpenKey(SubKey, False);
if (not openResult = True) Then
begin
MessageDlg('Unable to create key! Exiting.', mtError, mbOKCancel, 0);
end;
Далее пишем в реестр параметры LastLoggedOnSAMUser, LastLoggedOnUser и закрываем ветку реестра и освобождаем память. Следующие строчки:
WriteString('LastLoggedOnSAMUser', strSetRegValue);
WriteString('LastLoggedOnUser', strSetRegValue);
CloseKey();
Free;
Ниже показан снимок рабочей программы (Смотрите рисунок 5) и код полностью. При запуске приложения, оно спросит повышения привилегий, если вы имеете права админа (Смотрите рисунок 6) или повышения привилегий путем ввода логина и пароля администратора (Смотрите рисунок 7).
Рисунок 5. Запущенная программа
Рисунок 6. Окно разрешения запуска вашей программы, если вы имеете права администратора
Рисунок 7. Запрос прав администратора, если они у вас отсутствуют
unit p12_unit1;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, Registry;
type
TForm1 = class(TForm)
Button1: TButton;
ComboBox1: TComboBox;
procedure Button1Click(Sender: TObject);
procedure FormShow(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
var
strSetRegValue: String;
procedure TForm1.Button1Click(Sender: TObject);
var
R: TRegistry;
openResult: Boolean;
const
SubKey : String = 'SOFTWARE\Microsoft\Windows\CurrentVersion\Authentication\LogonUI';
begin
strSetRegValue := ComboBox1.Text;
if (strSetRegValue <> '') then
begin
R := TRegistry.Create(KEY_READ);
R.RootKey := HKEY_LOCAL_MACHINE;
if (R.KeyExists(SubKey)) then
begin
With R do
begin
Access := KEY_WRITE OR $0100;
openResult := OpenKey(SubKey, False);
if (not openResult = True) Then
begin
MessageDlg('Unable to create key! Exiting.', mtError, mbOKCancel, 0);
end;
WriteString('LastLoggedOnSAMUser', strSetRegValue);
WriteString('LastLoggedOnUser', strSetRegValue);
CloseKey();
Free;
end;
end;
ShowMessage('Done! Recorded in the registry.');
strSetRegValue := '';
end;
end;
procedure TForm1.FormShow(Sender: TObject);
begin
Combobox1.ItemIndex := Combobox1.Items.IndexOf('DOMAIN\User1');
end;
end.