Я разрабатываю проект, который поможет мне управлять моей удаленной сетью, так как мне нужны некоторые конкретные функции, которые я решил закодировать.NetShareEnum правильно отображает доли
Я подключаюсь к удаленным компьютерам, используя WNetAddConnection2, и эта часть работает. Но теперь я пытаюсь перечислить все акции (ADMIN $, C $, IPC $ и любые общие папки), используя функцию NetShareEnum. Я полагался на эту функцию, а не на WNetEnumResource, потому что нашел больше примеров работы с NetShareEnum, и он работает лучше для меня. Проблема в том, что моя реализация NetShareEnum перечисляет только некоторые типы папок (выглядит как только общие папки, но у меня нет доступа). Он не показывает обычные папки (где у меня есть доступ), ADMIN $, C $, IPC $ или что-то еще. Доступны только общие папки, на которые у меня нет прав.
Я все еще не уверен, что поведение на всех серверах одинаково, но те, которые я тестировал, были. До сих пор, что у меня есть:
unit Unit1;
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls;
type
TForm1 = class(TForm)
Memo1: TMemo;
procedure FormCreate(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
HostFile: TStringList;
iHost: integer;
type
SharesThread = class(TThread)
strict private
IPAddress: String;
function Authenticate: bool;
procedure EnumShares(RemoteName: PWChar);
protected
constructor Create(const IPv4: string);
procedure Execute; override;
end;
type
_SHARE_INFO_502 = packed record
shi502_netname: PWideChar;
shi502_type: DWORD;
shi502_remark: PWideChar;
shi502_permissions: DWORD;
shi502_max_uses: DWORD;
shi502_current_uses: DWORD;
shi502_path: LPWSTR;
shi502_passwd: LPWSTR;
shi502_reserved: DWORD;
shi502_security_dsc: PSECURITY_DESCRIPTOR;
end;
SHARE_INFO_502 = _SHARE_INFO_502;
PSHARE_INFO_502 = ^SHARE_INFO_502;
LPSHARE_INFO_502 = PSHARE_INFO_502;
TShareInfo502 = SHARE_INFO_502;
PShareInfo502 = PSHARE_INFO_502;
type
TShareInfo502Array = Array [0..MaxWord] of TShareInfo502;
PShareInfo502Array = ^TShareInfo502Array;
function NetApiBufferFree(buffer: Pointer): DWORD; stdcall; external 'netapi32.dll';
function NetShareEnum(servername: PWideChar;
level: DWORD;
bufptr: PByteArray;
prefmaxlen: DWORD;
entriesread: PDWORD;
totalentries: PDWORD;
resume_handle: PDWORD): DWORD; stdcall; external 'netapi32.dll';
implementation
const
NERR_Success = 0;
MAX_PREFERRED_LENGTH = DWORD(-1);
procedure StartThreads;
var
CurrentIP: string;
begin
if (iHost < HostFile.Count) then
begin
CurrentIP:= HostFile.Strings[iHost];
inc(iHost);
SharesThread.Create(CurrentIP);
end
else
Form1.Memo1.Lines.Add('finished');
end;
constructor SharesThread.Create(const IPv4: string);
begin
inherited Create(false);
FreeOnTerminate:= true;
IPAddress:= IPv4;
end;
function SharesThread.Authenticate;
var
lpNetResource: TNetResource;
myres: cardinal;
begin
with lpNetResource do
begin
dwType := RESOURCETYPE_ANY;
lpLocalName := nil;
lpProvider := nil;
lpRemoteName:= PChar('\\'+IPAddress);
end;
myres := WNetAddConnection2(lpNetResource, PChar('123456'), PChar('BlackNote'), 0);
if (myres = NO_ERROR) then
begin
Result:= true;
EnumShares(lpNetResource.lpRemoteName);
end
else
begin
Result:= false;
end;
end;
procedure SharesThread.EnumShares(RemoteName: PWChar);
var
p: PShareInfo502Array;
res, er, tr, resume, i: DWORD;
begin
repeat
res:=NetShareEnum(RemoteName, 502, @p, MAX_PREFERRED_LENGTH, @er, @tr, @resume);
if (res = ERROR_SUCCESS) or (res = ERROR_MORE_DATA) then
begin
for i:=1 to Pred(er) do
begin
Form1.Memo1.Lines.Add(String(p^[i].shi502_netname));
end;
NetApiBufferFree(p);
end;
until (res <> ERROR_MORE_DATA);
end;
procedure SharesThread.Execute;
begin
if Authenticate then
Form1.Memo1.Lines.Add(IPAddress + '=' + 'Listed shares above')
end;
{$R *.dfm}
procedure TForm1.FormCreate(Sender: TObject);
begin
HostFile:= TStringList.Create;
HostFile.LoadFromFile('Hosts.txt');
iHost:= 0;
StartThreads;
end;
end.
я могу разместить свой IP-адрес, чтобы вам попробовать этот проект, но не уверен, если это в соответствии с правилами. Во всяком случае, что-то не так с этим кодом?
Довольно трудно понять, что происходит не так. Может быть, interop, или может быть, что вы используете API неправильно. Если бы я был вами, я бы убрал interop из уравнения и сделаю начальную разработку на C++, используя заголовочные файлы Windows. Таким образом, вы знали бы, что вмешательство не было проблемой. Например, я не знаю, почему вы решили, что запись должна быть упакована. Может ли это быть проблема? Может быть. Возможно, нет. Удалите эти потенциальные точки отказа из уравнения. –
Взаимодействие Я думаю, что вызов функции из внешней DLL в Delphi? Я так думаю ... Проблема в том, что я знаю 0 C++ ... Я думаю, чтобы удалить этот потенциальный сбой, я мог бы использовать WNetEnumResource, но пока этого не добился. – LessStress
'for i: = 1 to Pred (er) do' - почему вы пропускаете первый элемент, который равен # 0? –