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. off course which I have a valid windows user and password for every machine which I want to access.
-
Take a look here: http://stackoverflow.com/questions/5433570/access-a-remote-directory-from-c. Its in C# though. – Mrchief Jul 20 '11 at 17:55
-
Thanks @Mrchief, but i need to list the content of `any folder` not only the shared. – Salvador Jul 20 '11 at 17:58
-
You can specify: `ResourceDisplayType.Any`. On second thought, `ResourceDisplayType.Share` doesn't mean shared folders (it includes shared folders yes but it simply say don't give my print folders etc.) – Mrchief Jul 20 '11 at 18:04
-
If the folders *truly* haven't been shared, you won't be able to see them. However, unless somebody has taken steps to remove them, there will normally be an administrative share for the root of each drive (at least the hard drives). These are normally named "C$", "D$", and so on. I'd *strongly* advise against depending on their presence though. – Jerry Coffin Jul 20 '11 at 19:26
3 Answers
You can use the WMI , check the CIM_DataFile
and CIM_Directory
classes.
Some Notes
1.First you must enable the wmi remote access in the client machines. 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
.
2.Always you must use filters (Where conditions) to restrict the result of these WMI classes.
3.Always you must use the Drive
field as condition, because these classes return the files of all drives.
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.
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.

- 134,889
- 20
- 356
- 483
-
1+1 Kewl WMI usage! However the need to remotely enable it does cool off the love for the WMI solution a bit. A better solution in a big Corporate Environment where you could push WMI enable out via Group Policy. – Warren P Jul 20 '11 at 20:09
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.
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". (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.
Here's a good link with a WNetAddConnection2 code sample that I will link to instead of poaching. 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.

- 65,725
- 40
- 181
- 316
I suppose this is included in Warren's answer, but to cut to the chase, IOUtils.TDirectory supports UNCs:
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...

- 10,879
- 12
- 61
- 101