Page 1 of 1

directory library issue.

Posted: Sat Jan 28, 2017 4:24 am
by Damion12
I have been getting this error a lot lately. I think it has something to do with calling it too fast or too many times -- but honestly, I have been unable to distill down the bare essence of what triggers it to happen.

Suffice it to say:

Code: Select all

  DirID = ExamineDirectory(#PB_Any, FQpath, "*.*")  ; FQpath is a full path ie: C:\ or F:\music and does exist.
  If DirID 
      While NextDirectoryEntry(DirID) ; << this line generates: [ERROR] The specified #Directory is Not initialised.
Image
I have seen it happen in other people's code as well as my own.
Any ideas on what could be going on or how to work around it?

Re: directory library issue.

Posted: Sat Jan 28, 2017 6:05 am
by Keya
show the full While/Wend loop, i wonder if there's something you're doing in the middle throwing it off

Re: directory library issue.

Posted: Sat Jan 28, 2017 8:40 am
by Fred
Yes, always post a full snippet showing the error or we won't be able to investigate

Re: directory library issue.

Posted: Sat Jan 28, 2017 10:45 am
by mk-soft
No problem with Windows and Mac (PB x64)

Code: Select all

;Directory$ = GetHomeDirectory()
Directory$ = "c:"
;Directory$ = "f:"
;Directory$ = "/"
DirID = ExamineDirectory(#PB_Any, Directory$, "*.*")
If DirID
  While NextDirectoryEntry(DirID)
    If DirectoryEntryType(DirID) = #PB_DirectoryEntry_File
      Type$ = "[File] "
      Size$ = " (Size: " + DirectoryEntrySize(DirID) + ")"
    Else
      Type$ = "[Directory] "
      Size$ = "" ; A directory doesn't have a size
    EndIf
    
    Debug Type$ + DirectoryEntryName(DirID) + Size$
  Wend
  FinishDirectory(DirID)
EndIf

Re: directory library issue.

Posted: Sat Jan 28, 2017 12:21 pm
by Dude
In your screenshot, you've got \Dir as the directory name. Why not a string?

Image

Re: directory library issue.

Posted: Sat Jan 28, 2017 12:50 pm
by nco2k
also there is a memory leak. you use ProcedureReturn without calling FinishDirectory() first. but its really hard to tell whats causing your IMA, without the complete code.

c ya,
nco2k

Re: directory library issue.

Posted: Sat Jan 28, 2017 4:07 pm
by #NULL
me too thought WTF is \Dir, but it is probably a structure field inside a block of With/EndWith.

<edit>
what is the type of DirID?
do you use Enable/DisableDebugger? does the error disappear when compiling without debugger?

Re: directory library issue.

Posted: Sat Jan 28, 2017 7:36 pm
by Damion12
It happens on Entry into the loop -- so
dir = ExamineDirectory( ... )
if dir
while NextDirectoryEntry( dir ) << error

the rest of code never gets executed...
but, this is code, exactly, as I got off the forums, as an example....
(I pick "C:\" when prompted; takes a little bit, then generates it)

Code: Select all

; Watch a folder and all subfolder for changes
; dige 5/2008
; Compile with ThreadSafe enabled!!

; #FILE_NOTIFY_CHANGE_FILE_NAME
; #FILE_NOTIFY_CHANGE_DIR_NAME
; #FILE_NOTIFY_CHANGE_ATTRIBUTES
; #FILE_NOTIFY_CHANGE_SIZE
; #FILE_NOTIFY_CHANGE_LAST_WRITE
; #FILE_NOTIFY_CHANGE_SECURITY

Structure WatchFolder
  Dir.s
  WaitMillisecs.l
  hChngObject.l
  ThreadID.l
  Flag.b
EndStructure

Structure FileList
  FileName.s
  FileSize.l
  Date_Created.l
  Date_Accessed.l
  Date_Modified.l
  Flag.b
EndStructure

Global NewList WF.WatchFolder()

Procedure   DragNDropFile()
  Protected File.s, Result.s
  
  For i = 0 To CountGadgetItems(1)-1
    If GetGadgetItemState(1, i) & #PB_ListIcon_Selected
      File = GetGadgetItemText(1, i)
      File = Trim(StringField( File, 2, ">" ))
      If File : Result + File + Chr(10) : EndIf
    EndIf
  Next i 
  
  If Result : DragFiles(Result) : EndIf
  
EndProcedure
Procedure   DoWatchFolder(*WF.WatchFolder)
  Protected NewList FL.FileList(), DirID.l, Found.b, File.s, Count.l
  
  Macro GetFileStuff
    FL()\FileSize      = FileSize (FL()\FileName)
    FL()\Date_Created  = GetFileDate( FL()\FileName, #PB_Date_Created )
    FL()\Date_Accessed = GetFileDate( FL()\FileName, #PB_Date_Accessed )
    FL()\Date_Modified = GetFileDate( FL()\FileName, #PB_Date_Modified )
  EndMacro
  
  
  With *WF
    DirID = ExamineDirectory(#PB_Any, \Dir, "*.*")  
    ; Add files
    If DirID 
    	If IsDirectory(dirid)
      While NextDirectoryEntry(DirID)
        If DirectoryEntryType(DirID) = #PB_DirectoryEntry_File
          If AddElement( FL() )
            FL()\FileName      = \Dir + "\" + DirectoryEntryName(DirID)
            GetFileStuff
          Else
            ProcedureReturn
          EndIf
        EndIf
      Wend
    Else 
    	CallDebugger
    EndIf
      FinishDirectory(DirID)
    EndIf
    
    While \Flag = 0
      \hChngObject=FindFirstChangeNotification_(\Dir, #Null, #FILE_NOTIFY_CHANGE_FILE_NAME|#FILE_NOTIFY_CHANGE_SIZE|#FILE_NOTIFY_CHANGE_LAST_WRITE)
      
      If WaitForSingleObject_(\hChngObject, \WaitMillisecs) = 0
        Count = 0
        Repeat
          DirID = ExamineDirectory(#PB_Any, \Dir, "*.*")  
          ; check files
          If DirID
            ForEach FL()
              FL()\Flag = 0
            Next
            
            While NextDirectoryEntry(DirID)
              If DirectoryEntryType(DirID) = #PB_DirectoryEntry_File
                Found = #False
                ForEach FL()
                  If FL()\FileName = \Dir + "\" + DirectoryEntryName(DirID)
                    Found = 1
                    
                    If FL()\FileSize <> FileSize (FL()\FileName) : Found = 2 : EndIf
                    If FL()\Date_Created <> GetFileDate( FL()\FileName, #PB_Date_Created )   : Found = 3 : EndIf
                    If FL()\Date_Accessed <> GetFileDate( FL()\FileName, #PB_Date_Accessed ) : Found = 4 : EndIf
                    If FL()\Date_Modified <> GetFileDate( FL()\FileName, #PB_Date_Modified ) : Found = 5 : EndIf
                    
                    File = FL()\FileName
                    GetFileStuff
                    FL()\Flag = Found
                  
                    Break
                  EndIf
                Next
                
                File = ""
                
                If Not Found
                  If AddElement( FL() )
                    FL()\FileName      = \Dir + "\" + DirectoryEntryName(DirID)
                    FL()\FileSize      = FileSize (FL()\FileName)
                    GetFileStuff
                    File = FL()\FileName
                    FL()\Flag = 6
                    Found = 6     ; New File
                  EndIf
                EndIf
              EndIf
              
              If File
                Select Found
                  Case 2     : File = "NewFileSize > " + File
                  Case 3,4,5 : File = "NewDate > " + File
                  Case 6     : File = "NewFile > " + File
                EndSelect
                
                If Found <> 1 : Count + 1 : AddGadgetItem( 1, -1, "[" + Str(\ThreadID) + "] " + File ) : EndIf
                File = ""
              EndIf
  
            Wend
            
            FinishDirectory(DirID)
            
            ForEach FL()
              If FL()\Flag = 0
                AddGadgetItem( 1, -1, "Deleted: " + FL()\FileName )
                DeleteElement( FL() )
                Count + 1
              EndIf
            Next
            
          Else
            Break 2
          EndIf
        Until Count = 0
      EndIf
      
      FindNextChangeNotification_(\hChngObject)
    Wend
    
    If \hChngObject
      FindCloseChangeNotification_(\hChngObject)
    EndIf
    
    ClearList( FL () )
    
    \ThreadID = 0
  EndWith
EndProcedure
Procedure   InitWatchFolder ( Dir.s )
  
  If Right(Dir, 1) = "\" : Dir = Left(Dir, Len(Dir) - 1) : EndIf
  DirID = ExamineDirectory(#PB_Any, Dir, "*.*")  
  
  If DirID
    AddElement( WF() )
    With WF()
      \Dir = Dir
      \WaitMillisecs = 2000; wait 1sec. to decrease cpu load
      \ThreadID = CreateThread(@DoWatchFolder(), @WF())
      ThreadPriority( \ThreadID,  1 ) ; decreas cpu load
    EndWith
    AddGadgetItem(1, -1, "Add: " + Dir )
    
    While NextDirectoryEntry(DirID)
      If DirectoryEntryType(DirID) = #PB_DirectoryEntry_Directory
        If DirectoryEntryName(DirID) <> "." And DirectoryEntryName(DirID) <> ".."
          InitWatchFolder( Dir + "\" + DirectoryEntryName(DirID) )
        EndIf
      EndIf
    Wend
    FinishDirectory(DirID)
  EndIf
EndProcedure
Procedure.b QuitWatchFolder()
  Protected Quit.b
  
  ForEach WF()
    If WF()\ThreadID And IsThread( WF()\ThreadID )
      WF()\Flag = 1
    EndIf
  Next
  
  TimeOut = ElapsedMilliseconds() + 50000
  Repeat
    Delay(200)
    Count = 0
    ForEach WF()
      If WF()\ThreadID
        Count + 1
      EndIf
    Next
  Until Count = 0 Or TimeOut < ElapsedMilliseconds()
  
  If Count = 0 : Quit = 1 : Else : Quit = 2 : EndIf
  AddGadgetItem(1, -1, "QuitCode: " + Str(Quit))
  
  ProcedureReturn Quit
EndProcedure

;{ MainLoop
If OpenWindow(0, 100, 200, 350, 400, "KeepTrackOnDirs by DiGe", #PB_Window_SystemMenu | #PB_Window_MinimizeGadget | #PB_Window_MaximizeGadget)
  If CreateGadgetList(WindowID(0))
    ListIconGadget( 1, 0, 0, 350, 380, "", 345, #PB_ListIcon_MultiSelect|#PB_ListIcon_GridLines|#PB_ListIcon_FullRowSelect )
    ButtonGadget( 2, 0, 380, 100, 20, "Clear List" )
    ButtonGadget( 3, 100, 380, 100, 20, "Quit Watch" )
  EndIf
  
  #INIFILE = "WatchFolder.ini"
  Dir.s    = ""
  
  FileID = ReadFile( #PB_Any, #INIFILE )
  If FileID
    While Not Eof(FileID)
      Dir = ReadString( FileID )
      If Dir
        InitWatchFolder( Dir )
      EndIf
    Wend
    CloseFile(FileID)
    
  Else
    Dir = PathRequester( "WatchFolder", "" )
    If Dir : InitWatchFolder( Dir ) : EndIf
  EndIf
   
  AddGadgetItem( 1, -1, "Watching " + Str(CountList(WF())) + " Folder(s)")
  
  Repeat
    EventID.l = WaitWindowEvent()
    If EventID = #PB_Event_CloseWindow
      Quit = QuitWatchFolder()
    ElseIf EventID = #PB_Event_Gadget
        
      Select EventGadget()
        Case 1 : If EventType() = #PB_EventType_DragStart : DragNDropFile () : EndIf
        Case 2 : ClearGadgetItemList(1)  
        Case 3 : Quit = QuitWatchFolder()  
      EndSelect
    EndIf
  Until Quit
  While WindowEvent() : Wend
  Delay(1000)
EndIf
;}
End
Here's another simpler example, while this doesn't do it 100% of the time, it does happen occasionally.
No virus scanner active, x64 win8.1.

Code: Select all

EnableExplicit

Procedure procdir( cFolder.s )
	Protected  hdir, cname.s
	
	hdir = ExamineDirectory(#PB_Any,cFolder,"*")
	If hdir 
;		If IsDirectory(hdir)
			While NextDirectoryEntry(hdir)
				cname = DirectoryEntryName(hdir)
				If DirectoryEntryType(hdir)=#PB_DirectoryEntry_Directory
					If cname <> "." And cname <> ".."
						procdir( cFolder+"\" + cname)
					EndIf
				EndIf 
			Wend 
			
			FinishDirectory(hdir)
			
		;Else
;			Debug "Failed directory: "+cFolder
;		EndIf
	EndIf 
EndProcedure

procdir("c:\")

Re: directory library issue.

Posted: Sat Jan 28, 2017 10:06 pm
by #NULL
the comment header in the first code says it needs threadsafe enabled.
and listing C:\ recursively probably needs a decent amount of recources (including pb dir list objects).
(i can't test the codes currently)