What happened to the Messenger Plus! forums on msghelp.net?
Shoutbox » MsgHelp Archive » Messenger Plus! for Live Messenger » Scripting » [?] Enumerating through files in Win32

[?] Enumerating through files in Win32
Author: Message:
SmokingCookie
Senior Member
****

Avatar

Posts: 815
Reputation: 15
30 / Male / Flag
Joined: Jul 2007
O.P. [?] Enumerating through files in Win32
Seems like Win32's not doing things it's said to be. Anyway, I've worked along the lines of this MSDN article, but somehow I can't get more than 2 valid file names, plus one "dummy" result; that dummy allows one to check if Interop.GetLastError() returns 18 (ERROR_NO_MORE_FILES) or something else is wrong. Indeed, Interop.GetLastError() does return ERROR_NO_MORE_FILES at the dummy, but I'm still getting only 2 useful results. Code:

JScript code:
/* FileSystem object and Print() functions defined elsewhere
furthermore: Paths.Root =  MsgPlus.ScriptFilesPath + "\\";*/

FileSystem.EnumerateFiles = function(Directory) {
    var ret = new Array();
    var result = this.FindFirstFile(Directory);
    if(result.hFind === 0) {
        result.WIN32_FIND_DATA.Size = 0;
        return ret;
    }
    ret.push(result);
    do {
        result = this.FindNextFile(result.hFind);
        ret.push(result);
    } while(result.hFind !== 0);
    return ret;
}

FileSystem.FindClose = function(hFind) {
    return Interop.Call("Kernel32.dll","FindClose",hFind);
}

FileSystem.FindNextFile = function(hFind,pData) {
    ret = new Object();
    ret.WIN32_FIND_DATA = typeof pData === "object" ? pData : Allocate(592); // confirmed working
    ret.hFind = Interop.Call("Kernel32.dll","FindNextFileW",hFind,ret.WIN32_FIND_DATA.DataPtr);
    ret.LastError = Interop.GetLastError();
    return ret;
}

FileSystem.FindFirstFile = function(sFile) {
    if(typeof sFile === "number") sFile = this.GetPathFromHandle(sFile); // confirmed working
    var ret = new Object();
    ret.WIN32_FIND_DATA = Allocate(592); // confirmed working
    ret.hFind = Interop.Call("Kernel32.dll","FindFirstFileW",sFile,ret.WIN32_FIND_DATA.DataPtr);
    ret.LastError = Interop.GetLastError();
    return ret;
}

var FindResult = FileSystem.EnumerateFiles(Paths.Root + "*");
for(var i = 0; i < FindResult.length; i++) {
    Print(FindResult[i].hFind);
    Print(FindResult[i].LastError);
    Print(FindResult[i].WIN32_FIND_DATA.readDWORD(0));
    Print(FindResult[i].WIN32_FIND_DATA.readSTRING(44));
    FindResult[i].WIN32_FIND_DATA.Size = 0;
    FileSystem.FindClose(FindResult[i].hFind);
}

The output is always:

code:
> 322211400 // some handle
> 0 // Interop.GetLastError() result => nothing's wrong
> 16 // dwFileAttributes member from the WIN32_FIND_DATA structure => this result is the current directory
> . // cFileName[MAX_PATH] member from the same struct
> 1 // always the same handle
> 0 // Interop.GetLastError() result => still okay
> 16 // Again a directory
> .. //cFileName[MAX_PATH] => parent directory
> 0 // dummy result with return value 0
> 18 // ERROR_NO_MORE_FILES
> 0 // Attributes
> // NULL

Also, calling the function for, say "Paths.Root + *.js" does something similar: it gives the first 2 .js files and then returns the same dummy. Any advice to get this working is welcome.
10-27-2011 07:54 PM
Profile PM Find Quote Report
matty
Scripting Guru
*****


Posts: 8336
Reputation: 109
39 / Male / Flag
Joined: Dec 2002
Status: Away
RE: [?] Enumerating through files in Win32
js code:
function GetDirectoryStructure(sPath, sPattern, IncludePath) {
        _debug.getfuncname(arguments);
        var aFileNames = [];
        var Win32_Find_Data = Interop.Allocate(592);
        var hSearch = Interop.Call('kernel32', 'FindFirstFileW', '\\\\?\\' + sPath + sPattern, Win32_Find_Data);
        var hResult;
        while (hResult !== 0) {
                if (!(Win32_Find_Data.ReadDWORD(0) & 0x10 /* FILE_ATTRIBUTE_DIRECTORY */ & 0x4 /* FILE_ATTRIBUTE_SYSTEM */) &&
                                 Win32_Find_Data.ReadString(44).charAt(0) !== '.') {
                        aFileNames.push((IncludePath ? sPath : '') + Win32_Find_Data.ReadString(44));
                }
                hResult = Interop.Call('kernel32', 'FindNextFileW', hSearch, Win32_Find_Data)
        }
        Interop.Call('kernel32', 'FindClose', hSearch);
        return aFileNames;
}

That is what we did for SS5. You only need to close the first handle, not all of them.

The problem is that you keep overwriting hFind. hFind should be the handle to the directory not the next file you keep finding. At least that is what it appears. No WLM/Plus! installed to check.

