Вопрос, представленный в данном запросе, связан с необходимостью перечисления всех компьютеров, подключенных к локальной сети, через работу с группой в Windows. Пользователь столкнулся с проблемой, что функция, предназначенная для возврата списка всех компьютеров в указанной рабочей группе, возвращает только имя собственного компьютера, несмотря на то, что другие компьютеры подключены к той же группе и отображаются в сетевом списке Windows Explorer.
Описание предоставленного кода
В приведенном коде используется функция FindAllComputers, которая принимает параметры Workgroup и WithIP. Функция создаёт список сетевых ресурсов, используя функцию WNetEnumResource из WinAPI. В цикле происходит перечисление ресурсов, и имена компьютеров добавляются в список Computers. Если установлен флаг WithIP, для каждого имени компьютера дополнительно возвращается его IP-адрес.
Проблема с условием цикла
Проблема в данном коде заключается в условии цикла, где перечисление ресурсов завершается, если Entries > 0. Это условие некорректно, так как переменная Entries на входе в функцию WNetEnumResource устанавливается в 1, и после перечисления одного ресурса она возвращается равной 1, что приводит к бесконечному циклу, поскольку условие Entries > 0 всегда истинно.
Подтвержденный ответ
В соответствии с документацией по функции WNetEnumResource, параметр lpcCount (в коде обозначается как Entries) на входе в функцию устанавливается в ожидаемое количество перечисляемых элементов, а на выходе получает фактическое количество перечисленных элементов. Следовательно, условие (Entries > 0) должно быть исключено из цикла, так как оно некорректно отражает логику работы функции. Вместо этого, следует использовать условие, которое проверяет успешность выполнения перечисления и ограничение по количеству попыток, например:
until (Res = NO_ERROR) and (Limit > 100);
Также стоит отметить, что в коде присутствует лишний вызов StrPas, который можно исключить, так как lpRemoteName уже возвращает строку в нужной кодировке.
Оптимизация кода
Для устранения проблемы, необходимо изменить условие цикла на следующее:
until (Res <> ERROR_NO_MORE_ITEMS) and (Limit > 100);
где ERROR_NO_MORE_ITEMS — это код ошибки, который указывает на то, что перечисление ресурсов завершено. Также, для избежания бесконечного цикла, рекомендуется ограничение по количеству попыток (Limit).
Пример исправленного кода
Вот исправленный и оптимизированный вариант функции FindAllComputers:
function FindAllComputers(Workgroup: string; WithIP: Boolean): TStringList;
var
EnumHandle: THandle;
WorkgroupRS: TNetResource;
Buf: array[1..500] of TNetResource;
BufSize: cardinal;
Entries: cardinal;
Res: Integer;
Computers: TStringList;
Limit, I: Integer;
begin
Limit := 0;
Workgroup := Workgroup + #0;
FillChar(WorkgroupRS, SizeOf(WorkgroupRS), 0);
with WorkgroupRS do
begin
dwScope := RESOURCE_GLOBALNET;
dwType := RESOURCETYPE_ANY;
dwDisplayType := DTYPE_SERVICE_COMPUTER;
lpRemoteName := PChar(Workgroup);
end;
WNetOpenEnum(RESOURCE_GLOBALNET, RESOURCETYPE_ANY, 0, @WorkgroupRS, EnumHandle);
Computers := TStringList.Create;
repeat
Entries := 1;
BufSize := SizeOf(Buf);
Res := WNetEnumResource(EnumHandle, @Entries, @Buf, BufSize);
if (Res = NO_ERROR) and (Entries > 0) then
begin
Computers.Add(Buf[1].lpRemoteName);
end;
Inc(Limit);
until (Res = ERROR_NO_MORE_ITEMS) or (Limit > 100);
WNetCloseEnum(EnumHandle);
if WithIP then
begin
for I := 0 to Computers.Count - 1 do
Computers[I] := Computers[I] + '=' + GetIP(Computers[I]);
end;
Result := Computers;
end;
Заключение
Исправление в коде позволяет корректно перечислять сетевые компьютеры в рабочей группе Windows. Важно помнить, что при работе с сетевыми функциями Windows необходимо внимательно изучать документацию и тестировать код в различных условиях сети.
Вопрос касается решения проблемы в коде на Delphi, где используя WinAPI пытаются перечислить сетевые компьютеры, но функция возвращает только имя собственного компьютера из-за ошибки в условии цикла.
Комментарии и вопросы
Получайте свежие новости и обновления по Object Pascal, Delphi и Lazarus прямо в свой смартфон. Подпишитесь на наш Telegram-канал delphi_kansoftware и будьте в курсе последних тенденций в разработке под Linux, Windows, Android и iOS
Материалы статей собраны из открытых источников, владелец сайта не претендует на авторство. Там где авторство установить не удалось, материал подаётся без имени автора. В случае если Вы считаете, что Ваши права нарушены, пожалуйста, свяжитесь с владельцем сайта.