[英]How I can list the contents of a folder of a remote machine
I'm looking for a windows api function or another way to get the content (folder and files) of a folder located in a machine on my LAN.我正在寻找 windows api function 或其他方式来获取位于我 LAN 上的机器中的文件夹的内容(文件夹和文件)。 off course which I have a valid windows user and password for every machine which I want to access.
当然,对于我想要访问的每台机器,我都有一个有效的 windows 用户和密码。
You can use the WMI, check the CIM_DataFile
and CIM_Directory
classes.您可以使用 WMI,检查
CIM_DataFile
和CIM_Directory
类。
1.First you must enable the wmi remote access in the client machines. 1.首先您必须在客户端机器中启用 wmi 远程访问。 Read these articles to see how do this and the differences between windows versions
Connecting to WMI on a Remote Computer
, Securing a Remote WMI Connection
.阅读这些文章,了解如何执行此操作以及 windows 版本之间的差异
Connecting to WMI on a Remote Computer
, Securing a Remote WMI Connection
。
2.Always you must use filters (Where conditions) to restrict the result of these WMI classes. 2.始终必须使用过滤器(Where 条件)来限制这些 WMI 类的结果。
3.Always you must use the Drive
field as condition, because these classes return the files of all drives. 3.始终必须使用
Drive
字段作为条件,因为这些类返回所有驱动器的文件。
4.The Wmi interprets the \
(Backslash) character as a reserverd symbol so you must need to escape that character to avoid problems with the WQL sentence. 4.Wmi 将
\
(反斜杠)字符解释为保留符号,因此您必须对该字符进行转义以避免WQL 语句出现问题。
{$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.
Without the authorization part, it's simple enough.没有授权部分,这很简单。 The right way to do the authorization is to call Windows.pas method
WNetAddConnection2
and go that way.进行授权的正确方法是调用 Windows.pas 方法
WNetAddConnection2
和 go 方法。
However, because I'm in a simple hack mode, I tried this, and it basically works:但是,因为我处于简单的黑客模式,所以我尝试了这个,它基本上可以工作:
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 Apologies for the ugly hack of ShellExecute "net use".为 ShellExecute “网络使用”的丑陋黑客行为道歉。 (Grin) Note that I have elected to "mount" this shared folder without giving it a drive letter, avoiding the problem of what to do if that drive is already mapped.
(Grin) 请注意,我选择“挂载”这个共享文件夹而不给它一个驱动器号,避免了如果该驱动器已经映射了该怎么办的问题。
Here's a good link with a WNetAddConnection2 code sample that I will link to instead of poaching.这是一个很好的链接,其中包含一个 WNetAddConnection2 代码示例,我将链接到该链接而不是偷猎。 It shows a sample of the non-evil way to do it.
它展示了一个非邪恶方法的示例。 :-) Then you can use the Directory enumeration code as I have shown above.
:-) 然后您可以使用上面显示的目录枚举代码。
I suppose this is included in Warren's answer, but to cut to the chase, IOUtils.TDirectory supports UNCs:我想这包含在 Warren 的回答中,但切入正题, 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;
etc, etc...等等等等……
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.