Sign in to follow this  
Followers 0
Xajar

Need help making _singleton wait on second occurrence

5 posts in this topic

I'm having some problems with a script I made to collect all the files and sub folders within a folder. When I use _Singleton to allow only one occurrence, the arguments pass but the first occurrence doesn't wait for the other occurrences to finish the recursive file search. I want to pause the script till the list of files is finished being gathered before enabling controls. Any help would be appreciated.

Here is the code in question and another script to add/remove support for right-clicking on folders.

Build List.au3

#include <GUIConstants.au3>
#include <GuiList.au3>
#include <Misc.au3>

;~ Passes the command line arguments to the first occurrence
If _Singleton( 'Build List',1 ) = 0 Then
    If $CmdLineRaw <> '' Then
        If IsFolder( $CmdLineRaw ) Then
            ScanFolders( $CmdLineRaw )
        Else
            ControlCommand( 'AForm1','','ListBox1','AddString', FileGetLongName($CmdLineRaw) )
        EndIf
    EndIf
    Exit
EndIf

;~ Creates the GUI
$Form1 = GUICreate("AForm1", 633, 233, 193, 115)
    $List1 = GUICtrlCreateList("", 8, 8, 617, 188)
    $Button1 = GUICtrlCreateButton("AButton1", 8, 200, 81, 25, 0)
    GUICtrlSetState( -1,$GUI_DISABLE )
GUISetState(@SW_SHOW)

;~ Parses the command line arguments
For $i = 1 To $CmdLine[0]
    If IsFolder( $CmdLine[$i] ) Then
        ScanFolders( $CmdLine[$i] )
    Else
        ControlCommand( 'AForm1','','ListBox1','AddString', FileGetLongName($CmdLine[$i]) )
    EndIf
Next

;~ I need the script to wait for the list to finish
MsgBox( '','Here is the problem',"I don't want to see this untill all the occurrences have passed their arguments and the file list is complete..." )
GUICtrlSetState( $Button1,$GUI_ENABLE )

While 1
    $nMsg = GUIGetMsg()
    Switch $nMsg
        Case $GUI_EVENT_CLOSE
            Exit
    EndSwitch
WEnd

;~ Gathers the folders/files and stores them in the listbox
Func ScanFolders( $Path )
    local $fileHandle, $file, $dirHandle, $dir
    local const $FILESPEC = "*.*"
    $fileHandle = fileFindFirstFile( $path & "\" & $FILESPEC )
    If $fileHandle <> -1 Then
        while ( 1 )
            $file = fileFindNextFile( $fileHandle )
            If @error = 1 Then exitLoop
            If $file = "." or $file = ".." Then continueLoop
            $file = $path & "\" & $file
            If isFolder( $file ) Then continueLoop
            ControlCommand( 'AForm1','','ListBox1','AddString', FileGetLongName($file) )
        wEnd
        fileClose( $fileHandle )
    EndIf
    $dirHandle = fileFindFirstFile( $path & "\*.*" )
    If $dirHandle <> -1 Then
        while ( 1 )
            $dir = fileFindNextFile( $dirHandle )
            If @error = 1 Then exitLoop
            If $dir = "." or $dir = ".." Then continueLoop
            $dir = $path & "\" & $dir
            If not( IsFolder($dir) ) Then continueLoop
            ScanFolders( $dir )
        wEnd
        fileClose( $dirHandle )
    EndIf
EndFunc

;~ Checks if a path is a folder or file
Func IsFolder( $Path )
    If stringInStr( fileGetAttrib($Path), "D" ) Then Return 1
    Return 0
EndFunc

Add Right Click Support.au3

#include <GUIConstants.au3>

#Region ### START Koda GUI section ### Form=C:\Documents and Settings\Xajar\Desktop\RSA Encryption\xCrypter_Setup.kxf
    $Form1 = GUICreate("Right-Click Setup", 186, 50, 193, 115)

    $Label2 = GUICtrlCreateLabel("Right-Click On Folder Option", 8, 8, 138, 17)
    
    $btn_add_folder = GUICtrlCreateButton("Add", 8, 25, 81, 21, 0)
    $btn_remove_folder = GUICtrlCreateButton("Remove", 96, 25, 81, 21, 0)
GUISetState(@SW_SHOW)
#EndRegion ### END Koda GUI section ###

While 1
    $Msg = GUIGetMsg()
    Switch $Msg
        Case $GUI_EVENT_CLOSE
            Exit
        Case $btn_add_folder
            RegWrite("HKEY_CLASSES_ROOT\Folder\shell\Build List...\Command", "", "REG_SZ", @ScriptDir & '\build list.exe %1')
        Case $btn_remove_folder
            RegDelete ( "HKEY_CLASSES_ROOT\Folder\shell\Build List..." )
    EndSwitch
WEnd

Share this post


Link to post
Share on other sites



#2 ·  Posted (edited)

Recursion should not require calling a script in a new process over and over. That is really going to be slow and eat resources. Recursion should be done by a function calling itself.

Here is one of many examples on this forum. This one happens to have been written by a particularly good looking flightless water fowl...

:)

P.S. On closer examination, you already have your ScanFolders() function calling itself for recursion, so what are the conditions calling the script repeatedly?

:)

