Как я могу перечислить содержимое папки удаленного компьютера - PullRequest
2 голосов
/ 20 июля 2011

Я ищу функцию Windows API или другой способ получить содержимое (папки и файлы) папки, расположенной на машине в моей локальной сети. Конечно, у меня есть действительный пользователь Windows и пароль для каждой машины, к которой я хочу получить доступ.

Ответы [ 3 ]

6 голосов
/ 20 июля 2011

Вы можете использовать WMI, проверить классы CIM_DataFile и CIM_Directory.

Некоторые заметки

1. Сначала необходимо включить удаленный доступ wmi на клиентских машинах.Прочтите эти статьи, чтобы узнать, как это сделать, и различия между версиями Windows Connecting to WMI on a Remote Computer, Securing a Remote WMI Connection.

2. Всегда используйте фильтры (где условия) ограничить результат этих классов WMI.

3. Всегда необходимо использовать поле Drive как условие, поскольку эти классы возвращают файлы всех дисков.

4. Wmi интерпретирует символ \ (обратная косая черта)символ резервирования, поэтому вам нужно экранировать этот символ, чтобы избежать проблем с предложением WQL.

Delphi Code

{$APPTYPE CONSOLE}

uses
  SysUtils,
  ActiveX,
  ComObj,
  Variants;

procedure  GetRemoteFolderContent(Const WbemComputer,WbemUser,WbemPassword,Path:string);
const
  wbemFlagForwardOnly = $00000020;
var
  FSWbemLocator : OLEVariant;
  FWMIService   : OLEVariant;
  FWbemObjectSet: OLEVariant;
  FWbemObject   : OLEVariant;
  oEnum         : IEnumvariant;
  iValue        : LongWord;    
  WmiPath       : string;
  Drive         : string;
begin;
  //The path  
  //Get the drive 
  Drive   :=ExtractFileDrive(Path);
  //get the path and add a backslash to the end
  WmiPath :=IncludeTrailingPathDelimiter(Copy(Path,3,Length(Path)));
  //escape the backslash character
  WmiPath :=StringReplace(WmiPath,'\','\\',[rfReplaceAll]);

  Writeln('Connecting');
  FSWbemLocator := CreateOleObject('WbemScripting.SWbemLocator');
  //Establish the connection
  FWMIService   := FSWbemLocator.ConnectServer(WbemComputer, 'root\CIMV2', WbemUser, WbemPassword);

  Writeln('Files');
  Writeln('-----');
  //Get the files from the specified folder
  FWbemObjectSet:= FWMIService.ExecQuery(Format('SELECT * FROM CIM_DataFile Where Drive="%s" AND Path="%s"',[Drive,WmiPath]),'WQL',wbemFlagForwardOnly);
  oEnum         := IUnknown(FWbemObjectSet._NewEnum) as IEnumVariant;
  while oEnum.Next(1, FWbemObject, iValue) = 0 do
  begin
    Writeln(Format('%s',[FWbemObject.Name]));
    FWbemObject:=Unassigned;
  end;

  Writeln('Folders');
  Writeln('-------');
  //Get the folders from the specified folder
  FWbemObjectSet:= FWMIService.ExecQuery(Format('SELECT * FROM CIM_Directory Where Drive="%s" AND Path="%s"',[Drive,WmiPath]),'WQL',wbemFlagForwardOnly);
  oEnum         := IUnknown(FWbemObjectSet._NewEnum) as IEnumVariant;
  while oEnum.Next(1, FWbemObject, iValue) = 0 do
  begin
    Writeln(Format('%s',[FWbemObject.Name]));
    FWbemObject:=Unassigned;
  end;
end;


begin
 try
    CoInitialize(nil);
    try
      GetRemoteFolderContent('remote_machine','user','password','C:\');
      GetRemoteFolderContent('remote_machine','user','password','C:\Program Files');
    finally
      CoUninitialize;
    end;
 except
    on E:EOleException do
        Writeln(Format('EOleException %s %x', [E.Message,E.ErrorCode]));
    on E:Exception do
        Writeln(E.Classname, ':', E.Message);
 end;
 Writeln('Press Enter to exit');
 Readln;
end.
2 голосов
/ 20 июля 2011

Без авторизации все достаточно просто. Правильный способ авторизации - вызвать метод Windows.pas WNetAddConnection2 и пойти по этому пути.

Однако, поскольку я нахожусь в простом режиме взлома, я попробовал это, и это в основном работает:

uses Types, IOUtils, ShellApi; // Works in Delphi XE.

procedure TForm5.Button1Click(Sender: TObject);
var
 dirs:TStringDynArray;
 files:TStringDynArray;
 apath, dir,filename:String;
begin
 ListBox1.Items.Clear;
 apath := '\\hostname\sharename';

// This should be calling WNetAddConnection2:
// instead It's an evil (portable) hack.
 ShellExecute(HWND(0), 'open', PChar('net use /delete '+  apath), 
    nil,nil,SW_SHOW );
 ShellExecute(HWND(0), 'open', PChar('net use '+ apath+' /user:uid pswd'),
    nil,nil,SW_SHOW );

  dirs := TDirectory.GetDirectories(apath);
  if Length(dirs)=0 then
      ListBox1.Items.Add('None found.')
  else
  for dir in dirs do
      ListBox1.Items.Add('Directory: '+dir);
  files := TDirectory.GetFiles(apath);
  for filename in files do
      ListBox1.Items.Add('File: '+filename );

end;

Abject Извиняюсь за уродливый взлом ShellExecute "net use". (Усмехается) Обратите внимание, что я решил «смонтировать» эту общую папку, не называя ее буквой диска, чтобы избежать проблемы того, что делать, если этот диск уже подключен.

Вот хорошая ссылка с примером кода WNetAddConnection2, на который я буду ссылаться вместо браконьерства. Это показывает образец не злого способа сделать это. :-) Тогда вы можете использовать код перечисления Справочника, как я показал выше.

0 голосов
/ 21 июля 2011

Я полагаю, что это включено в ответ Уоррена, но, чтобы сократить, IOUtils.TDirectory поддерживает UNC:

implementation
uses IOUtils,types;

procedure GetFiles;
var
  i: integer;
  files: TStringDynArray;
begin
  files := TDirectory.GetFiles('\\aServer\aPath\aShare\', '*.aFileFilter');
  for i := Low(files)to High(files) do
       memo1.Lines.Add(files[i]);
end;

и т. Д. И т. Д. *

...