Discussion:
vbscript: how to generate a FolderItem2 object from a filename ?
(too old to reply)
R.Wieser
2024-06-22 10:14:11 UTC
Permalink
Hello all,

I found a smal script which uses the "GetDetailsOf" method of a "Folder3"
object to extract some properties of a file.

The thing is that the "GetDetailsOf" method expects a "FolderItem2" object
as its first argument.

And although the "Folder3" object allows iterating thru its children by
which it returns an "FolderItem2" object for each of its entries (files,
subfolders), I would like to inspect just a single file.

So, I need a method to convert a (full) filename into a "FolderItem2" object
(withor-without the aid of a "Folder3" object, which "GetDetailsOf" needs
anyway).

Does what I'm looking for even exists ? And if so, what does it look like ?

reference script:
- - - - - - - - - - - - - - - - - -
Set objDlg = WScript.CreateObject("Shell.Application")

'-- returns a Folder3 object
Set oNSFolder = objDlg.NameSpace(folderName)

'-- returns FolderItem2 objects
For Each oNSFile In oNSFolder.items

'-- the "Artist" property value
sProperty = oNSFolder.GetDetailsOf(oNSFile, 16)

...
next
- - - - - - - - - - - - - - - - - -

Regards,
Rudy Wieser
Newyana2
2024-06-22 12:11:15 UTC
Permalink
Post by R.Wieser
Set objDlg = WScript.CreateObject("Shell.Application")
'-- returns a Folder3 object
Set oNSFolder = objDlg.NameSpace(folderName)
'-- returns FolderItem2 objects
For Each oNSFile In oNSFolder.items
'-- the "Artist" property value
sProperty = oNSFolder.GetDetailsOf(oNSFile, 16)
I'm not aware of any direct access to these compound objects.
VBS is only referencing a Folder object. In VB with early binding
it's the same. There's no sorting through versions. The following seems
to do what you want. I set it to return date rather than artist. I'm
not sure if I have a file with the artist property filled in.

Note that Namespace is available on XP, but the Self property
of a folder object is not available until IE6. That can lead to some
fairly complicated code in some cases.

Dim ObjDlg, oNSFolder, oNSFile, sProperty
Set ObjDlg = WScript.CreateObject("Shell.Application")

'-- returns a Folder3 object
Set oNSFolder = ObjDlg.NameSpace("C:\windows\desktop\fol1")
MsgBox Typename(oNSFolder)

'-- returns FolderItem2 objects.. do we care? It works.
For Each oNSFile In oNSFolder.items
If oNSFile.Name = "river.png" Then
sProperty = oNSFolder.GetDetailsOf(oNSFile, 3) 'date
MsgBox Typename(oNSFile) & vbCrLf & oNSFile.Name & vbCrLf & sProperty
End If
Next
Set oNSFolder = Nothing
Set ObjDlg = Nothing
R.Wieser
2024-06-22 12:42:07 UTC
Permalink
Newyana2,
Post by Newyana2
'-- returns FolderItem2 objects.. do we care? It works.
For Each oNSFile In oNSFolder.items
If oNSFile.Name = "river.png" Then
Yes, that was my first idea too.

But just imagine doing that on a folder with *lots* of files, or better yet
: on a remote computer (with a slow connection) ...

Regards,
Rudy Wieser
Newyana2
2024-06-22 15:40:21 UTC
Permalink
Post by R.Wieser
But just imagine doing that on a folder with *lots* of files, or better yet
: on a remote computer (with a slow connection) ...
I don't see a problem. I just ran it on a folder full of
XP SP2 files. About 480 files. It returned instantly. I also
added Exit For if the file was found. If you run it remotely it's
not going to call back with every loop, so there's no slowdown.

I don't see how you're going to make it simpler. A FolderItem
is part of a collection of what's in a folder. There's no method
like GetFolderItem(path).

A warning, though: Shell.app is connected with Explorer. It's
extremely buggy. On some Windows versions it won't see hidden
files or system files. I just tested the script on System32 and
it didn't work. Apparently Win10 won't let shell.app look in
system32!

The only other thing I can think of that might be cleaner would
be to use a basic file system methods, then maybe read the data out
by direct binary access. Then again, if you want fast then you're
not using VBScript. :) But a more direct method would at least avoid
the funky failures of shell.app. Even FSO works fine in System32
on Win10. I can access a file and check file object properties. But
then you'd need ffmpeg or a binary read or some such to get EXIF
data.
R.Wieser
2024-06-22 18:29:43 UTC
Permalink
Newyana2,
Post by Newyana2
Post by R.Wieser
But just imagine doing that on a folder with *lots* of files, or better
yet : on a remote computer (with a slow connection) ...
I don't see a problem.
I see several. The above one as the most relatable.
Post by Newyana2
I just ran it on a folder full of XP SP2 files. About 480 files.
I agree that if you take just a few files and doing a single retrieval you
won't notice the delay. IOW, "works well enough for home use".

Have you ever done any SQL ? The guys monitoring performance will not like
it when you ask the database for every record, and than just iterate thru
results yourself to find the single record you're interrested in. To me
this is the same.