Edited by PsaltyDS

Valuater's AutoIt 1-2-3, Class... Is now in Session!For those who want somebody to write the script for them: RentACoder"Any technology distinguishable from magic is insufficiently advanced." -- Geek's corollary to Clarke's law

Share this post


Link to post
Share on other sites

The problem with the above code I posted was when I tried to highlight multiple folders to be passed into a sub folder/file search through a right click on folders/files. Once the first occurrence finished searching the controls become enabled while the other occurrences were still adding files to the file list being built.

Share this post


Link to post
Share on other sites

The problem with the above code I posted was when I tried to highlight multiple folders to be passed into a sub folder/file search through a right click on folders/files. Once the first occurrence finished searching the controls become enabled while the other occurrences were still adding files to the file list being built.

I get it now. You are creating a right-click context for folders called "Build List...". If you have more than one object selected when you use it, it kicks off one instance for each object, but you want them all to aggregate the results.

I would use _Singleton() at the very top of the script. If this is the only instance, then this instance becomes master and is responsible for creating the aggregation GUI.

Later instances of the same script would see that they are not the master because of _Singleton(), and would know to only update the master GUI, not create one themselves.

The master instance will know it's done when _Singleton() is run again and indicates it is the only instance left. So all the master has to do is create the GUI update it from its own command line arguments, then after a minimal time delay wait for it to be the only one left. All the late-comer instances have to do is update the master's GUI and exit.

Make sense?

:)


Valuater's AutoIt 1-2-3, Class... Is now in Session!For those who want somebody to write the script for them: RentACoder"Any technology distinguishable from magic is insufficiently advanced." -- Geek's corollary to Clarke's law

Share this post


Link to post
Share on other sites

Thanks, I was able to get it. This is what I came up with.

#NoTrayIcon

#include <GUIConstants.au3>
#include <GuiList.au3>
#include <Misc.au3>
#include <Array.au3>
#include <File.au3>

Global $Wait = False
Global $Title = 'AForm1'

;~ Passes the command line arguments to the first occurrence
If _Singleton( 'Build List',1 ) = 0 Then;Second occurrence
    If $CmdLineRaw <> '' Then
        $Wait = True
        DisableControls()
        
        If IsFolder( $CmdLineRaw ) Then
            ScanFolders( $CmdLineRaw )
        Else
            ControlCommand( $Title,'','ListBox1','AddString', FileGetLongName($CmdLineRaw) )
        EndIf
        
        $Wait = False
        
        SetTimeOut()
    EndIf
    Exit
Else;First occurrence
;~ Creates the GUI
    $Form1 = GUICreate("AForm1", 633, 233, 193, 115)
        $List1 = GUICtrlCreateList("", 8, 8, 617, 188)
        $Button1 = GUICtrlCreateButton("AButton1", 8, 200, 81, 25, 0)
        GUICtrlSetState( -1,$GUI_DISABLE )
    GUISetState(@SW_SHOW)
    
;~ Parses the command line arguments
    For $i = 1 To $CmdLine[0]
        
        If IsFolder( $CmdLine[$i] ) Then
            ScanFolders( $CmdLine[$i] )
        Else
            ControlCommand( $Title,'','ListBox1','AddString', FileGetLongName($CmdLine[$i]) )
        EndIf
        
    Next
EndIf

EnableControls()

While 1
    $nMsg = GUIGetMsg()
    Switch $nMsg
        Case $GUI_EVENT_CLOSE
            Exit
    EndSwitch
WEnd

Func SetTimeOut()
    If $Wait = False Then
        Sleep( 10000 )
        EnableControls()
    EndIf
EndFunc

Func EnableControls()
    If $Wait = False Then
        ControlEnable( 'AForm1','','Button1' )
    EndIf
EndFunc

Func DisableControls()
    ControlDisable( 'AForm1','','Button1' )
EndFunc

;~ Checks if a path is a folder or file
Func IsFolder( $Path )
    If stringInStr( fileGetAttrib($Path), "D" ) Then Return 1
    Return 0
EndFunc

Func ScanFolders($Path)
    
    local $fileHandle, $file, $dirHandle, $dir
    local const $FILESPEC = "*.*"
    $fileHandle = fileFindFirstFile( $path & "\" & $FILESPEC )
    If $fileHandle <> -1 Then
        while ( 1 )
            $file = fileFindNextFile( $fileHandle )
            If @error = 1 Then exitLoop
            If $file = "." or $file = ".." Then continueLoop
            $file = $path & "\" & $file
            If isFolder( $file ) Then continueLoop
            ControlCommand( $Title,'','ListBox1','AddString', FileGetLongName($file) )
        wEnd
        fileClose( $fileHandle )
    EndIf
    $dirHandle = fileFindFirstFile( $path & "\*.*" )
    If $dirHandle <> -1 Then
        while ( 1 )
            $dir = fileFindNextFile( $dirHandle )
            If @error = 1 Then exitLoop
            If $dir = "." or $dir = ".." Then continueLoop
            $dir = $path & "\" & $dir
            If not( IsFolder($dir) ) Then continueLoop
            ScanFolders( $dir )
        wEnd
        fileClose( $dirHandle )
    EndIf
    
EndFunc

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now
Sign in to follow this  
Followers 0