Один программист другому:
- Представляешь, в Windows-2000 более четырех тысяч известных ошибок, а в моей программе только одна!
- Вот здорово! А какая?
- Не запускается.
unit Reg;
{$R-,T-,H+,X+}interfaceuses Registry, Classes, Windows, Consts, SysUtils;
type
TReg = class(TRegistry)
publicprocedure ReadStringList(const name: string; list: TStringList);
procedure WriteStringList(const name: string; list: TStringList);
end;
implementation//*** TReg *********************************************************************//------------------------------------------------------------------------------// Запись TStringList ввиде значения типа REG_MULTI_SZ в реестр//------------------------------------------------------------------------------procedure TReg.WriteStringList(const name: string; list: TStringList);
var
Buffer: Pointer;
BufSize: DWORD;
i, j, k: Integer;
s: string;
p: PChar;
begin{подготовим буфер к записи}
BufSize := 0;
for i := 0 to list.Count - 1 do
inc(BufSize, Length(list[i]) + 1);
inc(BufSize);
GetMem(Buffer, BufSize);
k := 0;
p := Buffer;
for i := 0 to list.Count - 1 dobegin
s := list[i];
for j := 0 to Length(s) - 1 dobegin
p[k] := s[j + 1];
inc(k);
end;
p[k] := chr(0);
inc(k);
end;
p[k] := chr(0);
{запись в реестр}if RegSetValueEx(CurrentKey, PChar(name), 0, REG_MULTI_SZ, Buffer,
BufSize) <> ERROR_SUCCESS thenraise ERegistryException.CreateResFmt(@SRegSetDataFailed, [name]);
end;
//------------------------------------------------------------------------------// Чтение TStringList ввиде значения типа REG_MULTI_SZ из реестра//------------------------------------------------------------------------------procedure TReg.ReadStringList(const name: string; list: TStringList);
var
BufSize,
DataType: DWORD;
Len, i: Integer;
Buffer: PChar;
s: string;
beginif list = nilthen
Exit;
{чтение из реестра}
Len := GetDataSize(Name);
if Len < 1 then
Exit;
Buffer := AllocMem(Len);
if Buffer = nilthen
Exit;
try
DataType := REG_NONE;
BufSize := Len;
if RegQueryValueEx(CurrentKey, PChar(name), nil, @DataType, PByte(Buffer),
@BufSize) <> ERROR_SUCCESS thenraise ERegistryException.CreateResFmt(@SRegGetDataFailed, [name]);
if DataType <> REG_MULTI_SZ thenraise ERegistryException.CreateResFmt(@SInvalidRegType, [name]);
{запись в TStringList}
list.Clear;
s := '';
for i := 0 to BufSize - 2 dobegin// BufSize-2 т.к. последние два нулевых символаif Buffer[i] = chr(0) thenbegin
list.Add(s);
s := '';
endelse
s := s + Buffer[i];
end;
finally
FreeMem(Buffer);
end;
end;
end.
Регулярный класс TReg - это наследник класса TRegistry, предназначенный для работы с значениями типа REG_MULTI_SZ в Windows NT и Windows 2000.
Класс TReg добавляет два метода: ReadStringList и WriteStringList, которые позволяют читать и записывать значения типа REG_MULTI_SZ.
Методы:
WriteStringList: Этот метод пишет список строк в реестр как значение типа REG_MULTI_SZ.
Метод сначала рассчитывает размер буфера, необходимого для хранения всех строковых значений.
Затем он выделяет память для буфера и проходит по списку TStringList, чтобы заполнить буфер каждой строкой, за которой следует нулевая терминация (chr(0)).
Наконец, метод пишет буфер в реестр с помощью RegSetValueEx.
ReadStringList: Этот метод читает значение типа REG_MULTI_SZ из реестра и пополняет TStringList каждой строкой.
Метод сначала проверяет, не является ли входной TStringList null, а затем получает размер буфера для указанного пары ключ-значение с помощью GetDataSize.
Он выделяет память для буфера и читает значение из реестра с помощью RegQueryValueEx. Если операция fails или тип данных не REG_MULTI_SZ, возникает исключение.
Метод затем проходит по буферу, извлекая каждую строку, найдя нулевую терминацию (chr(0)), и добавляет ее в входной TStringList.
Альтернативное решение:
Хотя это код функционирует, есть несколько предложений для улучшения:
Обработка ошибок: вместо бросания исключений на ошибку,consider возвращать код ошибки или булевое значение, указывающее, была ли операция успешной.
Управление памятью: метод WriteStringList выделяет память с помощью GetMem, который должен быть заменен AllocateMemory из unit Windows для лучшей совместимости.
Расчет размера буфера: размер буфера рассчитывается путем суммирования длин каждой строки, плюс один для нулевой терминации. Consider использовать более эффективный алгоритм, например, рассчитывая общую длину всех строк и добавляя небольшой буферный запас.
Организация кода: разбейте код на отдельные процедуры или методы для чтения и записи значений, чтобы улучшить поддержку и повторяемость.
В целом, этоsolid реализация, которая предоставляет полезную функциональность для работы с значениями REG_MULTI_SZ в Windows NT и Windows 2000.
Дополненный класс TRegistry, позволяющий работать с значениями типа REG_MULTI_SZ в Windows NT и Windows 2000.
Комментарии и вопросы
Получайте свежие новости и обновления по Object Pascal, Delphi и Lazarus прямо в свой смартфон. Подпишитесь на наш Telegram-канал delphi_kansoftware и будьте в курсе последних тенденций в разработке под Linux, Windows, Android и iOS
Материалы статей собраны из открытых источников, владелец сайта не претендует на авторство. Там где авторство установить не удалось, материал подаётся без имени автора. В случае если Вы считаете, что Ваши права нарушены, пожалуйста, свяжитесь с владельцем сайта.