Page 1 of 1

Detect empty Start Menu folders?

Posted: Thu Jan 31, 2008 10:38 pm
by eJan
Hi, i need help here for my cleanup program: after deinstalling some programs in Start Menu remains empty folders. How to list and delete them?
DirectoryEntrySize(#Directory) always return 0 regardless if dir is empty or contain shortcuts (.lnk, .url).

Code: Select all

Procedure.s GetSpecialFolder(CSIDL.l)
  Protected *itemid.ITEMIDLIST
  Protected location.s = Space(#MAX_PATH)

  If SHGetSpecialFolderLocation_ (0, CSIDL, @*itemid) = #NOERROR
    If SHGetPathFromIDList_(*itemid, @location)
      If Right(location, 1) <> "\" : location + "\" : EndIf
      ProcedureReturn location
    EndIf
  EndIf
EndProcedure

programs.s = GetSpecialFolder(#CSIDL_PROGRAMS)

If ExamineDirectory(0, programs, "*.*")
  While NextDirectoryEntry(0)
    If DirectoryEntryType(0) = #PB_DirectoryEntry_Directory
      If DirectoryEntryName(Dir) <> "." And DirectoryEntryName(Dir) <> ".."
        Debug DirectoryEntryName(0) + Type$ + "- Size in byte: " + Str(DirectoryEntrySize(0))
      EndIf
    EndIf

  Wend
  FinishDirectory(0)
EndIf

Posted: Fri Feb 01, 2008 12:40 am
by oridan
Hi eJan, try with my code:

Code: Select all

Global TotalSize.q

Procedure.s Convert(byte.q, NbDecimals.l=2) 
   If byte < 1024 
      If byte < 0 
         byte=0 
      EndIf 
      ProcedureReturn ReplaceString(Str(byte)+" Byte", ".", ",")
   ElseIf byte >= 1<<60 
      ProcedureReturn ReplaceString(StrD(byte/1<<60, NbDecimals)+" EB", ".", ",")
   ElseIf byte >= 1<<50 
      ProcedureReturn ReplaceString(StrD(byte/1<<50, NbDecimals)+" PB", ".", ",")
   ElseIf byte >= 1<<40 
      ProcedureReturn ReplaceString(StrD(byte/1<<40, NbDecimals)+" TB", ".", ",")
   ElseIf byte >= 1<<30 
      ProcedureReturn ReplaceString(StrD(byte/1<<30, NbDecimals)+" GB", ".", ",")
   ElseIf byte >= 1<<20 
      ProcedureReturn ReplaceString(StrD(byte/1<<20, NbDecimals)+" MB", ".", ",")
   Else 
      ProcedureReturn ReplaceString(StrD(byte/1024, NbDecimals)+" KB", ".", ",")
   EndIf 
EndProcedure

Procedure.s GetSpecialFolder(CSIDL.l) 
  Protected *itemid.ITEMIDLIST 
  Protected location.s = Space(#MAX_PATH) 

  If SHGetSpecialFolderLocation_ (0, CSIDL, @*itemid) = #NOERROR 
    If SHGetPathFromIDList_(*itemid, @location) 
      If Right(location, 1) <> "\" : location + "\" : EndIf 
      ProcedureReturn location 
    EndIf 
  EndIf 
EndProcedure 

path$ = GetSpecialFolder(#CSIDL_PROGRAMS) 

Procedure.q GET_CSIDL_PROGRAMS(path$,pattern$ = "*.*") 
  If Right(path$,1)<>"\":path$+"\":EndIf 
  DirID = ExamineDirectory(#PB_Any,path$,pattern$)
    If DirID 
    While NextDirectoryEntry(DirID) 
      If DirectoryEntryType(DirID) = #PB_DirectoryEntry_Directory 
        If DirectoryEntryName(DirID)<>"." And DirectoryEntryName(DirID)<>".."
          GET_CSIDL_PROGRAMS(path$+DirectoryEntryName(DirID)+"\",pattern$)
          Debug DirectoryEntryName(DirID) + " = "+ Convert(TotalSize.q)
        EndIf 
      EndIf 
      If DirectoryEntryType(DirID) = #PB_DirectoryEntry_File 
        TotalSize.q + DirectoryEntrySize(DirID) 
      EndIf 
    Wend 
    FinishDirectory(DirID) 
  EndIf 
  ProcedureReturn TotalSize.q
EndProcedure

GET_CSIDL_PROGRAMS(path$,"*.*")
Regards :wink:

Posted: Fri Feb 01, 2008 9:10 pm
by eJan
Thanks oridan, I doesn't work as espected in XP - for empty folder it returns 17,91 KB, another one with 2 subdirs 9,95 KB? until then i can always delete them manualy (i will try to to find some useful solution). :)
EDIT:
This dirty one works using API function 'RemoveDirectory_()'.
MSDN: http://msdn2.microsoft.com/en-us/librar ... S.85).aspx
Should be tweaked to list only folders...

Code: Select all

; Trond: http://www.purebasic.fr/english/viewtopic.php?p=178764#178764

Procedure ExamineDirectoryRecursive(Path.s, Pattern.s, List.s())
  Protected Dir = ExamineDirectory(#PB_Any, Path, Pattern)
  If Right(Path, 1) <> "\"
    Path + "\"
  EndIf
  If Dir
    While NextDirectoryEntry(Dir)
      If DirectoryEntryName(Dir) <> "." And DirectoryEntryName(Dir) <> ".."
        AddElement(List())
        List() = Path + DirectoryEntryName(Dir)
      EndIf
    Wend
    FinishDirectory(Dir)
  EndIf
  Dir = ExamineDirectory(#PB_Any, Path, "")
  If Dir
    While NextDirectoryEntry(Dir)
      If DirectoryEntryType(Dir) = #PB_DirectoryEntry_Directory
        If DirectoryEntryName(Dir) <> "." And DirectoryEntryName(Dir) <> ".."
          ExamineDirectoryRecursive(Path + DirectoryEntryName(Dir) + "\", Pattern, List())
        EndIf
      EndIf
    Wend
    FinishDirectory(Dir)
  EndIf
EndProcedure

Procedure.s GetSpecialFolder(CSIDL.l) 
  Protected *itemid.ITEMIDLIST 
  Protected location.s = Space(#MAX_PATH) 

  If SHGetSpecialFolderLocation_ (0, CSIDL, @*itemid) = #NOERROR 
    If SHGetPathFromIDList_(*itemid, @location) 
      If Right(location, 1) <> "\" : location + "\" : EndIf 
      ProcedureReturn location 
    EndIf 
  EndIf 
EndProcedure 

programs.s = GetSpecialFolder(#CSIDL_PROGRAMS) 

NewList List.s()
ExamineDirectoryRecursive(programs, "*.*", List())

ForEach List()
  ;Debug List()
  RemoveDirectory_(List())
Next

Posted: Fri Feb 01, 2008 10:25 pm
by Trond
This should do it:

Code: Select all

Procedure ExamineDirectoryRecursive(Path.s, List.s())
  Protected Dir
  If Right(Path, 1) <> "\"
    Path + "\"
  EndIf
  Dir = ExamineDirectory(#PB_Any, Path, "*.*")
  If Dir
    While NextDirectoryEntry(Dir)
      If DirectoryEntryType(Dir) = #PB_DirectoryEntry_Directory
        If DirectoryEntryName(Dir) <> "." And DirectoryEntryName(Dir) <> ".."
          AddElement(List())
          List() = Path + DirectoryEntryName(Dir)
          ExamineDirectoryRecursive(Path + DirectoryEntryName(Dir) + "\", List())
        EndIf
      EndIf
    Wend
    FinishDirectory(Dir)
  EndIf
EndProcedure

Procedure IsDirectoryEmpty(Dir.s)
  Protected D = ExamineDirectory(#PB_Any, Dir, "*.*")
  Protected I
  If D
    While NextDirectoryEntry(D)
      I + 1
      If I >= 3
        FinishDirectory(D)
        ProcedureReturn 0
      EndIf
    Wend
    FinishDirectory(D)
    ProcedureReturn 1
  EndIf
EndProcedure

Procedure.s GetSpecialFolder(CSIDL.l)
  Protected *itemid.ITEMIDLIST
  Protected location.s = Space(#MAX_PATH)
  If SHGetSpecialFolderLocation_ (0, CSIDL, @*itemid) = #NOERROR
    If SHGetPathFromIDList_(*itemid, @location)
      ProcedureReturn location
    EndIf
  EndIf
EndProcedure

programs.s = GetSpecialFolder(#CSIDL_PROGRAMS)

NewList List.s()
ExamineDirectoryRecursive(programs, List())
SortList(List(), 0)

ForEach List()
  If IsDirectoryEmpty(List())
    Debug List()
    ; DeleteDirectory(...
  EndIf
Next

Posted: Sat Feb 02, 2008 1:35 pm
by eJan
Thanks Trond, this one works! :D