News:

Masm32 SDK description, downloads and other helpful links
Message to All Guests

Main Menu

File-finder program: works, but ...

Started by NoCforMe, July 14, 2022, 01:29:30 PM

Previous topic - Next topic

NoCforMe

I've pretty much got my file-finder program working. Motivation for this was the fact that my Explorer is totally broken when it comes to searching for files. Does nothing. Totally useless. (My whole computer is pretty messed up, Windows 7 with many many problems.) So I wrote this. Learned a lot along the way. I'm attaching source and all for any curious onlookers.

It works but has a couple issues:

  • Long and/or deep searches cause some of the file icons to be corrupted. To see this, try doing a search first on .dll (this will find a shitload of files; 51,679 on my system. No wonder things are so screwed up! Too much complexity there!) Then try doing another search (I've been using "test"). You should see some black squares instead of file icons. I have no idea why this is happening. Not a deal-breaker but highly annoying.
  • Listview control gets screwed up, strangely. After a couple searches the first item gets partially covered; you can't scroll all the way up to see it.

The "find" field is implicitly wildcarded; i.e., test = *test*. That part works pretty reliably well.

A "text" search will search files for a text string, similarly wildcarded. Can be case sensitive or not. (All file searches are case-insensitive, per the file system.)

In case you're wondering about what I call the "flicker" field which comes up during a long (> 4 sec.) search and shows filenames flashing by, this was supposed to be a progress-bar control. It worked OK, except that on long searches it would stop moving (the PBS_MARQUEE behavior). This is another mystery to me. The static control works reliably, even though it's possibly more annoying to the user. I wanted something that would show the user that something is actually happening, that the damn thing isn't frozen.

Note: The source has one include file which is a memory dialog template (produced by another of my tools, DialogGen; if interested, I could post that here as well, though it's complicated). Otherwise pretty straightforward stuff.

What did I learn from writing this?
  • Thread execution (file-finder runs in a worker thread so UI isn't crippled)
  • Using SHGetFileInfo() to retrieve file icons
  • Weird file system stuff
What weird file system stuff? Well, for one thing, I discovered that FindFirstFile() and FindNextFile() will give me what are basically bogus files whose names are ':'. That's right; as we know, that's a totally "illegal" character for a filename. And yet you'll see those files if you do a full recursive scan of your filesystem. They occur in certain Windows folders; I think they are actually what they call "junctions" instead of real files. So I just filter them out and ignore them. (The file size fields for these "files" are set to some really wacky values.)
Assembly language programming should be fun. That's why I do it.

hutch--

The notation "." and ".." have ben around since the MS-DOS era and if you don't need or want them, just filter them out. They are useful enough as they can be passed to a comand line.

NoCforMe

If you look at the guts of my program, that's exactly what I do.

If I find a folder, I recurse into it. (Except for . and ..)

I use "..\[dir]" all the time with my command shell (good old 4DOS, still working after all these decades!) to hop over to an adjacent folder.
Assembly language programming should be fun. That's why I do it.

jj2007

I'd like to build your source, but... (inter alia, it expects a resource file not included in the archive):

Microsoft (R) Windows Resource To Object Converter Version 5.00.1736.1
Copyright (C) Microsoft Corp. 1992-1997. All rights reserved.

CVTRES : fatal error CVT1101: cannot open FindIt!_res.res for reading
Microsoft (R) Macro Assembler Version 10.00.40219.01
Copyright (C) Microsoft Corporation.  All rights reserved.

Assembling: FindIt!.asm

***********
ASCII build
***********

FindIt!.asm(73) : error A2008:syntax error : PROTO
strcat(17): Macro Called From
  FindIt!.asm(73): Main Line Code
FindIt!.asm(970) : error A2148:invalid symbol type in expression : strcat
FindIt!.asm(971) : error A2148:invalid symbol type in expression : strcat
FindIt!.asm(1117) : error A2148:invalid symbol type in expression : strcat
FindIt!.asm(1118) : error A2148:invalid symbol type in expression : strcat
FindIt!.asm(1210) : error A2148:invalid symbol type in expression : strcat
FindIt!.asm(1211) : error A2148:invalid symbol type in expression : strcat
FindIt!.asm(1404) : error A2148:invalid symbol type in expression : strcat
FindIt!.asm(1847) : error A2006:undefined symbol : dest
strcat(17): Macro Called From
  FindIt!.asm(1847): Main Line Code
FindIt!.asm(1847) : error A2114:INVOKE argument type mismatch : argument : 0
strcat(17): Macro Called From
  FindIt!.asm(1847): Main Line Code
FindIt!.asm(1847) : error A2206:missing operator in expression
strcat(17): Macro Called From
  FindIt!.asm(1847): Main Line Code
FindIt!.asm(1847) : error A2114:INVOKE argument type mismatch : argument : 2
strcat(17): Macro Called From
  FindIt!.asm(1847): Main Line Code
FindIt!.asm(1870) : error A2008:syntax error : ENDP
strcat(17): Macro Called From
  FindIt!.asm(1870): Main Line Code
FindIt!.asm(1851) : error A2006:undefined symbol : source
FindIt!.asm(1852) : error A2006:undefined symbol : dest
_
Assembly Error


With GetFiles, you have two choices:
  GetFiles \AllBasics\*.bas      ; simple extension
  GetFiles \AllBasics\*.bas*   ; bas, but also *.basic

The second one behaves like your executable, i.e. it returns *.bas* files. I'm not sure whether that's a feature or a design flaw, but think e.g. of a search for C header files (*.h) that returns also all *.htm and *.html files :cool:

Another design point: Your application allows to find
- all \Masm32\include\*.inc files
- all \Masm32\include\ files that contain the string "crt_"
- but not all \Masm32\include\*.inc files that contain the string "crt_"

Your executable finds files a factor 15 slower than mine, but that is easy to fix because it's entirely the fault of the slow listview control. You should look at the LVM_SETITEMCOUNT message:
QuoteThe LVM_SETITEMCOUNT message prepares a list view control for adding a large number of items.

Nice work, keep going :thumbsup:

TimoVJL

ml.exe Macro Assembler Version 14.30.30705.0
Microsoft (R) Macro Assembler Version 14.30.30705.0
Copyright (C) Microsoft Corporation.  All rights reserved.

Assembling: test1.asm

***********
ASCII build
***********

\masm32\include\winextra.inc(11052) : error A2026:constant expected
\masm32\include\winextra.inc(11053) : error A2026:constant expected
May the source be with you

jj2007

Here is a minimally modified version that assembles fine.

TimoVJL

May the source be with you

jj2007

Thanks, Timo. I don't see any difference, though :rolleyes:

NoCforMe

Quote from: jj2007 on July 14, 2022, 10:23:06 PM
Another design point: Your application allows to find
- all \Masm32\include\*.inc files
- all \Masm32\include\ files that contain the string "crt_"
- but not all \Masm32\include\*.inc files that contain the string "crt_"
Just this one small point: Are you saying you'd like to see a filename qualifier (.inc) and a text search term? In other words, limit the file text search to a certain subset of files? I could do that.
Assembly language programming should be fun. That's why I do it.

NoCforMe

Quote from: jj2007 on July 14, 2022, 10:23:06 PM
I'd like to build your source, but... (inter alia, it expects a resource file not included in the archive):

Microsoft (R) Windows Resource To Object Converter Version 5.00.1736.1
Copyright (C) Microsoft Corp. 1992-1997. All rights reserved.

CVTRES : fatal error CVT1101: cannot open FindIt!_res.res for reading

Whoops, sorry, my bad: I included my other resource file (compiled) in the archive. Haven't quite standardized here at NoCforMe Laboratories, GmbH yet.
Quote
Assembling: FindIt!.asm

***********
ASCII build
***********

FindIt!.asm(73) : error A2008:syntax error : PROTO
strcat(17): Macro Called From
  FindIt!.asm(73): Main Line Code
FindIt!.asm(970) : error A2148:invalid symbol type in expression : strcat
FindIt!.asm(971) : error A2148:invalid symbol type in expression : strcat
FindIt!.asm(1117) : error A2148:invalid symbol type in expression : strcat
FindIt!.asm(1118) : error A2148:invalid symbol type in expression : strcat
FindIt!.asm(1210) : error A2148:invalid symbol type in expression : strcat
FindIt!.asm(1211) : error A2148:invalid symbol type in expression : strcat
FindIt!.asm(1404) : error A2148:invalid symbol type in expression : strcat
FindIt!.asm(1847) : error A2006:undefined symbol : dest
strcat(17): Macro Called From
  FindIt!.asm(1847): Main Line Code
Also my bad; I use my own include file, my_masm32rt.inc, which omits macros (I just don't use 'em). I have a subroutine named "strcat".

I have another problem with the stock file (masm32rt.inc): why doesn't it include a .nolist/.list pair? Have you seen the huge listing files you get if you don't do that? Whose idea was that?

Updated archive attached here.
Assembly language programming should be fun. That's why I do it.

jj2007

Quote from: NoCforMe on July 15, 2022, 04:43:14 AMI have a subroutine named "strcat".

Which happens to be a standard C function. I had to rename it to strcatx to assemble your source.

Quote from: NoCforMe on July 15, 2022, 04:36:56 AMAre you saying you'd like to see a filename qualifier (.inc) and a text search term? In other words, limit the file text search to a certain subset of files? I could do that.

Exactly. Imagine you want to see all *.inc files that contain the string crt_ - but your routine has to load and scan also some gigabytes of *.bmp and *.wav files that happen to be in the same folder... not very efficient, right?

This is how GetFiles does it, searching for include files that contain the string "Winsock":

GetFiles \Masm32\include\*.inc, "Winsock", 1, 1        ; 1 = return first match only, 1 = case-insensitive

0                 \Masm32\include\dnsapi.inc
1                 \Masm32\include\mswsock.inc
2                 \Masm32\include\windows.inc
3                 \Masm32\include\windows64.inc
4                 \Masm32\include\wshisotp.inc
5                 \Masm32\include\wsock32.inc

NoCforMe

Quote from: jj2007 on July 15, 2022, 05:12:27 AM
Quote from: NoCforMe on July 15, 2022, 04:43:14 AMI have a subroutine named "strcat".

Which happens to be a standard C function. I had to rename it to strcatx to assemble your source.
I renamed it to "_strcat" in my source. These utility functions are always a problem, name-wise.

Quote
Quote from: NoCforMe on July 15, 2022, 04:36:56 AMAre you saying you'd like to see a filename qualifier (.inc) and a text search term? In other words, limit the file text search to a certain subset of files? I could do that.

Exactly. Imagine you want to see all *.inc files that contain the string crt_ - but your routine has to load and scan also some gigabytes of *.bmp and *.wav files that happen to be in the same folder... not very efficient, right?
It's on my list for the next revision.
Assembly language programming should be fun. That's why I do it.

FORTRANS

Hi,

Quote from: NoCforMe on July 15, 2022, 04:43:14 AM
I have another problem with the stock file (masm32rt.inc): why doesn't it include a .nolist/.list pair? Have you seen the huge listing files you get if you don't do that? Whose idea was that?

   Just put the directives in where you include the file.

; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
        .XCREF
        .XLIST
INCLUDE  MASM32RT.INC
        .LIST
        .CREF

; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -


   Easy, and you can leave the directives out if you need a listing.

Cheers,

Steve N.

NoCforMe

But who would ever need a listing of that file? All you gotta do is open it in your editor if you want to see what's in it. No need to ever list it that I can see.

BTW, that's what I do when I do use that file. This is one of the very few complaints I have about this otherwise exemplary and useful package.
Assembly language programming should be fun. That's why I do it.

NoCforMe

Quote from: jj2007 on July 15, 2022, 05:12:27 AM
Quote from: NoCforMe on July 15, 2022, 04:36:56 AMAre you saying you'd like to see a filename qualifier (.inc) and a text search term? In other words, limit the file text search to a certain subset of files? I could do that.

Exactly. Imagine you want to see all *.inc files that contain the string crt_ - but your routine has to load and scan also some gigabytes of *.bmp and *.wav files that happen to be in the same folder... not very efficient, right?

This is how GetFiles does it, searching for include files that contain the string "Winsock":

GetFiles \Masm32\include\*.inc, "Winsock", 1, 1        ; 1 = return first match only, 1 = case-insensitive

0                 \Masm32\include\dnsapi.inc
1                 \Masm32\include\mswsock.inc
2                 \Masm32\include\windows.inc
3                 \Masm32\include\windows64.inc
4                 \Masm32\include\wshisotp.inc
5                 \Masm32\include\wsock32.inc


I hear and I obey. New version attached. A blank "Filenames to match" means "all files".

I thought of another possible design change: how 'bout if the current folder field was an edit control so you could type the path in directly instead of having to use the Select Folder dialog?
Assembly language programming should be fun. That's why I do it.