ReadDir() and "Access denied"

Yesterday I posted a script command in the scripts section of the forum: Command: RenameFolderAddCount
It uses ReadDir() to recursively step through subfolders and works as expected so far, but..

If I use ReadDir() recursively (by scripting) more than once in non-recurse mode, a final "RENAME FROM.. TO.." on a top-level folder results in an "Access denied" message:


This does not happen if I use ReadDir() and it's builtin recurse option and also not if ReadDir() is called on that folder only once (in non-recurse mode).
So it's my own recursion implementation that leads to that problem it seems, but actually I don't see why that should happen, it does not stall or run endless, it exactly yields the results I am after.

I tried to resolve things by nulling all enumerators in use and calling the RENAME out of the loop of while(!enumerator.complete){...} etc., but it does not help.
Now that ReadDir() has that builtin recurse mode, I wonder if this is for convinience only or if it intentionally exists to get around things I encounter? I doubt that though! o)

Maybe anybody has a clue why that happens? The problem can be seen when calling "RenameFolderAddCount deepness=9999" to activate my own recursion.
Thx! o)

I put some smallish demo-code together to make things easier for you and me, find it attached and in the code-box.
The script adds a command "ReadDirAndRename", which gives "Access Denied" whenever used with a folder that contains subfolders (so ReadDir() was called more than once).

/////////////////////////////////////////////////////////////////////////////// function OnInit(data){ data.name = "Command.Folder: ReadDirAndRename"; data.default_enable = true; var cmd = data.AddCommand(); cmd.name = "ReadDirAndRename"; cmd.method = "Command_ReadDirAndRename"; cmd.label = "ReadDirAndRename"; } /////////////////////////////////////////////////////////////////////////////// function Command_ReadDirAndRename(data) { var foldersEnum = new Enumerator(data.func.sourcetab.selected_dirs); while (!foldersEnum.atEnd()) { var folder = foldersEnum.item(); foldersEnum.moveNext(); Crawl(folder.realpath); var cmd = 'RENAME PATTERN=* FROM="'+folder.realpath+'" TO="* (x)"'; data.func.command.RunCommand(cmd); } } ////////////////////////////////////////////////////////////////////////////// function Crawl(path){ DOpus.Output("Crawling ["+path+"].."); var folderEnum = DOpus.FSUtil.ReadDir( path, false); while(!folderEnum.Complete){ var childItem = folderEnum.Next(); if (childItem.is_dir) Crawl(childItem.realpath); } }
Command.Folder_ReadDirAndRename.js.txt (1.07 KB)

Add a call to CollectGarbage(); before the line that runs the command. That will force JScript to release the out-of-scope objects it is holding on to.

(CollectGarbage() is a Microsoft extension to JavaScript, and not technically guaranteed to do anything, but it seems to solve the problem.)

We'll also add a folderEnum.Close(); method in the next update, which may be needed for Perl/Python/etc. and will also be more efficient for JScript (since doing a whole GC to release one object is overkill).

Yes, it does the trick here too! Thank you very much for your investigation and research! o)
I was about to reimplement the Crawl() method to base on "Scripting.FilesystemObject", but prefer it this way of course! o)