Announcement

Collapse

Forum Guidelines

This forum is for finished source code that is working properly. If you have questions about this or any other source code, please post it in one of the Discussion Forums, not here.
See more
See less

Scan directories

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • Scan directories

    In the following posts you will find 2 versions of ScanDir.inc.
    The following examples are based on ScanDir.inc version 2.
    In the last post you find ScanDir.inc version 3. The parameters
    in the user-defined callback-function is changed in this version.


    The ScanDir function scans directories. The criteria of the scan is defined by a user-defined callback function.
    The following 2 examples use the include-file "scandir.inc". This file is given in the next post.

    Regards
    Peter

    Example 1
    Code:
    #COMPILE EXE
    #INCLUDE "win32api.inc"
    #INCLUDE "ScanDir.inc"
        
    GLOBAL PathHit AS STRING
        
    ' User-defined callback function defining the criteria of the scan
    FUNCTION ScanFunc(BYVAL File AS STRING, BYVAL Path AS STRING) AS LONG
        
        IF LCASE$(File) = "win32api.inc" THEN
            PathHit = Path
            FUNCTION = %SCAN_END  ' If find file: end scan
        END IF
        
    END FUNCTION
        
    FUNCTION PBMAIN
         
        ScanDir "c:", CODEPTR(ScanFunc), %TRUE
        MSGBOX PathHit
        
    END FUNCTION
    Example 2
    Code:
    #COMPILE EXE
    #INCLUDE "win32api.inc"
    #INCLUDE "ScanDir.inc"
        
    GLOBAL FileHit() AS STRING
    GLOBAL i AS LONG
        
    ' User-defined callback function defining the criteria of the scan
    FUNCTION ScanFunc(BYVAL File AS STRING, BYVAL Path AS STRING) AS LONG
       
        IF INSTR(LCASE$(File),".exe") THEN
            FileHit(i) = Path & "\" & File
            INCR i
        END IF
        
    END FUNCTION
        
    FUNCTION PBMAIN
        
        LOCAL n AS LONG
        LOCAL hDlg AS LONG
        REDIM FileHit(10000)
        
        ScanDir "c:", CODEPTR(ScanFunc), %TRUE
        
        REDIM PRESERVE FileHit(i)
        
        DIALOG NEW 0, "Number of files: " & FORMAT$(i+1),,,200, 200, %WS_SYSMENU OR %DS_CENTER TO hDlg
        CONTROL ADD LISTBOX, hDlg, 100, FileHit(), 0,0,197,200, %WS_VSCROLL, %WS_EX_CLIENTEDGE
        DIALOG SHOW MODAL hDlg
        
    END FUNCTION


    [This message has been edited by Peter P Stephensen (edited August 29, 2001).]
    [email protected]
    www.dreammodel.dk

  • #2
    Code:
    ' SCANDIR.INC Version 2 
    '---------------------------------------------------------------------------------------------------------
    '
    '   The ScanDir function scans directories. The criteria of the scan is defined by a user-defined callback
    '   function.
    '
    '   Function ScanDir(BYVAL StartDir AS STRING, BYVAL lpfnCallback AS LONG, BYVAL bSubDir AS LONG) AS LONG
    '
    '   Parameters:
    '
    '       StartDir       Directory from which the scan starts
    '       lpfnCallback   Address of user-defined callback function (see below)
    '       bSubDir        Specifies whether sub-directories should be included in the scan. If %TRUE (1) the
    '                      sub-directories are included. If %FALSE (0) the sub-directories are not included.
    '
    '---------------------------------------------------------------------------------------------------------
    '
    '   Uder-defined callback function:
    '
    '   Function ScanCallback (BYVAL File AS STRING, BYVAL Path AS STRING) AS LONG
    '
    '   Parameters:
    '
    '       File           Filename without path (e.g. "win32api.inc")
    '       Path           The path (e.g. "c:\pbdll60\winapi")
    '
    '   Return value
    '
    '       No value should be returned except when halting the scan. Returning %SCAN_END implies
    '       that the scan stops.
    '
    '---------------------------------------------------------------------------------------------------------
      
    #IF NOT %DEF(%SCANDIR_INC)
    %SCANDIR_INC = 1
      
    DECLARE FUNCTION ScanCallback (BYVAL File AS STRING, BYVAL Path AS STRING) AS LONG
      
    GLOBAL lpfnCallback_Global AS DWORD
    GLOBAL bSubDir_Global AS LONG
      
    %SCAN_END = -1
      
    %START_MEM = 100
    %ADD_MEM = 100
      
    FUNCTION EnumDirs(BYVAL ParentDir AS STRING, Dirs() AS STRING) AS LONG
      
        LOCAL i AS LONG
        LOCAL wfd AS WIN32_FIND_DATA
        LOCAL hFile  AS LONG
        LOCAL CallbackResult AS LONG
        LOCAL n AS LONG
       
        n = %START_MEM
      
        hFile = FindFirstFile(ParentDir & "\*.*", wfd)
        IF hFile = %INVALID_HANDLE_VALUE THEN EXIT FUNCTION
        CALL DWORD lpfnCallback_Global USING ScanCallback(wfd.cFileName, ParentDir) TO CallbackResult
        IF CallbackResult = %SCAN_END THEN
            FindClose hFile        
            FUNCTION = %SCAN_END 
            EXIT FUNCTION
        END IF
      
        DO
            IF (wfd.dwFileAttributes AND %FILE_ATTRIBUTE_DIRECTORY) AND LEFT$(wfd.cFileName,1) <> "." THEN
                Dirs(i) = TRIM$(wfd.cFileName)
                INCR i
                IF i = n THEN
                    n = n + %ADD_MEM
                    REDIM PRESERVE Dirs(n)
                END IF
            END IF
            IF FindNextFile(hFile, wfd) = 0 THEN EXIT DO
            CALL DWORD lpfnCallback_Global USING ScanCallback(wfd.cFileName, ParentDir) TO CallbackResult
            IF CallbackResult = %SCAN_END THEN
                FindClose hFile
                FUNCTION = %SCAN_END 
                EXIT FUNCTION
            END IF
        LOOP
     
        FindClose hFile 
        FUNCTION = i
      
    END FUNCTION
      
    FUNCTION DoScanDir(BYVAL ParentDir AS STRING) AS LONG
      
        DIM Dirs(%START_MEM) AS LOCAL STRING
        LOCAL n AS LONG
        LOCAL i AS LONG
      
        n = EnumDirs(ParentDir, Dirs())
        IF n = %SCAN_END THEN
            ERASE Dirs : EXIT FUNCTION
        END IF
      
        IF bSubDir_Global THEN
            FOR i = 0 TO n-1
                DoScanDir ParentDir & "\" & Dirs(i)
            NEXT i
        END IF
      
        ERASE Dirs
        FUNCTION = 1
      
    END FUNCTION
      
    FUNCTION ScanDir(BYVAL StartDir AS STRING, BYVAL lpfnCallback AS LONG, BYVAL bSubDir AS LONG) AS LONG
      
        lpfnCallback_Global = lpfnCallback
        bSubDir_Global = bSubDir
        DoScanDir StartDir
      
        FUNCTION = 1
      
    END FUNCTION
    #ENDIF
    ------------------


    [This message has been edited by Peter P Stephensen (edited March 25, 2000).]
    [email protected]
    www.dreammodel.dk

    Comment


    • #3
      Another example:
      Example 3
      Code:
      #COMPILE EXE
      #INCLUDE "win32api.inc"
      #INCLUDE "ScanDir.inc"
       
      GLOBAL FileHit() AS STRING
      GLOBAL i AS LONG
      GLOBAL gPath AS STRING
      GLOBAL gEndThreadFlag AS LONG
       
      %IDC_LAB = 100
       
      ' User-defined callback function defining the criteria of the scan
      FUNCTION ScanFunc(BYVAL File AS STRING, BYVAL Path AS STRING) AS LONG
       
          gPath = Path
       
          IF INSTR(LCASE$(File),".exe") THEN
              FileHit(i) = Path & "\" & File
              INCR i
          END IF
       
      END FUNCTION
       
      FUNCTION InitDlg(BYVAL x AS LONG) AS LONG
       
          LOCAL hDlg AS LONG
       
          DIALOG NEW 0, "Scanning directories...",,,300, 30, %DS_CENTER, %WS_EX_TOOLWINDOW TO hDlg
          CONTROL ADD LABEL, hDlg, %IDC_LAB, "", 5,5,280,15
          DIALOG SHOW MODELESS hDlg
       
          DO
              IF gEndThreadFlag THEN EXIT LOOP
              CONTROL SET TEXT hDlg, %IDC_LAB, gPath
              SLEEP 20
              DIALOG DOEVENTS
          LOOP
       
          DIALOG END hDlg
       
      END FUNCTION
       
      FUNCTION PBMAIN
       
          LOCAL hDlg AS LONG
          REDIM FileHit(10000)
       
          THREAD CREATE InitDlg(0) TO h& :THREAD CLOSE h& TO r&
          ScanDir "e:", CODEPTR(ScanFunc), %TRUE
          gEndThreadFlag = %TRUE
       
          REDIM PRESERVE FileHit(i)
       
          DIALOG NEW 0, "Number of files: " & FORMAT$(i+1),,,200, 200, %WS_SYSMENU OR %DS_CENTER OR %DS_SETFOREGROUND TO hDlg
          CONTROL ADD LISTBOX, hDlg, 100, FileHit(), 0,0,197,200, %WS_VSCROLL, %WS_EX_CLIENTEDGE
          DIALOG SHOW MODAL hDlg
       
      END FUNCTION

      ------------------
      [email protected]
      www.dreammodel.dk

      Comment


      • #4
        I forgot FindClose in the ScanDir.inc. It is changed now.

        Regards
        Peter

        ------------------
        [email protected]
        www.dreammodel.dk

        Comment


        • #5
          A question from Gregery D Engle made me realize that a more
          general formulation of ScanDir.inc could speed up some scan's.
          Here is version 3:

          Code:
          ' SCANDIR.INC Version 3 
          ' Change from version 2: The parameters in ScanCallback is changed to wfd AS WIN32_FIND_DATA.
          '                        This type has all the informations you need incl. file name and size.
          '
          '---------------------------------------------------------------------------------------------------------
          '
          '   The ScanDir function scans directories. The criteria of the scan is defined by a user-defined callback
          '   function.
          '
          '   Function ScanDir(BYVAL StartDir AS STRING, BYVAL lpfnCallback AS LONG, BYVAL bSubDir AS LONG) AS LONG
          '
          '   Parameters:
          '
          '       StartDir       Directory from which the scan starts
          '       lpfnCallback   Address of user-defined callback function (see below)
          '       bSubDir        Specifies whether sub-directories should be included in the scan. If %TRUE (1) the
          '                      sub-directories are included. If %FALSE (0) the sub-directories are not included.
          '
          '---------------------------------------------------------------------------------------------------------
          '
          '   Uder-defined callback function:
          '
          '   Function ScanCallback (wfd AS WIN32_FIND_DATA) AS LONG
          '
          '   Parameter: The name of the file can be found using wfd.cFileName
          '              The size of the file can be found using wfd.nFileSizeLow
          '
          '    Return value
          '
          '       No value should be returned except when halting the scan. Returning %SCAN_END implies
          '       that the scan stops.
          '
          '---------------------------------------------------------------------------------------------------------
             
          #IF NOT %DEF(%SCANDIR_INC)
          %SCANDIR_INC = 1
             
          DECLARE FUNCTION ScanCallback (wfd AS WIN32_FIND_DATA) AS LONG
             
          GLOBAL lpfnCallback_Global AS DWORD
          GLOBAL bSubDir_Global AS LONG
             
          %SCAN_END = -1
             
          %START_MEM = 100
          %ADD_MEM = 100
             
          FUNCTION EnumDirs(BYVAL ParentDir AS STRING, Dirs() AS STRING) AS LONG
             
              LOCAL i AS LONG
              LOCAL wfd AS WIN32_FIND_DATA
              LOCAL hFile  AS LONG
              LOCAL CallbackResult AS LONG
              LOCAL n AS LONG
              
              n = %START_MEM
             
              hFile = FindFirstFile(ParentDir & "\*.*", wfd)
              IF hFile = %INVALID_HANDLE_VALUE THEN EXIT FUNCTION
              CALL DWORD lpfnCallback_Global USING ScanCallback(wfd) TO CallbackResult
              IF CallbackResult = %SCAN_END THEN
                  FindClose hFile        
                  FUNCTION = %SCAN_END 
                  EXIT FUNCTION
              END IF
             
              DO
                  IF (wfd.dwFileAttributes AND %FILE_ATTRIBUTE_DIRECTORY) AND LEFT$(wfd.cFileName,1) <> "." THEN
                      Dirs(i) = TRIM$(wfd.cFileName)
                      INCR i
                      IF i = n THEN
                          n = n + %ADD_MEM
                          REDIM PRESERVE Dirs(n)
                      END IF
                  END IF
                  IF FindNextFile(hFile, wfd) = 0 THEN EXIT DO
                  CALL DWORD lpfnCallback_Global USING ScanCallback(wfd) TO CallbackResult
                  IF CallbackResult = %SCAN_END THEN
                      FindClose hFile
                      FUNCTION = %SCAN_END 
                      EXIT FUNCTION
                  END IF
              LOOP
            
              FindClose hFile 
              FUNCTION = i
             
          END FUNCTION
             
          FUNCTION DoScanDir(BYVAL ParentDir AS STRING) AS LONG
             
              DIM Dirs(%START_MEM) AS LOCAL STRING
              LOCAL n AS LONG
              LOCAL i AS LONG
             
              n = EnumDirs(ParentDir, Dirs())
              IF n = %SCAN_END THEN
                  ERASE Dirs : EXIT FUNCTION
              END IF
             
              IF bSubDir_Global THEN
                  FOR i = 0 TO n-1
                      DoScanDir ParentDir & "\" & Dirs(i)
                  NEXT i
              END IF
             
              ERASE Dirs
              FUNCTION = 1
             
          END FUNCTION
             
          FUNCTION ScanDir(BYVAL StartDir AS STRING, BYVAL lpfnCallback AS LONG, BYVAL bSubDir AS LONG) AS LONG
             
              lpfnCallback_Global = lpfnCallback
              bSubDir_Global = bSubDir
              DoScanDir StartDir
             
              FUNCTION = 1
             
          END FUNCTION
          #ENDIF
          ------------------
          [email protected]
          [email protected]
          www.dreammodel.dk

          Comment


          • #6
            Here is an example using version 3 (calculating size of folder):

            Code:
            #compile exe
            #include "win32api.inc"
            #include "ScanDir.inc"  
             
            $TargetFolder = "c:\winnt" 
            global FolderSize as ext
               
            ' User-defined callback function defining the criteria of the scan
            function ScanFunc(wfd AS WIN32_FIND_DATA) as long
                FolderSize = FolderSize + wfd.nFileSizeLow
            end function
              
            function pbmain
                ScanDir $TargetFolder, codeptr(ScanFunc), %TRUE
                msgbox "Size of folder '" + $TargetFolder + "' is " + format$(FolderSize) + " bytes"
            end function
            ------------------
            [email protected]

            [This message has been edited by Peter P Stephensen (edited August 29, 2001).]
            [email protected]
            www.dreammodel.dk

            Comment

            Working...
            X