Results 1 to 4 of 4

Thread: [VB6] List files by level from a folder, in natural sorted order using INamespaceWalk

  1. #1

    Thread Starter
    PowerPoster
    Join Date
    Jul 2010
    Location
    NYC
    Posts
    7,654

    [VB6] List files by level from a folder, in natural sorted order using INamespaceWalk

    cNamespaceWalk


    I initially brought this interface to VB6 to spite the people asking how to list files in sorted order, without actually having to sort them as they're added (the spite is that the complexity of using a shell interface from a tlb is higher than simply using Dir() and inserting already sorted). Then I almost didn't release this because while the interface is very simple, there's a large amount of support code. But here it is, using INamespaceWalk in VB6.

    The interface is available on XP.

    Performance Note
    While it's tough to do an exact comparison, for the task of listing files names with a PathMatchSpec call, but without recreating the details of a findfile structure, INamespaceWalk is indeed faster than FindFirstFile/FindNextFile. Walking a folder with 1187 items and processing them into a listview took an average of 14.48s with INamespaceWalk, and 29.16s with FindFirstFile/FindNextFile. The only difference was how the file name was passed to a FileFound handler. INamespaceWalk doesn't natively return the details like size and dates, but does require converting an ishellfolder and relative pidl to a regular file name... so my gut says faster at the core.
    Project Update
    In the original project, the walk could only be cancelled via the progress dialog. The only way besides this to cancel is by returning ERROR_CANCELLED in the EnterFolder event, which VB doesn't allow by default. I've attached another version of the sample project that uses SwapVTable to replace the normal EnterFolder with one that supports returning values. So every time a new folder is entered, you can continue (S_OK), skip that folder (S_FALSE), or stop all together (ERROR_CANCELLED).

    What is INamespaceWalk?

    INamespaceWalk provides an alternative way to list the files in a given directory. Unlike other methods, unless a no sort flag is specified, results are returned already in the natural sort order that they would appear in Explorer. There's also options for what to do with links. It's faster than FSO, but I'm not sure how it compares to a full API FindFirstFile/FindNextFile search. While it's not in the sample project, turning this into a search is as simple as checking the filename returned in the FoundItem event.

    The most unique feature is that it provides a modern styled progress dialog just by specifying a flag.

    The attached sample project contains a class module that wraps all the details up, making usage very simple:
    Code:
    With cNSW
        .Flags = NSWF_DONT_RESOLVE_LINKS Or NSWF_DONT_TRAVERSE_LINKS Or NSWF_SHOW_PROGRESS
        .Levels = CLng(Text2.Text)
        .ReturnInfo = True
        .Root = Text1.Text
        .Walk
    End With
    Requirements
    Requires my Modern Shell Interfaces Type Library, v4.0 or higher.

    NEW UPDATE: 28 July 2016
    So normally when I want to implement an interface that inherits from another, I just merge the two and include all the methods of the first and the second, and inherit from IUnknown, which VB requires. But INamespaceWalk is unique; its .Walk function takes a callback for INamespaceWalkCB *only*. It doesn't work at all if you try to pass it anything else, either INamespaceWalkCB2 directly or as an IUnknown.
    This led to much frustration as I tried a bunch of things that work for other similar situations. But today I revisited the issue and finally found what worked: The callback class must implement BOTH INamespaceWalkCB and INamespaceWalkCB2, *with* all methods from the first duplicated in CB2. But the CB2 functions can be left blank and are never called; only the method unique to CB2 is called, so a pure callback class looks like this:
    Code:
    Implements INamespaceWalkCB
    Implements INamespaceWalkCB2
    
    Private Sub INamespaceWalkCB_FoundItem(ByVal psf As IShellFolder, ByVal pidl As Long)
    'Live code
    End Sub
    Private Sub INamespaceWalkCB_EnterFolder(ByVal psf As IShellFolder, ByVal pidl As Long)
    'Live code
    End Sub
    Private Sub INamespaceWalkCB_LeaveFolder(ByVal psf As IShellFolder, ByVal pidl As Long)
    'Live code
    End Sub
    Private Sub INamespaceWalkCB_InitializeProgressDialog(ppszTitle As Long, ppszCancel As Long)
    'Live code
    End Sub
    
    
    Public Sub INamespaceWalkCB2_FoundItem(ByVal psf As IShellFolder, ByVal pidl As Long)
    '(this sub is never called)
    End Sub
    Public Sub INamespaceWalkCB2_EnterFolder(ByVal psf As IShellFolder, ByVal pidl As Long)
    '(this sub is never called)
    End Sub
    Public Sub INamespaceWalkCB2_LeaveFolder(ByVal psf As IShellFolder, ByVal pidl As Long)
    '(this sub is never called)
    End Sub
    Public Sub INamespaceWalkCB2_InitializeProgressDialog(ppszTitle As Long, ppszCancel As Long)
    '(this sub is never called)
    End Sub
    
    Private Sub INamespaceWalkCB2_WalkComplete(ByVal hr As Long)
    Debug.Print "WalkComplete, hr=" & hr
    End Sub
    Then the .Walk call, which is still hard typed to INamespaceWalkCB, takes this class.

    The class and sample project have been updated to fully implement the WalkComplete event now.

    Also this update has had the references updated to reference oleexp.tlb v4.0 or higher instead of oleexp3.tlb; the INamespaceWalk interface also now receives the class ByRef instead of by Long with ObjPtr.


    -------

    twinBASIC 64bit compatible version at https://github.com/fafalone/MiscDemos
    Attached Files Attached Files
    Last edited by fafalone; Nov 15th, 2025 at 03:41 AM. Reason: You can use oleexp on Windows XP.

  2. #2

    Thread Starter
    PowerPoster
    Join Date
    Jul 2010
    Location
    NYC
    Posts
    7,654

    Re: [VB6] List files by level from a folder, in natural sorted order using INamespace

    Updated to show how to skip folders or stop all together by using SwapVTable to use an EnterFolder that's a function instead of a sub.

  3. #3

    Thread Starter
    PowerPoster
    Join Date
    Jul 2010
    Location
    NYC
    Posts
    7,654

    Re: [VB6] List files by level from a folder, in natural sorted order using INamespace

    Project Updated

    So I finally figured out how to get INamespaceWalkCB2 working so the WalkComplete notice can be received. In all other circumstances, CB2 would just implement the methods of CB1 and be passed instead. But here, CB2 must implement all of the methods of CB1 as duplicates, and the CB1 implementation must also be included (and its events are the ones that fire; only the WalkComplete of CB2 is ever entered). More details in main post; just wanted to bump because of this unique oddity of implementing an interface derived from something besides IUnknown or IDispatch, which VB doesn't allow with Implements.
    (update also changes references from oleexp/olelib to oleexp3)

  4. #4
    PowerPoster
    Join Date
    Jun 2015
    Posts
    2,229

    Re: [VB6] List files by level from a folder, in natural sorted order using INamespace

    This is actually the standard VB Way of supporting multiple interfaces.

    Usually you code a single routine, and then call them from the interface stubs.

    They improved on this redundancy in DOT NET though.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width