Author Topic: Progressbar starts too late  (Read 8965 times)

clamicun

  • Member
  • ***
  • Posts: 257
Progressbar starts too late
« on: December 05, 2014, 04:53:32 AM »
This is a part of my own "Search Program".
It is far from beeing finished.

I am puzzled because the progressbar does not start  to run when it should ....
Very likely I do not understand some  basics.
----
I start the progressbar -(Modeless dialog)...
Immediately after - I start the proc which searches for existing directories in the choosen path...

The progressbar shows up, but starts running only after the search has finished.

Any good ideas ?

PS.
I do know that I have to "hook" the progressbar somehow to the search proc - but first things first.
If your machine goes down - enlarge the dir_array buffer. My C:\ only contents 19000 directories.


 

jj2007

  • Member
  • *****
  • Posts: 8617
  • Assembler is fun ;-)
    • MasmBasic
Re: Progressbar starts too late
« Reply #1 on: December 05, 2014, 07:04:46 AM »
You need to send a message to the progress bar from the loop where you find the directories. SetTimer is not the right approach...

Attached a modified example, using a fake WM_TIMER message.

Note that I get a different count with GetFolders(), but no idea why. You might compare them with the WindowsFolders.txt file created with the snippet below (about 2MB).

include \masm32\MasmBasic\MasmBasic.inc      ; download
  Init
  Let esi=ExpandEnv$("%WINDIR%\")      ; 21204 (JJ) vs 18624 (clamicun)
  PrintLine "Searching ", esi
  GetFolders esi
  Print Str$("%i folders found, first 10:\n", eax)
  xor ecx, ecx
  .Repeat
      PrintLine Files$(ecx)
      inc ecx
  .Until ecx>10
  Store "WindowsFolders.txt", Files$()
  Inkey "ok?"
  Exit
end start

clamicun

  • Member
  • ***
  • Posts: 257
Re: Progressbar starts too late
« Reply #2 on: December 05, 2014, 10:09:34 PM »
jj2007 thank you.

"You need to send a message to the progress bar from the loop where you find the directories. SetTimer is not the right approach..."

I try to organize the message - not exactely shure what kind of msg..

----------------
I made the directory selection  a bit easier...

CreateDirArray proc
pushad

xor eax,eax
mov eax,wfd.dwFileAttributes
AND eax,16

;push eax
;INVOKE MessageBox,0,offset wfd.cFileName,offset cur_path,0
;INVOKE wsprintf,offset wsprintf_msg,offset testintdd,wfd.dwFileAttributes
;INVOKE MessageBox,0,offset wsprintf_msg,offset cur_path,0
;pop eax

;.if  eax == 16 || eax == 17   || eax == 18   ||  eax == 19  || eax == 22 \
;               || eax == 48   || eax == 50   ||  eax == 51 \
;               || eax == 8208 || eax == 8212 || eax == 8214 ||  eax == 8240 || eax == 9238

.if eax != 0

;Above I included AttribValue 8212 - The count is different now - much higher
;INVOKE MessageBox,0,offset wfd.cFileName,offset cur_path,0

;--- Clean array ----
"
"
----------------
Have a good one

Tedd

  • Member
  • ***
  • Posts: 353
  • Procrastinor Extraordinaire
Re: Progressbar starts too late
« Reply #3 on: December 06, 2014, 12:05:49 AM »
The issue is that you only have one thread.
The search keeps the thread busy, so the window doesn't get updated, so the progress bar isn't updated.
Run the search in a separate thread and then the window can continue to be updated.
Potato2

clamicun

  • Member
  • ***
  • Posts: 257
Re: Progressbar starts too late
« Reply #4 on: December 06, 2014, 01:04:53 AM »
JJ
Your program creates the textfile - and real fast.
But it does not give out any message and does not end. I have to kill it with the taskmanager !
So I can not compare the result to the result of my very slow proc.
----------
On my computer it works like this...
include \masm32\MasmBasic\MasmBasic.inc      ; download

.data
;------------
store_folder TCHAR 'Folders.txt',0

;cur_path    TCHAR 'D:\test\',0
;cur_path    TCHAR 'D:\arquivo\',0
;cur_path    TCHAR 'D:\software\',0
cur_path     TCHAR 'C:\windows\',0

.code

  Init

  mov esi,offset cur_path
 
  PrintLine "Searching ", esi            ;No
  GetFolders esi
  Print Str$("%i folders found, first 10:\n", eax)   ;No
 
;-----  ???
  ;xor ecx, ecx
  ;.Repeat

      PrintLine Files$(ecx)   ;No
      ;inc ecx
  ;.Until ecx > 1
  ;Store "WindowsFolders.txt", Files$()
 ;-----  ???
 
  Store offset store_folder, Files$()
 
  ;Inkey "ok?"          ;No - This causes to not end the program !
  INVOKE MessageBox,0,offset cur_path,offset cur_path,0
  INVOKE ExitProcess,0
end start

---------------------------------
Tedd
Yes - I already thought on the multithread problem. I think that is it

jj2007

  • Member
  • *****
  • Posts: 8617
  • Assembler is fun ;-)
    • MasmBasic