Do something like this:
js code:
FileSystem.EnumerateFiles = function(Directory) {
    var ret = new Array();
>>>    var result;<<<
>>>    var hFind = (result = this.FindFirstFile(Directory)).hFind;<<<
    if(result.hFind === 0) {
        result.WIN32_FIND_DATA.Size = 0;
        return ret;
    }
    ret.push(result);
    do {
>>>        result = this.FindNextFile(hFind);<<<
        ret.push(result);
    } while(result.hFind !== 0);
    return ret;
}

This post was edited on 10-27-2011 at 10:27 PM by matty.
10-27-2011 09:31 PM
Profile E-Mail PM Find Quote Report
SmokingCookie
Senior Member
****

Avatar

Posts: 815
Reputation: 15
30 / Male / Flag
Joined: Jul 2007
O.P. RE: [?] Enumerating through files in Win32
JScript code:
FileSystem.EnumerateFiles = function(Directory) {
    var ret = new Array();
    var result = this.FindFirstFile(Directory);
    if(result.hFind === 0) {
        result.WIN32_FIND_DATA.Size = 0;
        return ret;
    }
    do {
        var oResult = this.FindNextFile(result.hFind);
        ret.push(oResult);
    } while(oResult.hFind !== 0);
    return ret;
}

That does it; I guess that using the result object in the loop changes the references stored in the array..?
10-29-2011 09:37 AM
Profile PM Find Quote Report
matty
Scripting Guru
*****


Posts: 8336
Reputation: 109
39 / Male / Flag
Joined: Dec 2002
Status: Away
RE: [?] Enumerating through files in Win32
quote:
Originally posted by SmokingCookie
That does it; I guess that using the result object in the loop changes the references stored in the array..?
Not exactly, you are changing the handle of the directory you are searching.

So you said find me the files in folder XYZ, it finds the first file as "." then you said find me the next file in XYZ and it found ".." but then you changed the handle of the object you were searching from XYZ to "..". Does that make sense?

If it doesn't make sense here is some pseudo since I am now on a computer and not my iPad:

This is what you should be doing

FindFirstFile ('XYZ')
> retval = 1
FindNextFile(1)
> retval = 100
FindNextFile(1)
> retval = 100

What you are doing is this
FindFirstFile ('XYZ')
> retval = 1
FindNextFile(1)
> retval = 100
FindNextFile(100)
> retval = 18 (no more files)

Hope that clears things up a bit.

Post 8000 w00t!

This post was edited on 10-31-2011 at 02:31 PM by matty.
10-31-2011 11:10 AM
Profile E-Mail PM Find Quote Report
SmokingCookie
Senior Member
****

Avatar

Posts: 815
Reputation: 15
30 / Male / Flag
Joined: Jul 2007
O.P. RE: [?] Enumerating through files in Win32
It sure does! I thought that FindNextFile() used the previously found handle, while it actually uses the handle retreived with FindFirstFile().

I suggest trying to make 2000 posts between now and December 2012 :P
10-31-2011 02:45 PM
Profile PM Find Quote Report
matty
Scripting Guru
*****


Posts: 8336
Reputation: 109
39 / Male / Flag
Joined: Dec 2002
Status: Away
RE: [?] Enumerating through files in Win32
quote:
Originally posted by SmokingCookie
It sure does! I thought that FindNextFile() used the previously found handle, while it actually uses the handle retreived with FindFirstFile().
After reading the MSDN article I can see why you would think that but no it has to be the original handle for the folder.

quote:
Originally posted by SmokingCookie
I suggest trying to make 2000 posts between now and December 2012 :P
Why is that? 10,000 posts in 10 years?
10-31-2011 02:53 PM
Profile E-Mail PM Find Quote Report
SmokingCookie
Senior Member
****

Avatar

Posts: 815
Reputation: 15
30 / Male / Flag
Joined: Jul 2007
O.P. RE: [?] Enumerating through files in Win32
quote:
Originally posted by matty
quote:
Originally posted by SmokingCookie
It sure does! I thought that FindNextFile() used the previously found handle, while it actually uses the handle retreived with FindFirstFile().
After reading the MSDN article I can see why you would think that but no it has to be the original handle for the folder.

Well, at least these details have been cleared up now, and my enumeration function works like a charm :)

quote:
Originally posted by matty
quote:
Originally posted by SmokingCookie
I suggest trying to make 2000 posts between now and December 2012 :P
Why is that? 10,000 posts in 10 years?

Exactly

This post was edited on 10-31-2011 at 03:55 PM by SmokingCookie.
10-31-2011 03:55 PM
Profile PM Find Quote Report
matty
Scripting Guru
*****


Posts: 8336
Reputation: 109
39 / Male / Flag
Joined: Dec 2002
Status: Away
RE: [?] Enumerating through files in Win32
Glad you got it sorted out!

And I will see what I can do about 2000 1995 posts in a 13 months.

This post was edited on 10-31-2011 at 05:36 PM by matty.
10-31-2011 05:36 PM
Profile E-Mail PM Find Quote Report
« Next Oldest Return to Top Next Newest »


Threaded Mode | Linear Mode
View a Printable Version
Send this Thread to a Friend
Subscribe | Add to Favorites
Rate This Thread:

Forum Jump:

Forum Rules:
You cannot post new threads
You cannot post replies
You cannot post attachments
You can edit your posts
HTML is Off
myCode is On
Smilies are On
[img] Code is On