And In that regard I've always wondered why the filesystem object doesn't
allow filename filtering (using wildcards). Sometimes I only need to see
files with a specific extension, but I have to do that filtering myself. On
my local machine. Without any kind of wildcard comparision. With the
filenames possibly coming from a (slow) remote computer. It just kills me
to see that kind of waste. :-(
Post by Newyana2
I don't see how you're going to make it simpler. A FolderItem
is part of a collection of what's in a folder.
The funny thing that you can do this :

set objFSO = CreateObject("Scripting.FileSystemObject")
set oFile = objFSO.GetFile(strFile)

It just happens to return the wrong type of file-object.
Post by Newyana2
There's no method like GetFolderItem(path).
As I could not find such a method myself that (its absense) is all I wanted
to verify.
Post by Newyana2
A warning, though: Shell.app is connected with Explorer. It's extremely
buggy. On some Windows versions it won't see hidden files or system files.
Thanks for the warning. I might just write my own ActiveX object for the
purpose (was already doing that, but came across some VBScript code and just
had to check it out - and noticed it doesn't return the "keywords" field in
image files. :-().
Post by Newyana2
I just tested the script on System32 and it didn't work. Apparently Win10
won't let shell.app look in system32!
I seem to remember that Win10 has a number of virtual folders (more than XP
or Win7 I mean). Could that be the cause ?
Post by Newyana2
The only other thing I can think of that might be cleaner would
be to use a basic file system methods, then maybe read the data out
by direct binary access.
Yep, that was what I was thinking of. I already did something like it
years ago, but never as an ActiveX component. *And*, I could than add
stuff to write properties too.
Post by Newyana2
Then again, if you want fast then you're not using VBScript. :)
:-p Thats no reason to make it even slower.
Post by Newyana2
Even FSO works fine in System32 on Win10. I can access a file and check
file object properties.
It works as dependable on XP. At least, I've never had any problems with
it, and I've used it quite a bit.
Post by Newyana2
But then you'd need ffmpeg or a binary read or some such to get EXIF data.
... or I read the file as an VT_UI1 array and write a number of methods to
extract different sizes of data from it. Bytes, words, quadbytes, byte and
wide strings, etc.

You want slow ? We can make it slow ! :-)

(I might just do that to see if it works and how slow it gets - and than
never look at it again)

Regards,
Rudy Wieser
JJ
2024-06-22 17:52:57 UTC
Permalink
Post by R.Wieser
Hello all,
I found a smal script which uses the "GetDetailsOf" method of a "Folder3"
object to extract some properties of a file.
The thing is that the "GetDetailsOf" method expects a "FolderItem2" object
as its first argument.
And although the "Folder3" object allows iterating thru its children by
which it returns an "FolderItem2" object for each of its entries (files,
subfolders), I would like to inspect just a single file.
"GetDetailsOf" is a method of "Folder". It's inherited to "Folder2" and
"Folder3". "Folder" is a base class of "Folder2", and "Folder2" is a base
class of "Folder3". So both "Folder3" is also "Folder2", and "Folder2" is
also "Folder".

"Folder"'s "GetDetailsOf" accepts "FolderItem". Not just "FolderItem2".
Post by R.Wieser
So, I need a method to convert a (full) filename into a "FolderItem2" object
(withor-without the aid of a "Folder3" object, which "GetDetailsOf" needs
anyway).
Does what I'm looking for even exists ? And if so, what does it look like ?
Use "ParseName" method of the "Computer" folder. The folder which shows all
of the drives. e.g.

fullfilepath = "d:\dir\subdir\file.ext"
Set objDlg = WScript.CreateObject("Shell.Application")
Set oCompFolder = objDlg.NameSpace(17)
set oFile = oCompFolder.ParseName(fullfilepath)
set oFolder = oFile.GetFolder
sProperty = oNSFolder.GetDetailsOf(oFile, 16)

Not mentioned by MSDN:
Unless done from the "Computer" or "Network" folders, "ParseName" can only
accept file/folder name without any path (i.e. just the name and extension -
as seen in Explorer).
R.Wieser
2024-06-22 18:47:13 UTC
Permalink
JJ,
Post by JJ
"Folder"'s "GetDetailsOf" accepts "FolderItem". Not just "FolderItem2".
Good to know. Alas, I have no idea how to create a "FolderItem" object from
a full path either (actually, even less than a FolderItem2). -|
Post by JJ
Use "ParseName" method of the "Computer" folder. The folder which shows
all of the drives. e.g.
[snip code]

Alas, the line
Post by JJ
set oFolder = oFile.GetFolder
returns a "(null): The system cannot find the file specified." error.

... which just might be a difference between Win7 and XP, the latter of
which I'm using.

I did check if the oFile object retuned sane data and both the "file" as
well as the "path" methods (properties?) returned th expected strings.

Thanks for the code though. Its something of which you just know that all
of that works together that way. No, really ! :-) <whistle>

Regards,
Rudy Wieser
JJ
2024-06-23 08:53:50 UTC
Permalink
Post by R.Wieser
Alas, the line
Post by JJ
set oFolder = oFile.GetFolder
returns a "(null): The system cannot find the file specified." error.
Whoops. That should be:

set oFolder = oFile.Parent
R.Wieser
2024-06-23 09:50:05 UTC
Permalink
JJ,
Post by JJ
set oFolder = oFile.Parent
Yep, that makes the whole thing work. Thank you.

Now to make sure I never lose that script, as I won't be able to re-create
it. :-|

Regards,
Rudy Wieser

Loading...