Re: Progressbar starts too late
« Reply #5 on: December 06, 2014, 02:51:15 AM »
JJ
Your program creates the textfile - and real fast.
But it does not give out any message and does not end. I have to kill it with the taskmanager !

In case you are using qEditor or similar: You need to build it as a console application, otherwise print and inkey won't work.
RichMasm autodetects console apps, but most other IDEs don't, unfortunately.

Speedwise there is not much difference between our codes. According to my timings, GetFolder may be a little bit faster (20%?), but that doesn't really matter. For both, there is a huge difference between the first and the second time you run the program, due to the file cache. A more interesting question is why the folder counts differ - could be linked to attributes like system & hidden.

jj2007

  • Member
  • *****
  • Posts: 8617
  • Assembler is fun ;-)
    • MasmBasic
Re: Progressbar starts too late
« Reply #6 on: December 06, 2014, 02:58:30 AM »
The issue is that you only have one thread.
The search keeps the thread busy, so the window doesn't get updated, so the progress bar isn't updated.

Interesting point, Tedd. My example above (console build!) works with a single thread, but the progress bar does get updated. It seems that SendMessage returns only after the progress bar has been updated.

The bigger problem is that you can't tell beforehand how many folders correspond to 100% :(

There seems no API that can do that, so apparently you need FindFirstFile & FindNextFile to find the total number of folders; which implies that you'll know what 100% means after the exercise, but during the search you'll have no idea - which makes the progress bar kind of meaningless. Unless somebody knows a magic API that can ask the NTFS directly "how many subfolders are in %WinDir%?"...

clamicun

  • Member
  • ***
  • Posts: 257
Re: Progressbar starts too late
« Reply #7 on: December 06, 2014, 04:36:34 AM »
JJ

Here is a fine working proc - made from yours.
S4F.zip

The differences  indeed seem to be "Windowsmade". Obviously "getfolders" does not count  folders with certain attributes.

On the progressbar I am working. If I find solution, I let you know.

jj2007

  • Member
  • *****
  • Posts: 8617
  • Assembler is fun ;-)
    • MasmBasic
Re: Progressbar starts too late
« Reply #8 on: December 06, 2014, 05:33:37 AM »
Here is a fine working proc - made from yours.
Thanks :biggrin:

Quote
The differences  indeed seem to be "Windowsmade". Obviously "getfolders" does not count  folders with certain attributes.

My impression was that GetFolders counts more folders than yours, but I could be wrong, of course.

One more, just for fun:

include \masm32\MasmBasic\MasmBasic.inc      ; download
  Init
  Let esi=FolderOpen$("Pick a folder:", "Masm is great;", "\Masm32\examples\exampl01")+"\*"
  GetFolders esi
  push eax            ; save folder count to stack
  xor ecx, ecx
  .Repeat
      Print Str$("\n%i\t",ecx), Files$(ecx)
      inc ecx
  .Until ecx>=stack
  pop eax
  Inkey Str$("\n%i folders found in ", eax), esi
  Exit
end start

TWell

  • Member
  • ****
  • Posts: 748
Re: Progressbar starts too late
« Reply #9 on: December 06, 2014, 06:08:11 AM »
If call something like this inside loop, GUI may work ?
Code: [Select]
CheckMsgQueue PROC hWnd:DWORD
LOCAL msg:MSG
.WHILE 1
INVOKE PeekMessageA,ADDR msg,hWnd,0,0,1
.BREAK .IF (!eax)
.BREAK .IF (msg.message == 012h) ; WM_QUIT
INVOKE TranslateMessage,ADDR msg
INVOKE DispatchMessageA,ADDR msg
.ENDW
ret
CheckMsgQueue ENDP
Correct this, if there is something wrong.

jj2007

  • Member
  • *****
  • Posts: 8617
  • Assembler is fun ;-)
    • MasmBasic
Re: Progressbar starts too late
« Reply #10 on: December 06, 2014, 09:17:23 PM »
If call something like this inside loop, GUI may work ?

