Under Win 10, there seems to be files that have dates that are wacky (greater than today). I wrote some thing to go thru all the files on my PC, starting at c:\ and then to process all files. It is supposed to only show those that have weird dates, but since it is quitting long before it processes more than a few directories, I need help. Has recursion been limited on the latest version of IWB?
I am attaching my code, it writes all records right now, but until I can find out why it stops after only a few directories, it will print all.
Thanks for any help,
Bill
Found the problem, it seems that values inside the subroutine that is being called recursively need to be defined within the subroutine.
Bill
Glad you found it.
I just started looking at it and couldn't even get it to run more than 20 iterations on my machines without crashing and wanting to phone home to MS.
Remember this old faithful:
DEF count:INT
OPENCONSOLE
'recursively print all directories
count = printdir("c:\\")
PRINT count,"Files"
PRINT "Press Any Key"
DO:UNTIL INKEY$ <> ""
CLOSECONSOLE
END
SUB printdir(path:STRING),INT
DEF count:INT
DEF dir,attrib:INT
DEF filename:STRING
DEF fullname:STRING
count = 0
dir = FINDOPEN(path + "*.*")
IF(dir)
DO
filename = FINDNEXT(dir,attrib)
IF len(filename)
IF attrib & @FILE_DIRECTORY
IF(filename <> ".") & (filename <> "..")
PRINT path + "[" + filename + "]"
fullname = path + filename + "\\"
count = count + printdir(fullname)
ENDIF
ELSE
count = count + 1
PRINT path + filename
ENDIF
ENDIF
'the exit case is when there are no more entries
'in the current directory
UNTIL filename = ""
FINDCLOSE dir
ENDIF
RETURN count
ENDSUB
It found all 858,095 files and print the full path names in the console window on my win7 machine in a matter of just a few minutes.
Little gui version I made for fun :) it will be more slow because it runs in a separate thread, but you can control its behavior a bit more using the interface.
$INCLUDE "windowssdk.inc"
$INCLUDE "Shlobj.inc"
' ----------------------------------------------------------------------------------------------------
' INTERFACE
' ----------------------------------------------------------------------------------------------------
CONST EDIT_DIR = 1
CONST BUTTON_DIR = 2
CONST LISTBOX_FILES = 3
CONST BUTTON_START = 4
CONST BUTTON_PAUSE = 5
CONST BUTTON_STOP = 6
CONST STATIC_TIME = 7
CONST STATIC_FILES = 8
CONST TIMER_1 = 9
DIALOG d1
CREATEDIALOG d1,0,0,600,490,0x80CA0080,0,"Scan",&d1_handler
CONTROL d1,@EDIT,"",20,20,440,30,0x50800800,EDIT_DIR
CONTROL d1,@BUTTON,"Select directory",480,20,100,30,0x50000000,BUTTON_DIR
CONTROL d1,@LISTBOX,"",20,70,560,350,0x50A00140,LISTBOX_FILES
CONTROL d1,@SYSBUTTON,"start",20,440,80,30,0x50000000,BUTTON_START
CONTROL d1,@SYSBUTTON,"Pause",120,440,80,30,0x50000000,BUTTON_PAUSE
CONTROL d1,@SYSBUTTON,"Stop",220,440,80,30,0x50000000,BUTTON_STOP
CONTROL d1,@STATIC,"",330,447,110,30,0x5000010B,STATIC_TIME
CONTROL d1,@STATIC,"",470,447,110,30,0x5000010B,STATIC_FILES
' ----------------------------------------------------------------------------------------------------
' DATA
' ----------------------------------------------------------------------------------------------------
' STRING BUFFER SIZE
CONST STRING_SIZE = 500
' FLAG
INT dirSelected = 0
INT threadState = 0 ' 0 default, 1 running, 2 paused
' VARIABLES
INT timeElapsed = 0
INT fileCount = 0
CRITICAL_SECTION critSec ' thread safe object
uint hThread = 0 ' thread ID
' ----------------------------------------------------------------------------------------------------
' PROGRAM ENTRY POINT
' ----------------------------------------------------------------------------------------------------
DOMODAL d1
' ----------------------------------------------------------------------------------------------------
' PROCEDURE
' ----------------------------------------------------------------------------------------------------
SUB d1_handler
SELECT @MESSAGE
CASE @IDINITDIALOG
CENTERWINDOW d1
/* Initialize any controls here */
OnInit()
CASE @IDCLOSEWINDOW
OnFinish()
CLOSEDIALOG d1,@IDOK
CASE @IDTIMER
INT elapsed = GetTimeElapsed()
SetTimeElapsed(elapsed + 1)
DisplayTimeElapsed()
CASE @IDCONTROL
SELECT @CONTROLID
CASE BUTTON_DIR
IF @NOTIFYCODE = 0
/*button clicked*/
OnSelectDir()
ENDIF
CASE BUTTON_START
IF @NOTIFYCODE = 0
/*button clicked*/
OnStart()
ENDIF
CASE BUTTON_PAUSE
IF @NOTIFYCODE = 0
/*button clicked*/
OnPause()
ENDIF
CASE BUTTON_STOP
IF @NOTIFYCODE = 0
/*button clicked*/
OnStop()
ENDIF
ENDSELECT
ENDSELECT
RETURN
ENDSUB
' ----------------------------------------------------------------------------------------------------
' EVENTS
' ----------------------------------------------------------------------------------------------------
SUB OnInit()
' init COM
OleInitialize(0)
InitializeCriticalSection(critSec)
updateGUI()
ENDSUB
SUB OnFinish()
IF threadState > 0 THEN OnStop()
DeleteCriticalSection(critSec)
' finish COM
OleUninitialize()
ENDSUB
SUB OnSelectDir()
ISTRING dir[STRING_SIZE] = FolderDialog()
IF LEN(dir) THEN
dirSelected = 1
SETCONTROLTEXT d1, EDIT_DIR, dir
UpdateGUI()
ENDIF
ENDSUB
SUB OnStart()
INT state = GetThreadState()
IF state = 2 THEN ' paused
' resume thread
SetThreadState(1)
UpdateGUI()
ResumeThread(hThread)
ELSE
SetTimeElapsed(0)
SetFileCount(0)
DisplayTimeElapsed()
SENDMESSAGE d1, LB_RESETCONTENT, 0, 0 ,LISTBOX_FILES
SETCONTROLTEXT d1, STATIC_TIME, ""
SETCONTROLTEXT d1, STATIC_FILES, ""
SetThreadState(1)
_StartTimer()
UpdateGUI()
' start thread
InitThread()
ENDIF
ENDSUB
SUB OnPause()
SetThreadState(2) ' paused
_StopTimer()
UpdateGUI()
' pause thread
SuspendThread(hThread)
ENDSUB
SUB OnStop()
SetThreadState(0) ' default
_StopTimer()
UpdateGUI()
' stop thread
TerminateThread(hThread, -1)
ENDSUB
' ----------------------------------------------------------------------------------------------------
' BROWSE FOR FOLDER DIALOG
' ----------------------------------------------------------------------------------------------------
SUB FolderDialog(), string
BROWSEINFO bi
ZeroMemory(&bi, LEN(bi))
bi.lpszTitle = "Select directory"
bi.ulFlags = BIF_RETURNONLYFSDIRS | BIF_NEWDIALOGSTYLE
bi.lpfn = 0
pointer pidl = SHBrowseForFolder(&bi)
IF pidl THEN RETURN fixPath(GetDirectory(pidl))
RETURN ""
ENDSUB
SUB FixPath(string path), string
IF RIGHT$(path, 1) <> "\\"
RETURN path + "\\"
ENDIF
RETURN path
ENDSUB
SUB GetDirectory(pointer pidl), string
IWSTRING dir[STRING_SIZE] = L""
IShellItem psi = 0
IF FAILED(SHCreateShellItem(NULL, NULL, pidl, &psi)) THEN RETURN ""
pointer pwszTip = CoTaskMemAlloc(STRING_SIZE)
IF SUCCEEDED(psi->GetDisplayName(SIGDN_DESKTOPABSOLUTEPARSING, &pwszTip))
dir = #<wstring>pwszTip
ENDIF
CoTaskMemFree(pwszTip)
psi->Release()
RETURN W2S(dir)
ENDSUB
' ----------------------------------------------------------------------------------------------------
' THREAD SAFE FUNCTIONS
' ----------------------------------------------------------------------------------------------------
SUB SetfileCount(int count)
EnterCriticalSection(critSec)
fileCount = count
LeaveCriticalSection(critSec)
ENDSUB
SUB GetFileCount(), INT
EnterCriticalSection(critSec)
INT count = fileCount
LeaveCriticalSection(critSec)
RETURN count
ENDSUB
SUB SetTimeElapsed(int elapsed)
EnterCriticalSection(critSec)
timeElapsed = elapsed
LeaveCriticalSection(critSec)
ENDSUB
SUB GetTimeElapsed(), INT
EnterCriticalSection(critSec)
INT elapsed = timeElapsed
LeaveCriticalSection(critSec)
RETURN elapsed
ENDSUB
SUB SetThreadState(int state)
EnterCriticalSection(critSec)
threadState = state
LeaveCriticalSection(critSec)
ENDSUB
SUB GetThreadState(), INT
EnterCriticalSection(critSec)
INT state = threadState
LeaveCriticalSection(critSec)
RETURN state
ENDSUB
SUB DisplayTimeElapsed()
EnterCriticalSection(critSec)
INT min = GetTimeElapsed() / 60
INT sec = GetTimeElapsed() - 60 * min
SETCONTROLTEXT d1, STATIC_TIME, "Time: " + STR$(min) + "m " + STR$(sec) + "s"
LeaveCriticalSection(critSec)
ENDSUB
SUB _StartTimer()
EnterCriticalSection(critSec)
STARTTIMER d1, 1000, TIMER_1
LeaveCriticalSection(critSec)
ENDSUB
SUB _StopTimer()
EnterCriticalSection(critSec)
STOPTIMER d1, TIMER_1
LeaveCriticalSection(critSec)
ENDSUB
SUB updateGUI()
EnterCriticalSection(critSec)
IF threadState = 0 THEN ' default
SETCONTROLTEXT d1, BUTTON_START, "Start"
ELSE
SETCONTROLTEXT d1, BUTTON_START, "Continue"
ENDIF
IF dirSelected = 0 THEN
ENABLECONTROL d1, BUTTON_DIR, 1
ENABLECONTROL d1, BUTTON_START, 0
ENABLECONTROL d1, BUTTON_PAUSE, 0
ENABLECONTROL d1, BUTTON_STOP, 0
ELSE
SELECT threadState
CASE 0 ' default
ENABLECONTROL d1, BUTTON_DIR, 1
ENABLECONTROL d1, BUTTON_START, 1
ENABLECONTROL d1, BUTTON_PAUSE, 0
ENABLECONTROL d1, BUTTON_STOP, 0
CASE 1 ' running
ENABLECONTROL d1, BUTTON_DIR, 0
ENABLECONTROL d1, BUTTON_START, 0
ENABLECONTROL d1, BUTTON_PAUSE, 1
ENABLECONTROL d1, BUTTON_STOP, 1
CASE 2 ' paused
ENABLECONTROL d1, BUTTON_DIR, 0
ENABLECONTROL d1, BUTTON_START, 1
ENABLECONTROL d1, BUTTON_PAUSE, 0
ENABLECONTROL d1, BUTTON_STOP, 1
ENDSELECT
ENDIF
LeaveCriticalSection(critSec)
ENDSUB
' ----------------------------------------------------------------------------------------------------
' THREAD FUNCTIONS
' ----------------------------------------------------------------------------------------------------
SUB InitThread()
ISTRING dir[STRING_SIZE] = GETCONTROLTEXT (d1, EDIT_DIR)
IF LEN(dir) THEN
hThread = CreateThread(NULL, 0, &ThreadFunc, dir, CREATE_SUSPENDED, 0)
IF hThread THEN ResumeThread(hThread)
ENDIF
ENDSUB
SUB ThreadFunc(pointer param), INT
ISTRING dir[STRING_SIZE] = *<string>param
printdir(dir)
SetThreadState(0)
_StopTimer()
UpdateGUI()
RETURN 0
ENDSUB
SUB printdir(path:STRING),INT
DEF count:INT
DEF dir,attrib:INT
DEF filename:STRING
DEF fullname:STRING
count = 0
dir = FINDOPEN(path + "*.*")
IF(dir)
DO
'Sleep(10) ' if CPU usage is too high enable this line, and try different values
filename = FINDNEXT(dir,attrib)
IF len(filename)
IF attrib & @FILE_DIRECTORY
IF(filename <> ".") AND (filename <> "..")
fullname = path + filename + "\\"
count = count + printdir(fullname)
ENDIF
ELSE
count = count + 1
ListBoxAddFile(path + filename)
ENDIF
ENDIF
'the exit case is when there are no more entries
'in the current directory
UNTIL filename = ""
FINDCLOSE dir
ENDIF
RETURN count
ENDSUB
SUB ListBoxAddFile(string text)
INSERTSTRING d1, LISTBOX_FILES, 0, text
INT count = GetfileCount()
count += 1
SetFileCount(count)
SETCONTROLTEXT d1, STATIC_FILES, STR$(count) + " files"
ENDSUB
All I can say is WOW to fasecero...
I loaded and tried your version and it is amazing. Lightning fast and your code is very interesting. It will take me a while to comprehend exactly how it works, but I really like it.
Thank you for sharing.
Bill
Now for the next part of why I originally started this program. I need to be able to call Windows Powershell and send it a command to change the Creation Date of those files that have dates that are > current date.
Here is the powershell command to be run (Note: I will need some one to tell me how to run Powershell from IWB):
Get-ChildItem C:\testFile1.txt | % {$_.CreationTime = '05/27/2017 12:00:00'}
I am planning on keeping the original time, but changing the date to be < current date, but still based on what the wrong creation date shows.
Examples:
2052-06-12 -> 2016-06-12
2052-02-22 -> 2017-02-22
I am doing this, since Win 10 complains when I copy these weirdly dated files to another media and I want to stop it from prompting me every time I try and copy these files. Plus it will also allow for better backups. Plus I think there might be other people who could use this for the same purpose.
Thanks,
Bill
Can Powershell commands be run from the command line? i.e.
Powershell.exe Get-ChildItem C:\testFile1.txt | % {$_.CreationTime = '05/27/2017 12:00:00'}
That was just way too easy. Was thinking too much.
Thanks LarryMc,
Bill
If you need to run it from within your program you can use the SYSTEM() function. You will have to have saperos windowssdk.inc included.
system("Powershell.exe Get-ChildItem C:\testFile1.txt | % {$_.CreationTime = '05/27/2017 12:00:00'}")
I think this should work. I haven't tried it.
Later,
Clint
Well, I tried fasecero's little program. It ran, I set up a directory, I pressed start and nothing happened!
Brian
It is possible to get nothing, if your files all had dates < current date. My program is looking for dates > current date. On my system they are > 2051. My program will reset them to be < current date, when I get it working. That way when you copy them to a backup or to a Jump Drive, they will not complain about them.
Bill
Brian, you are correct, was passing a local variable to thread, and this caused that the code does not work properly on some directories. It should work now. The thread causes the source code to be a lot more complex :o so probably will need aditional tweeks. The adventage is that the dialog will continue to be responsive and follow user commands (like move, minimize, pressing buttons, ...) despite the fact of performing a long and otherwise gui-blocking task, and gives the user the ability to pause or stop anytime.
$INCLUDE "windowssdk.inc"
$INCLUDE "Shlobj.inc"
' ----------------------------------------------------------------------------------------------------
' INTERFACE
' ----------------------------------------------------------------------------------------------------
CONST EDIT_DIR = 1
CONST BUTTON_DIR = 2
CONST LISTBOX_FILES = 3
CONST BUTTON_START = 4
CONST BUTTON_PAUSE = 5
CONST BUTTON_STOP = 6
CONST STATIC_TIME = 7
CONST STATIC_FILES = 8
CONST TIMER_1 = 9
DIALOG d1
CREATEDIALOG d1,0,0,600,490,0x80CA0080,0,"Scan",&d1_handler
CONTROL d1,@EDIT,"",20,20,440,30,0x50800800,EDIT_DIR
CONTROL d1,@BUTTON,"Select directory",480,20,100,30,0x50000000,BUTTON_DIR
CONTROL d1,@LISTBOX,"",20,70,560,350,0x50A00140,LISTBOX_FILES
CONTROL d1,@SYSBUTTON,"start",20,440,80,30,0x50000000,BUTTON_START
CONTROL d1,@SYSBUTTON,"Pause",120,440,80,30,0x50000000,BUTTON_PAUSE
CONTROL d1,@SYSBUTTON,"Stop",220,440,80,30,0x50000000,BUTTON_STOP
CONTROL d1,@STATIC,"",330,447,110,30,0x5000010B,STATIC_TIME
CONTROL d1,@STATIC,"",470,447,110,30,0x5000010B,STATIC_FILES
' ----------------------------------------------------------------------------------------------------
' DATA
' ----------------------------------------------------------------------------------------------------
' STRING BUFFER SIZE
CONST STRING_SIZE = 500
' FLAG
INT dirSelected = 0
INT threadState = 0 ' 0 default, 1 running, 2 paused
' VARIABLES
INT timeElapsed = 0
INT fileCount = 0
CRITICAL_SECTION critSec ' thread safe object
uint hThread = 0 ' thread ID
' ----------------------------------------------------------------------------------------------------
' PROGRAM ENTRY POINT
' ----------------------------------------------------------------------------------------------------
DOMODAL d1
' ----------------------------------------------------------------------------------------------------
' PROCEDURE
' ----------------------------------------------------------------------------------------------------
SUB d1_handler
SELECT @MESSAGE
CASE @IDINITDIALOG
CENTERWINDOW d1
/* Initialize any controls here */
OnInit()
CASE @IDCLOSEWINDOW
OnFinish()
CLOSEDIALOG d1,@IDOK
CASE @IDTIMER
INT elapsed = GetTimeElapsed()
SetTimeElapsed(elapsed + 1)
DisplayTimeElapsed()
CASE @IDCONTROL
SELECT @CONTROLID
CASE BUTTON_DIR
IF @NOTIFYCODE = 0
/*button clicked*/
OnSelectDir()
ENDIF
CASE BUTTON_START
IF @NOTIFYCODE = 0
/*button clicked*/
OnStart()
ENDIF
CASE BUTTON_PAUSE
IF @NOTIFYCODE = 0
/*button clicked*/
OnPause()
ENDIF
CASE BUTTON_STOP
IF @NOTIFYCODE = 0
/*button clicked*/
OnStop()
ENDIF
ENDSELECT
ENDSELECT
RETURN
ENDSUB
' ----------------------------------------------------------------------------------------------------
' EVENTS
' ----------------------------------------------------------------------------------------------------
SUB OnInit()
' init COM
OleInitialize(0)
InitializeCriticalSection(critSec)
updateGUI()
ENDSUB
SUB OnFinish()
IF threadState > 0 THEN OnStop()
DeleteCriticalSection(critSec)
' finish COM
OleUninitialize()
ENDSUB
SUB OnSelectDir()
ISTRING dir[STRING_SIZE] = FolderDialog()
IF LEN(dir) THEN
dirSelected = 1
SETCONTROLTEXT d1, EDIT_DIR, dir
UpdateGUI()
ENDIF
ENDSUB
SUB OnStart()
INT state = GetThreadState()
IF state = 2 THEN ' paused
' resume thread
SetThreadState(1)
_StartTimer()
UpdateGUI()
ResumeThread(hThread)
ELSE
SetTimeElapsed(0)
SetFileCount(0)
DisplayTimeElapsed()
SENDMESSAGE d1, LB_RESETCONTENT, 0, 0 ,LISTBOX_FILES
SETCONTROLTEXT d1, STATIC_TIME, ""
SETCONTROLTEXT d1, STATIC_FILES, ""
SetThreadState(1)
_StartTimer()
UpdateGUI()
' start thread
InitThread()
ENDIF
ENDSUB
SUB OnPause()
SetThreadState(2) ' paused
_StopTimer()
UpdateGUI()
' pause thread
SuspendThread(hThread)
ENDSUB
SUB OnStop()
SetThreadState(0) ' default
_StopTimer()
UpdateGUI()
' stop thread
TerminateThread(hThread, -1)
ENDSUB
' ----------------------------------------------------------------------------------------------------
' BROWSE FOR FOLDER DIALOG
' ----------------------------------------------------------------------------------------------------
SUB FolderDialog(), string
BROWSEINFO bi
ZeroMemory(&bi, LEN(bi))
bi.lpszTitle = "Select directory"
bi.ulFlags = BIF_RETURNONLYFSDIRS | BIF_NEWDIALOGSTYLE
bi.lpfn = 0
pointer pidl = SHBrowseForFolder(&bi)
IF pidl THEN RETURN fixPath(GetDirectory(pidl))
RETURN ""
ENDSUB
SUB FixPath(string path), string
IF RIGHT$(path, 1) <> "\\"
RETURN path + "\\"
ENDIF
RETURN path
ENDSUB
SUB GetDirectory(pointer pidl), string
IWSTRING dir[STRING_SIZE] = L""
IShellItem psi = 0
IF FAILED(SHCreateShellItem(NULL, NULL, pidl, &psi)) THEN RETURN ""
pointer pwszTip = CoTaskMemAlloc(STRING_SIZE)
IF SUCCEEDED(psi->GetDisplayName(SIGDN_DESKTOPABSOLUTEPARSING, &pwszTip))
dir = #<wstring>pwszTip
ENDIF
CoTaskMemFree(pwszTip)
psi->Release()
RETURN W2S(dir)
ENDSUB
' ----------------------------------------------------------------------------------------------------
' THREAD SAFE FUNCTIONS
' ----------------------------------------------------------------------------------------------------
SUB SetfileCount(int count)
EnterCriticalSection(critSec)
fileCount = count
LeaveCriticalSection(critSec)
ENDSUB
SUB GetFileCount(), INT
EnterCriticalSection(critSec)
INT count = fileCount
LeaveCriticalSection(critSec)
RETURN count
ENDSUB
SUB SetTimeElapsed(int elapsed)
EnterCriticalSection(critSec)
timeElapsed = elapsed
LeaveCriticalSection(critSec)
ENDSUB
SUB GetTimeElapsed(), INT
EnterCriticalSection(critSec)
INT elapsed = timeElapsed
LeaveCriticalSection(critSec)
RETURN elapsed
ENDSUB
SUB SetThreadState(int state)
EnterCriticalSection(critSec)
threadState = state
LeaveCriticalSection(critSec)
ENDSUB
SUB GetThreadState(), INT
EnterCriticalSection(critSec)
INT state = threadState
LeaveCriticalSection(critSec)
RETURN state
ENDSUB
SUB DisplayTimeElapsed()
EnterCriticalSection(critSec)
INT min = GetTimeElapsed() / 60
INT sec = GetTimeElapsed() - 60 * min
SETCONTROLTEXT d1, STATIC_TIME, "Time: " + STR$(min) + "m " + STR$(sec) + "s"
LeaveCriticalSection(critSec)
ENDSUB
SUB _StartTimer()
EnterCriticalSection(critSec)
STARTTIMER d1, 1000, TIMER_1
LeaveCriticalSection(critSec)
ENDSUB
SUB _StopTimer()
EnterCriticalSection(critSec)
STOPTIMER d1, TIMER_1
LeaveCriticalSection(critSec)
ENDSUB
SUB updateGUI()
EnterCriticalSection(critSec)
IF threadState = 0 THEN ' default
SETCONTROLTEXT d1, BUTTON_START, "Start"
ELSE
SETCONTROLTEXT d1, BUTTON_START, "Continue"
ENDIF
IF dirSelected = 0 THEN
ENABLECONTROL d1, BUTTON_DIR, 1
ENABLECONTROL d1, BUTTON_START, 0
ENABLECONTROL d1, BUTTON_PAUSE, 0
ENABLECONTROL d1, BUTTON_STOP, 0
ELSE
SELECT threadState
CASE 0 ' default
ENABLECONTROL d1, BUTTON_DIR, 1
ENABLECONTROL d1, BUTTON_START, 1
ENABLECONTROL d1, BUTTON_PAUSE, 0
ENABLECONTROL d1, BUTTON_STOP, 0
CASE 1 ' running
ENABLECONTROL d1, BUTTON_DIR, 0
ENABLECONTROL d1, BUTTON_START, 0
ENABLECONTROL d1, BUTTON_PAUSE, 1
ENABLECONTROL d1, BUTTON_STOP, 1
CASE 2 ' paused
ENABLECONTROL d1, BUTTON_DIR, 0
ENABLECONTROL d1, BUTTON_START, 1
ENABLECONTROL d1, BUTTON_PAUSE, 0
ENABLECONTROL d1, BUTTON_STOP, 1
ENDSELECT
ENDIF
LeaveCriticalSection(critSec)
ENDSUB
' ----------------------------------------------------------------------------------------------------
' THREAD FUNCTIONS
' ----------------------------------------------------------------------------------------------------
TYPE THREAD_PARAM
ISTRING dir[STRING_SIZE]
ENDTYPE
SUB InitThread()
pointer param = NEW(THREAD_PARAM, 1)
*<THREAD_PARAM>param.dir = GETCONTROLTEXT (d1, EDIT_DIR)
IF LEN(*<THREAD_PARAM>param.dir) THEN
hThread = CreateThread(NULL, 0, &ThreadFunc, param, CREATE_SUSPENDED, 0)
IF hThread THEN ResumeThread(hThread)
ENDIF
ENDSUB
SUB ThreadFunc(pointer param), INT
ISTRING dir[STRING_SIZE] = *<THREAD_PARAM>param.dir
delete param
printdir(dir)
SetThreadState(0)
_StopTimer()
UpdateGUI()
RETURN 0
ENDSUB
SUB printdir(path:STRING),INT
DEF count:INT
DEF dir,attrib:INT
DEF filename:STRING
DEF fullname:STRING
count = 0
dir = FINDOPEN(path + "*.*")
IF(dir)
DO
'Sleep(10) ' if CPU usage is too high enable this line, and try different values
filename = FINDNEXT(dir,attrib)
IF len(filename)
IF attrib & @FILE_DIRECTORY
IF(filename <> ".") AND (filename <> "..")
fullname = path + filename + "\\"
count = count + printdir(fullname)
ENDIF
ELSE
count = count + 1
ListBoxAddFile(path + filename)
ENDIF
ENDIF
'the exit case is when there are no more entries
'in the current directory
UNTIL filename = ""
FINDCLOSE dir
ENDIF
RETURN count
ENDSUB
SUB ListBoxAddFile(string text)
INSERTSTRING d1, LISTBOX_FILES, 0, text
INT count = GetfileCount()
count += 1
SetFileCount(count)
SETCONTROLTEXT d1, STATIC_FILES, STR$(count) + " files"
ENDSUB
Billhsln, I really didn't want to divert the subject matter of your topic, sorry about this. Anyway, thank you very very much for your kind words. Back to topic, if powershell works, great, but if not, I think you can use winapi: CreateFile + SetFileTime. They are a little complex though.