You should post the complete code to see how it is embedded in the rest of the application. PeekMessage is generally not such a good idea, because it can drive up CPU usage.

In the meantime, GetFolders() has learnt to accept a callback. Below a very simple example, but you could also implement a file counter, or display all files/paths found or tested etc; edx is current count, edi is path tested with FindFirstFileEx, and eax is the result of the test.

include \masm32\MasmBasic\MasmBasic.inc     ; download version 6 December
  Init
  Let esi=ExpandEnv$("%WINDIR%\System32")   ; usually C:\Windows\System32
  Print "Searching ", esi, ": "
  GfCallback cbGetFiles                     ; define a callback function
  GetFolders esi
  Print Str$(" - %i folders found, first 20:", eax)
  xor ecx, ecx
  .Repeat
      Print Str$("\n%i\t", ecx+1), Files$(ecx)
      inc ecx
  .Until ecx>=20
  ; Store "Sys32Folders.txt", Files$()      ; in case you need a textfile
  Inkey CrLf$, "ok?"
  Exit

cbGetFiles:
  test edx, 31       ; edx is file or folder counter
  .if Zero?          ; every once in while
      Print "*"      ; console mode progress bar ;-)
  .endif
  ret
end start


Simple variant displaying the file counter in a constant position on the screen:

cbGetFiles:
  Print Str$(edx), Cr$
  ret

TWell

  • Member
  • ****
  • Posts: 748
Re: Progressbar starts too late
« Reply #11 on: December 06, 2014, 09:39:05 PM »
You should post the complete code to see how it is embedded in the rest of the application. PeekMessage is generally not such a good idea, because it can drive up CPU usage.
No code as i'm not an asm programmer.
I like use that PeekMessage in single threaded program as it make debugging easier.

clamicun

  • Member
  • ***
  • Posts: 257
Re: Progressbar starts too late
« Reply #12 on: December 08, 2014, 10:04:23 PM »
JJ,
"My impression was that GetFolders counts more folders than yours, but I could be wrong, of course.!

Excuse me - .Of course you were not wrong. GetFolders counted more. Not any more. I found out why.

Windows creates folders like: \.NET ,  \.!!,   \.cache   

Because of the line

.if byte ptr  wfd.cFileName != '.'

my program did not find them.

Your program GetFolders with callback does  not compile on my computer...
Syntax error : gfCallback on line 5.
----------
Tedd,
"The issue is that you only have one thread.Run the search in a separate thread and then the window can continue to be updated."

Could you or someone be a bit more explicit - I do not have the slightest idea how to start a new thread.

jj2007

  • Member
  • *****
  • Posts: 8617
  • Assembler is fun ;-)
    • MasmBasic
Re: Progressbar starts too late
« Reply #13 on: December 09, 2014, 01:15:17 AM »
Your program GetFolders with callback does  not compile on my computer...
Syntax error : gfCallback on line 5.

You must have an incredibly old version of MasmBasic: Since 6 December, it understands GfCallback (note: uppercase G and C). And since right now (download again, please), the callback passes in ebx the address of the WIN32_FIND_DATAW structure used to do the search - see example below.

I am curious to see your latest version, to see whether they still differ, and where.

include \masm32\MasmBasic\MasmBasic.inc      ; download
  Init
  Let esi=ExpandEnv$("%WINDIR%")      ; usually C:\Windows
  PrintLine "Searching ", esi, ": "
  GfCallback cbGetFiles      ; define a callback function
  GetFolders esi
  Print Str$("%i folders found, first 20:", eax)
  xor ecx, ecx
  .Repeat
      Print Str$("\n%i\t", ecx+1), Files$(ecx)
      inc ecx
  .Until ecx>=20
  ; Store "Sys32Folders.txt", Files$()      ; in case you need a textfile
  Inkey CrLf$, "ok?"
  Exit

cbGetFiles:
  test edx, 1023      ; edx is file or folder counter
  .if Zero?                  ; every once in while
      lea edx, [ebx.WIN32_FIND_DATAW.cFileName]
      Print edx, CrLf$
  .endif
  ret
end start

clamicun

  • Member
  • ***
  • Posts: 257
Re: Progressbar starts too late
« Reply #14 on: December 10, 2014, 03:36:52 AM »
Hello JJ,
here are the 2 versions. My finds 2 folders more on my C-Drive.
I didn't yet see which entries are not there, because the textfiles are 200KB - that is labourious.

Yours is better. I don't know how it finds the folders which start with '.' without explicitly naming them as my does.
What is the difference between WIN32_FIND_DATA  and WIN32_FIND_DATAW ?