SuperviseDirectory() & GetKnownFolder() [Module][WIN]

Hier könnt Ihr gute, von Euch geschriebene Codes posten. Sie müssen auf jeden Fall funktionieren und sollten möglichst effizient, elegant und beispielhaft oder einfach nur cool sein.
Benutzeravatar
Bisonte
Beiträge: 2427
Registriert: 01.04.2007 20:18

SuperviseDirectory() & GetKnownFolder() [Module][WIN]

Beitrag von Bisonte »

Mahlzeit.

Ich brauchte für ein Projekt eine Überwachung eines Systemverzeichnisses von Windows und
fand in der WINAPI Library von RSBasic einen Code von Sparkie. Dieser war mir zu unflexibel,
daher hab ich diesen etwas verallgemeinert und in ein Modul verfrachtet.

Bei der Nutzung fiel mir noch ein böser Schnitzer von Sparkie auf, der dafür sorgte, das Filenamen,
die länger waren als der vorherige Name, den neu ausgelesenen Namen beeinflusste (es wurde immer
die maximale Länge ausgegeben).

WICHTIG !!! ist nur, dass man bei der Eventabfrage den Speicher, dessen Adresse man mit EventData()
bekommt (da steht der Filename drin) wieder freigibt. (Siehe Demo am Ende des Codes)

Da meine heissgeliebte Prozedur "GetSpecialFolder(CLSID)" von TS-Soft leider nicht mehr alle Verzeichnisse ermitteln kann,
habe ich die Prozedur "GetKnownFolder()" von GS-68 etwas erweitert, damit man Konstanten anstelle von Adressen
nutzen kann um ein Systemverzeichnis Pfad zu ermitteln. Dieser wird dann in PB Manier mit abschliessendem Backslash
ausgegeben.
Microsoft meint das dies jetzt aktuell wäre und die CLSID Methode seit Windows 8 obsolet wäre.... Kennt man ja.

Der Name des Moduls ist völlig unwichtig.... mir ging es um wenig Tipparbeit :mrgreen:

Nun doch mit Versionsnummern :

History:
  • 05.08.18 - V1.06
  • Bugfix : Das abbrechen einer Überwachung wird jetzt per "Killthread" beendet.
  • 10.03.18 - V1.05
  • Bugfix : Filename wurde mit falscher Länge behandelt. Somit waren u.U. die ermittelten Namen nicht korrekt.
  • 09.03.18 - V1.04
  • Identifizierung von mehreren SuperviseDirectories und deren Events per ID ermöglicht
  • GetSuperViseDirectory(ID) gibt überwachtes Verzeichnis zurück
  • 09.03.18 : V1.02
  • Rekursivität ist optinional ein/ausschaltbar
  • 08.03.18 : V1.01
  • Löschen des kompletten Buffers im Thread eingefügt.
  • 08.03.18 : V1.00
  • Release
Lange Rede kurzer Code... (wenn man die Datazeilen nicht mitzählt ;) )

Code: Alles auswählen

DeclareModule mAPI
   
  ; mAPI V1.06
  ; Bugfix : StopSuperViseDirectory()
  
  ; mApi V1.05
  ; Bugfix : FilenameLength was unmodified, so sometimes the string was longer than it should.
 
  ; mApi V1.04
  ; Now returns StartSuperVise an ID. This ID is present in EventGadget() at every Event.
  ; GetSuperViseDirectory(ID) returns the Directory that is supervised with this ID.
 
  ; mAPI V1.03
  ; Renaming files where also detected if the eventtype is given as parameter at
  ; Init_SuperVisorDirectory() call.
  ; to get both filenames I use StringField with ":" as delimeter
  ; First Field = Old Filename , Second Field = New FileName
 
  ; mAPI V1.02
  ; Supervise SubDirectories recursiv is now an optional parameter.
 
  ; mAPI V1.01
  ; Clear buffer completly in loop of thread.
 
  ; mAPI V1.00
  ; Release
 
  ; GetKnownFolderPath()
  ; Original Author : GJ-68
  ; Original Link   : http://www.purebasic.fr/english/viewtopic.php?p=416385#p416385
  ; modified by George Bisonte (Module & "Constants : source MSDN" )
 
  ; SuperVisorDirectory()
  ; Original Author: Sparkie
  ; Original Link  : http://www.purebasic.fr/english/viewtopic.php?p=86514#p86514
  ; modified by George Bisonte for PB 5.62 (EventDriven & Module)
 
  EnableExplicit

  Enumeration 0
    #FID_NetworkFolder
    #FID_ComputerFolder
    #FID_InternetFolder
    #FID_ControlPanelFolder
    #FID_PrintersFolder
    #FID_SyncManagerFolder
    #FID_SyncSetupFolder
    #FID_ConflictFolder
    #FID_SyncResultsFolder
    #FID_RecycleBinFolder
    #FID_ConnectionsFolder
    #FID_Fonts
    #FID_Desktop
    #FID_Startup
    #FID_Programs
    #FID_StartMenu
    #FID_Recent
    #FID_SendTo
    #FID_Documents
    #FID_Favorites
    #FID_NetHood
    #FID_PrintHood
    #FID_Templates
    #FID_CommonStartup
    #FID_CommonPrograms
    #FID_CommonStartMenu
    #FID_PublicDesktop
    #FID_ProgramData
    #FID_CommonTemplates
    #FID_PublicDocuments
    #FID_RoamingAppData
    #FID_LocalAppData
    #FID_LocalAppDataLow
    #FID_InternetCache
    #FID_Cookies
    #FID_History
    #FID_System
    #FID_SystemX86
    #FID_Windows
    #FID_Profile
    #FID_Pictures
    #FID_ProgramFilesX86
    #FID_ProgramFilesCommonX86
    #FID_ProgramFilesX64
    #FID_ProgramFilesCommonX64
    #FID_ProgramFiles
    #FID_ProgramFilesCommon
    #FID_UserProgramFiles
    #FID_UserProgramFilesCommon
    #FID_AdminTools
    #FID_CommonAdminTools
    #FID_Music
    #FID_Videos
    #FID_Ringtones
    #FID_PublicPictures
    #FID_PublicMusic
    #FID_PublicVideos
    #FID_PublicRingtones
    #FID_ResourceDir
    #FID_LocalizedResourcesDir
    #FID_CommonOEMLinks
    #FID_CDBurning
    #FID_UserProfiles
    #FID_Playlists
    #FID_SamplePlaylists
    #FID_SampleMusic
    #FID_SamplePictures
    #FID_SampleVideos
    #FID_PhotoAlbums
    #FID_Public
    #FID_ChangeRemovePrograms
    #FID_AppUpdates
    #FID_AddNewPrograms
    #FID_Downloads
    #FID_PublicDownloads
    #FID_SavedSearches
    #FID_QuickLaunch
    #FID_Contacts
    #FID_PublicGameTasks
    #FID_GameTasks
    #FID_SavedGames
    #FID_Games
    #FID_SEARCH_MAPI
    #FID_SEARCH_CSC
    #FID_Links
    #FID_UsersFiles
    #FID_UsersLibraries
    #FID_SearchHome
    #FID_OriginalImages
    #FID_DocumentsLibrary
    #FID_MusicLibrary
    #FID_PicturesLibrary
    #FID_VideosLibrary
    #FID_RecordedTVLibrary
    #FID_HomeGroup
    #FID_DeviceMetadataStore
    #FID_Libraries
    #FID_PublicLibraries
    #FID_UserPinned
    #FID_ImplicitAppShortcuts
  EndEnumeration
   
  ; Get Windows-Systemfolder by FID Constant for compatibility => Windows 7 (MSDN)
  ; Returns full path with Backslash like PB functions
  Declare.s GetKnownFolderPath(FID)
 
  ; Supervise a folder with a thread and if changes PostEvent() : UNICODE Only!
  ; BE SURE THAT YOU FREE THE MEMORY (EventData() is the address) !!!!
 
  ; Declare Event and EventTypes for SuperVisorDirectory
  Declare.i Init_SuperVisorDirectory(Event, EventTypeAdd, EventTypeModified, EventTypeRemove, EventTypeRename = 0)
  ; Start SuperVisor Thread, Returns SuperViser ID
  Declare.i StartSuperviseDirectory(Directory.s, Window, Recursive = #True)                                     
  ; Stop SuperVisorThread
  Declare.i StopSuperviseDirectory(Directory.s)                                               
  ; Get the Directory from a SuperViser ID
  Declare.s GetSuperViserDirectory(ID)
EndDeclareModule
Module mAPI
 
  #Magic = 2018030922
 
  #FILE_NOTIFY_CHANGE_LAST_ACCESS = $20
  #FILE_NOTIFY_CHANGE_CREATION    = $40
  #FILE_NOTIFY_CHANGE_ALL         = $17F
  #FILE_ACTION_ADDED              = 1
  #FILE_ACTION_REMOVED            = 2
  #FILE_ACTION_MODIFIED           = 3
  #FILE_ACTION_RENAMED_OLD_NAME   = 4
  #FILE_ACTION_RENAMED_NEW_NAME   = 5
 
  Structure FILE_NOTIFY_INFORMATION
    NextEntryOffset.l
    Action.l
    FileNameLength.l
    Filename.s{1024*32}
  EndStructure
 
  Prototype SHGetKnownFolderPath__(rfid, dwFlags.l, hToken, *ppszPath)

  Import "kernel32.lib"
    ReadDirectoryChangesW(hDirectory, lpBuffer, nBufferLength, bWatchSubtree, dwNotifyFilter, lpBytesReturned, lpOverlapped, lpCompletionRoutine)
  EndImport
 
  Structure s_superviseDirectory
    Magic.l
    Address.i
    ID.i
    Halt.i   
    Directory.s
    Window.i
    Recursive.i
    New.s
    Old.s
  EndStructure
  Structure s_supervisorInit
    Init.i
    Event.i
    ETADD.i
    ETMOD.i
    ETREM.i
    ETRENAME.i
  EndStructure
 
  Global NewMap SuperVisor.s_superviseDirectory()
  Global SuperVisorInit.s_supervisorInit
 
  Procedure.s GetKnownFolderPath(FID)
   
    Protected DLL, i, Result.s, *UnicodeBuffer, kfFlag.l, SHGetKnownFolderPath.SHGetKnownFolderPath__
    Protected *FolderID
   
    If FID > -1 And FID <= #FID_ImplicitAppShortcuts
      *FolderID = ?FOLDERID_NetworkFolder + (16 * FID)
    Else
      ProcedureReturn ""
    EndIf
   
    DLL = OpenLibrary(#PB_Any, "Shell32.dll")
    If DLL
      SHGetKnownFolderPath = GetFunction(DLL, "SHGetKnownFolderPath")
      If SHGetKnownFolderPath
        If SHGetKnownFolderPath(*FolderID, kfFlag, #Null, @*UnicodeBuffer) = #S_OK And *UnicodeBuffer
          Result = PeekS(*UnicodeBuffer, -1, #PB_Unicode) + "\"
          CoTaskMemFree_(*UnicodeBuffer)
        EndIf
      EndIf
      CloseLibrary(DLL)
    EndIf
   
    If Result = ""
      Result = GetHomeDirectory()
    EndIf
   
    ProcedureReturn Result
   
  EndProcedure

  Procedure.i SuperVisorThread(*p.s_superviseDirectory)
   
    Protected NotifyFilter.l = #FILE_NOTIFY_CHANGE_ALL
    Protected buffer.FILE_NOTIFY_INFORMATION, ovlp.OVERLAPPED
    Protected hDir, bytesRead, *FileName, FileAction_File.s, String.s, Size1, Size2
   
    If *p
     
      hDir = CreateFile_(*p\Directory, #FILE_LIST_DIRECTORY, #FILE_SHARE_READ | #FILE_SHARE_WRITE | #FILE_SHARE_DELETE, #Null, #OPEN_EXISTING, #FILE_FLAG_BACKUP_SEMANTICS, #Null)
      
      
      While ReadDirectoryChangesW(hDir, @buffer, SizeOf(FILE_NOTIFY_INFORMATION), *p\Recursive, NotifyFilter, bytesRead, ovlp, 0)
               
        FileAction_File = PeekS(@buffer\Filename, buffer\FileNameLength / SizeOf(Unicode), #PB_Unicode)

        *FileName = AllocateMemory(StringByteLength(FileAction_File, #PB_Unicode) + StringByteLength(" ", #PB_Unicode))
        If *FileName
          PokeS(*FileName, FileAction_File, -1, #PB_Unicode)
         
          Select buffer\Action
            Case #FILE_ACTION_ADDED   
              PostEvent(SuperVisorInit\Event, *p\Window, *p\Address, SuperVisorInit\ETADD, *FileName)
            Case #FILE_ACTION_MODIFIED
              PostEvent(SuperVisorInit\Event, *p\Window, *p\Address, SuperVisorInit\ETMOD, *FileName)
            Case #FILE_ACTION_REMOVED
              PostEvent(SuperVisorInit\Event, *p\Window, *p\Address, SuperVisorInit\ETREM, *FileName)
            Case #FILE_ACTION_RENAMED_OLD_NAME
              If SuperVisorInit\ETRENAME
                *p\Old = FileAction_File : *p\New = PeekS(@buffer\Filename + buffer\NextEntryOffset, -1, #PB_Unicode)
              Else
                *p\Old = "" : *p\New = ""
              EndIf
             
            Default
              FreeMemory(*FileName)
             
          EndSelect
         
          If SuperVisorInit\ETRENAME
            If *p\New <> "" And *p\Old <> ""
              String = *p\Old + ":" + *p\New
              *FileName = AllocateMemory(StringByteLength(String, #PB_Unicode) + StringByteLength(" ", #PB_Unicode))
              If *FileName
                PokeS(*FileName, String, -1, #PB_Unicode)
                PostEvent(SuperVisorInit\Event, *p\Window, *p\Address, SuperVisorInit\ETRENAME, *FileName)
              EndIf 
            EndIf
            *p\Old = "" : *p\New = ""
          EndIf
         
        EndIf
        
       
        ; Clear buffer
        buffer\Filename = "" : buffer\Action = 0 : buffer\FileNameLength = 0 : buffer\NextEntryOffset = 0
        
        If *p\Halt = #True : Break : EndIf
        
      Wend
      
      
    EndIf     
   
  EndProcedure
 
  Procedure.i Init_SuperVisorDirectory(Event, EventTypeAdd, EventTypeModified, EventTypeRemove, EventTypeRename = 0)
   
    With SuperVisorInit
      \Init = #True
      \Event = Event
      \ETADD = EventTypeAdd
      \ETMOD = EventTypeModified
      \ETREM = EventTypeRemove
      \ETRENAME = EventTypeRename
    EndWith
       
  EndProcedure
 
  Procedure.i StopSuperviseDirectory(Directory.s)
    
    Protected Counter = 0
    
    If FindMapElement(SuperVisor(), LCase(Directory))
      If IsThread(SuperVisor()\ID)
        SuperVisor()\Halt = #True
        KillThread(SuperVisor()\ID)
      EndIf
      DeleteMapElement(SuperVisor(), LCase(Directory))
    EndIf
   
  EndProcedure
  Procedure.i StartSuperviseDirectory(Directory.s, Window, Recursive = #True)
   
    Protected Result = #False
   
    CompilerIf #PB_Compiler_Unicode = #False
      CompilerError "ONLY UNICODE"
    CompilerEndIf
         
    If SuperVisorInit\Init = #True And IsWindow(Window)
     
      If FindMapElement(SuperVisor(), LCase(Directory))
        If IsThread(SuperVisor()\ID)
          StopSuperviseDirectory(Directory)
        EndIf
      EndIf
     
      With SuperVisor(LCase(Directory))
        \Magic     = #Magic
        \Address   = @SuperVisor(LCase(Directory))
        \Recursive = Bool(Recursive)
        \Directory = Directory
        \Halt      = #False
        \Window    = Window
        \ID        = CreateThread(@SuperVisorThread(), @SuperVisor(LCase(Directory)))
      EndWith
     
      Result = SuperVisor(LCase(Directory))\Address
     
    Else
      Debug "You have to call Init_SuperVisorDirectory() first!"
    EndIf
   
    ProcedureReturn Result
   
  EndProcedure
 
  Procedure.s GetSuperViserDirectory(ID)
   
    Protected *a.s_superviseDirectory = ID
    Protected Result.s
   
    If *a
      If *a\Magic = #Magic
        Result = *a\Directory
      EndIf
    EndIf
   
    ProcedureReturn Result
           
  EndProcedure
   
  DataSection
    FOLDERID_NetworkFolder:
    Data.l $D20BEEC4
    Data.w $5CA8,$4905
    Data.b $AE,$3B,$BF,$25,$1E,$A0,$9B,$53
   
    FOLDERID_ComputerFolder:
    Data.l $0AC0837C
    Data.w $BBF8,$452A
    Data.b $85,$0D,$79,$D0,$8E,$66,$7C,$A7
   
    FOLDERID_InternetFolder:
    Data.l $4D9F7874
    Data.w $4E0C,$4904
    Data.b $96,$7B,$40,$B0,$D2,$0C,$3E,$4B
   
    FOLDERID_ControlPanelFolder:
    Data.l $82A74AEB
    Data.w $AEB4,$465C
    Data.b $A0,$14,$D0,$97,$EE,$34,$6D,$63
   
    FOLDERID_PrintersFolder:
    Data.l $76FC4E2D
    Data.w $D6AD,$4519
    Data.b $A6,$63,$37,$BD,$56,$06,$81,$85
   
    FOLDERID_SyncManagerFolder:
    Data.l $43668BF8
    Data.w $C14E,$49B2
    Data.b $97,$C9,$74,$77,$84,$D7,$84,$B7
   
    FOLDERID_SyncSetupFolder:
    Data.l $F214138
    Data.w $B1D3,$4A90
    Data.b $BB,$A9,$27,$CB,$C0,$C5,$38,$9A
   
    FOLDERID_ConflictFolder:
    Data.l $4BFEFB45
    Data.w $347D,$4006
    Data.b $A5,$BE,$AC,$0C,$B0,$56,$71,$92
   
    FOLDERID_SyncResultsFolder:
    Data.l $289A9A43
    Data.w $BE44,$4057
    Data.b $A4,$1B,$58,$7A,$76,$D7,$E7,$F9
   
    FOLDERID_RecycleBinFolder:
    Data.l $B7534046
    Data.w $3ECB,$4C18
    Data.b $BE,$4E,$64,$CD,$4C,$B7,$D6,$AC
   
    FOLDERID_ConnectionsFolder:
    Data.l $6F0CD92B
    Data.w $2E97,$45D1
    Data.b $88,$FF,$B0,$D1,$86,$B8,$DE,$DD
   
    FOLDERID_Fonts:
    Data.l $FD228CB7
    Data.w $AE11,$4AE3
    Data.b $86,$4C,$16,$F3,$91,$0A,$B8,$FE
   
    FOLDERID_Desktop:
    Data.l $B4BFCC3A
    Data.w $DB2C,$424C
    Data.b $B0,$29,$7F,$E9,$9A,$87,$C6,$41
   
    FOLDERID_Startup:
    Data.l $B97D20BB
    Data.w $F46A,$4C97
    Data.b $BA,$10,$5E,$36,$08,$43,$08,$54
   
    FOLDERID_Programs:
    Data.l $A77F5D77
    Data.w $2E2B,$44C3
    Data.b $A6,$A2,$AB,$A6,$01,$05,$4A,$51
   
    FOLDERID_StartMenu:
    Data.l $625B53C3
    Data.w $AB48,$4EC1
    Data.b $BA,$1F,$A1,$EF,$41,$46,$FC,$19
   
    FOLDERID_Recent:
    Data.l $AE50C081
    Data.w $EBD2,$438A
    Data.b $86,$55,$8A,$09,$2E,$34,$98,$7A
   
    FOLDERID_SendTo:
    Data.l $8983036C
    Data.w $27C0,$404B
    Data.b $8F,$08,$10,$2D,$10,$DC,$FD,$74
   
    FOLDERID_Documents:
    Data.l $FDD39AD0
    Data.w $238F,$46AF
    Data.b $AD,$B4,$6C,$85,$48,$03,$69,$C7
   
    FOLDERID_Favorites:
    Data.l $1777F761
    Data.w $68AD,$4D8A
    Data.b $87,$BD,$30,$B7,$59,$FA,$33,$DD
   
    FOLDERID_NetHood:
    Data.l $C5ABBF53
    Data.w $E17F,$4121
    Data.b $89,$00,$86,$62,$6F,$C2,$C9,$73
   
    FOLDERID_PrintHood:
    Data.l $9274BD8D
    Data.w $CFD1,$41C3
    Data.b $B3,$5E,$B1,$3F,$55,$A7,$58,$F4
   
    FOLDERID_Templates:
    Data.l $A63293E8
    Data.w $664E,$48DB
    Data.b $A0,$79,$DF,$75,$9E,$05,$09,$F7
   
    FOLDERID_CommonStartup:
    Data.l $82A5EA35
    Data.w $D9CD,$47C5
    Data.b $96,$29,$E1,$5D,$2F,$71,$4E,$6E
   
    FOLDERID_CommonPrograms:
    Data.l $0139D44E
    Data.w $6AFE,$49F2
    Data.b $86,$90,$3D,$AF,$CA,$E6,$FF,$B8
   
    FOLDERID_CommonStartMenu:
    Data.l $A4115719
    Data.w $D62E,$491D
    Data.b $AA,$7C,$E7,$4B,$8B,$E3,$B0,$67
   
    FOLDERID_PublicDesktop:
    Data.l $C4AA340D
    Data.w $F20F,$4863
    Data.b $AF,$EF,$F8,$7E,$F2,$E6,$BA,$25
   
    FOLDERID_ProgramData:
    Data.l $62AB5D82
    Data.w $FDC1,$4DC3
    Data.b $A9,$DD,$07,$0D,$1D,$49,$5D,$97
   
    FOLDERID_CommonTemplates:
    Data.l $B94237E7
    Data.w $57AC,$4347
    Data.b $91,$51,$B0,$8C,$6C,$32,$D1,$F7
   
    FOLDERID_PublicDocuments:
    Data.l $ED4824AF
    Data.w $DCE4,$45A8
    Data.b $81,$E2,$FC,$79,$65,$08,$36,$34
   
    FOLDERID_RoamingAppData:
    Data.l $3EB685DB
    Data.w $65F9,$4CF6
    Data.b $A0,$3A,$E3,$EF,$65,$72,$9F,$3D
   
    FOLDERID_LocalAppData:
    Data.l $F1B32785
    Data.w $6FBA,$4FCF
    Data.b $9D,$55,$7B,$8E,$7F,$15,$70,$91
   
    FOLDERID_LocalAppDataLow:
    Data.l $A520A1A4
    Data.w $1780,$4FF6
    Data.b $BD,$18,$16,$73,$43,$C5,$AF,$16
   
    FOLDERID_InternetCache:
    Data.l $352481E8
    Data.w $33BE,$4251
    Data.b $BA,$85,$60,$07,$CA,$ED,$CF,$9D
   
    FOLDERID_Cookies:
    Data.l $2B0F765D
    Data.w $C0E9,$4171
    Data.b $90,$8E,$08,$A6,$11,$B8,$4F,$F6
   
    FOLDERID_History:
    Data.l $D9DC8A3B
    Data.w $B784,$432E
    Data.b $A7,$81,$5A,$11,$30,$A7,$59,$63
   
    FOLDERID_System:
    Data.l $1AC14E77
    Data.w $02E7,$4E5D
    Data.b $B7,$44,$2E,$B1,$AE,$51,$98,$B7
   
    FOLDERID_SystemX86:
    Data.l $D65231B0
    Data.w $B2F1,$4857
    Data.b $A4,$CE,$A8,$E7,$C6,$EA,$7D,$27
   
    FOLDERID_Windows:
    Data.l $F38BF404
    Data.w $1D43,$42F2
    Data.b $93,$05,$67,$DE,$0B,$28,$FC,$23
   
    FOLDERID_Profile:
    Data.l $5E6C858F
    Data.w $0E22,$4760
    Data.b $9A,$FE,$EA,$33,$17,$B6,$71,$73
   
    FOLDERID_Pictures:
    Data.l $33E28130
    Data.w $4E1E,$4676
    Data.b $83,$5A,$98,$39,$5C,$3B,$C3,$BB
   
    FOLDERID_ProgramFilesX86:
    Data.l $7C5A40EF
    Data.w $A0FB,$4BFC
    Data.b $87,$4A,$C0,$F2,$E0,$B9,$FA,$8E
   
    FOLDERID_ProgramFilesCommonX86:
    Data.l $DE974D24
    Data.w $D9C6,$4D3E
    Data.b $BF,$91,$F4,$45,$51,$20,$B9,$17
   
    FOLDERID_ProgramFilesX64:
    Data.l $6D809377
    Data.w $6AF0,$444B
    Data.b $89,$57,$A3,$77,$3F,$02,$20,$0E
   
    FOLDERID_ProgramFilesCommonX64:
    Data.l $6365D5A7
    Data.w $F0D,$45E5
    Data.b $87,$F6,$D,$A5,$6B,$6A,$4F,$7D
   
    FOLDERID_ProgramFiles:
    Data.l $905E63B6
    Data.w $C1BF,$494E
    Data.b $B2,$9C,$65,$B7,$32,$D3,$D2,$1A
   
    FOLDERID_ProgramFilesCommon:
    Data.l $F7F1ED05
    Data.w $9F6D,$47A2
    Data.b $AA,$AE,$29,$D3,$17,$C6,$F0,$66
   
    FOLDERID_UserProgramFiles:
    Data.l $5CD7AEE2
    Data.w $2219,$4A67
    Data.b $B8,$5D,$6C,$9C,$E1,$56,$60,$CB
   
    FOLDERID_UserProgramFilesCommon:
    Data.l $BCBD3057
    Data.w $CA5C,$4622
    Data.b $B4,$2D,$BC,$56,$DB,$0A,$E5,$16
   
    FOLDERID_AdminTools:
    Data.l $724EF170
    Data.w $A42D,$4FEF
    Data.b $9F,$26,$B6,$0E,$84,$6F,$BA,$4F
   
    FOLDERID_CommonAdminTools:
    Data.l $D0384E7D
    Data.w $BAC3,$4797
    Data.b $8F,$14,$CB,$A2,$29,$B3,$92,$B5
   
    FOLDERID_Music:
    Data.l $4BD8D571
    Data.w $6D19,$48D3
    Data.b $BE,$97,$42,$22,$20,$08,$0E,$43
   
    FOLDERID_Videos:
    Data.l $18989B1D
    Data.w $99B5,$455B
    Data.b $84,$1C,$AB,$7C,$74,$E4,$DD,$FC
   
    FOLDERID_Ringtones:
    Data.l $C870044B
    Data.w $F49E,$4126
    Data.b $A9,$C3,$B5,$2A,$1F,$F4,$11,$E8
   
    FOLDERID_PublicPictures:
    Data.l $B6EBFB86
    Data.w $6907,$413C
    Data.b $9A,$F7,$4F,$C2,$AB,$F0,$7C,$C5
   
    FOLDERID_PublicMusic:
    Data.l $3214FAB5
    Data.w $9757,$4298
    Data.b $BB,$61,$92,$A9,$DE,$AA,$44,$FF
   
    FOLDERID_PublicVideos:
    Data.l $2400183A
    Data.w $6185,$49FB
    Data.b $A2,$D8,$4A,$39,$2A,$60,$2B,$A3
   
    FOLDERID_PublicRingtones:
    Data.l $E555AB60
    Data.w $153B,$4D17
    Data.b $9F,$04,$A5,$FE,$99,$FC,$15,$EC
   
    FOLDERID_ResourceDir:
    Data.l $8AD10C31
    Data.w $2ADB,$4296
    Data.b $A8,$F7,$E4,$70,$12,$32,$C9,$72
   
    FOLDERID_LocalizedResourcesDir:
    Data.l $2A00375E
    Data.w $224C,$49DE
    Data.b $B8,$D1,$44,$0D,$F7,$EF,$3D,$DC
   
    FOLDERID_CommonOEMLinks:
    Data.l $C1BAE2D0
    Data.w $10DF,$4334
    Data.b $BE,$DD,$7A,$A2,$0B,$22,$7A,$9D
   
    FOLDERID_CDBurning:
    Data.l $9E52AB10
    Data.w $F80D,$49DF
    Data.b $AC,$B8,$43,$30,$F5,$68,$78,$55
   
    FOLDERID_UserProfiles:
    Data.l $0762D272
    Data.w $C50A,$4BB0
    Data.b $A3,$82,$69,$7D,$CD,$72,$9B,$80
   
    FOLDERID_Playlists:
    Data.l $DE92C1C7
    Data.w $837F,$4F69
    Data.b $A3,$BB,$86,$E6,$31,$20,$4A,$23
   
    FOLDERID_SamplePlaylists:
    Data.l $15CA69B3
    Data.w $30EE,$49C1
    Data.b $AC,$E1,$6B,$5E,$C3,$72,$AF,$B5
   
    FOLDERID_SampleMusic:
    Data.l $B250C668
    Data.w $F57D,$4EE1
    Data.b $A6,$3C,$29,$0E,$E7,$D1,$AA,$1F
   
    FOLDERID_SamplePictures:
    Data.l $C4900540
    Data.w $2379,$4C75
    Data.b $84,$4B,$64,$E6,$FA,$F8,$71,$6B
   
    FOLDERID_SampleVideos:
    Data.l $859EAD94
    Data.w $2E85,$48AD
    Data.b $A7,$1A,$09,$69,$CB,$56,$A6,$CD
   
    FOLDERID_PhotoAlbums:
    Data.l $69D2CF90
    Data.w $FC33,$4FB7
    Data.b $9A,$0C,$EB,$B0,$F0,$FC,$B4,$3C
   
    FOLDERID_Public:
    Data.l $DFDF76A2
    Data.w $C82A,$4D63
    Data.b $90,$6A,$56,$44,$AC,$45,$73,$85
   
    FOLDERID_ChangeRemovePrograms:
    Data.l $DF7266AC
    Data.w $9274,$4867
    Data.b $8D,$55,$3B,$D6,$61,$DE,$87,$2D
   
    FOLDERID_AppUpdates:
    Data.l $A305CE99
    Data.w $F527,$492B
    Data.b $8B,$1A,$7E,$76,$FA,$98,$D6,$E4
   
    FOLDERID_AddNewPrograms:
    Data.l $DE61D971
    Data.w $5EBC,$4F02
    Data.b $A3,$A9,$6C,$82,$89,$5E,$5C,$04
   
    FOLDERID_Downloads:
    Data.l $374DE290
    Data.w $123F,$4565
    Data.b $91,$64,$39,$C4,$92,$5E,$46,$7B
   
    FOLDERID_PublicDownloads:
    Data.l $3D644C9B
    Data.w $1FB8,$4F30
    Data.b $9B,$45,$F6,$70,$23,$5F,$79,$C0
   
    FOLDERID_SavedSearches:
    Data.l $7D1D3A04
    Data.w $DEBB,$4115
    Data.b $95,$CF,$2F,$29,$DA,$29,$20,$DA
   
    FOLDERID_QuickLaunch:
    Data.l $52A4F021
    Data.w $7B75,$48A9
    Data.b $9F,$6B,$4B,$87,$A2,$10,$BC,$8F
   
    FOLDERID_Contacts:
    Data.l $56784854
    Data.w $C6CB,$462B
    Data.b $81,$69,$88,$E3,$50,$AC,$B8,$82
   
    FOLDERID_PublicGameTasks:
    Data.l $DEBF2536
    Data.w $E1A8,$4C59
    Data.b $B6,$A2,$41,$45,$86,$47,$6A,$EA
   
    FOLDERID_GameTasks:
    Data.l $54FAE61
    Data.w $4DD8,$4787
    Data.b $80,$B6,$9,$2,$20,$C4,$B7,$0
   
    FOLDERID_SavedGames:
    Data.l $4C5C32FF
    Data.w $BB9D,$43B0
    Data.b $B5,$B4,$2D,$72,$E5,$4E,$AA,$A4
   
    FOLDERID_Games:
    Data.l $CAC52C1A
    Data.w $B53D,$4EDC
    Data.b $92,$D7,$6B,$2E,$8A,$C1,$94,$34
   
    FOLDERID_SEARCH_MAPI:
    Data.l $98EC0E18
    Data.w $2098,$4D44
    Data.b $86,$44,$66,$97,$93,$15,$A2,$81
   
    FOLDERID_SEARCH_CSC:
    Data.l $EE32E446
    Data.w $31CA,$4ABA
    Data.b $81,$4F,$A5,$EB,$D2,$FD,$6D,$5E
   
    FOLDERID_Links:
    Data.l $BFB9D5E0
    Data.w $C6A9,$404C
    Data.b $B2,$B2,$AE,$6D,$B6,$AF,$49,$68
   
    FOLDERID_UsersFiles:
    Data.l $F3CE0F7C
    Data.w $4901,$4ACC
    Data.b $86,$48,$D5,$D4,$4B,$04,$EF,$8F
   
    FOLDERID_UsersLibraries:
    Data.l $A302545D
    Data.w $DEFF,$464B
    Data.b $AB,$E8,$61,$C8,$64,$8D,$93,$9B
   
    FOLDERID_SearchHome:
    Data.l $190337D1
    Data.w $B8CA,$4121
    Data.b $A6,$39,$6D,$47,$2D,$16,$97,$2A
   
    FOLDERID_OriginalImages:
    Data.l $2C36C0AA
    Data.w $5812,$4B87
    Data.b $BF,$D0,$4C,$D0,$DF,$B1,$9B,$39
   
    FOLDERID_DocumentsLibrary:
    Data.l $7B0DB17D
    Data.w $9CD2,$4A93
    Data.b $97,$33,$46,$CC,$89,$02,$2E,$7C
   
    FOLDERID_MusicLibrary:
    Data.l $2112AB0A
    Data.w $C86A,$4FFE
    Data.b $A3,$68,$D,$E9,$6E,$47,$1,$2E
   
    FOLDERID_PicturesLibrary:
    Data.l $A990AE9F
    Data.w $A03B,$4E80
    Data.b $94,$BC,$99,$12,$D7,$50,$41,$4
   
    FOLDERID_VideosLibrary:
    Data.l $491E922F
    Data.w $5643,$4AF4
    Data.b $A7,$EB,$4E,$7A,$13,$8D,$81,$74
   
    FOLDERID_RecordedTVLibrary:
    Data.l $1A6FDBA2
    Data.w $F42D,$4358
    Data.b $A7,$98,$B7,$4D,$74,$59,$26,$C5
   
    FOLDERID_HomeGroup:
    Data.l $52528A6B
    Data.w $B9E3,$4ADD
    Data.b $B6,$D,$58,$8C,$2D,$BA,$84,$2D
   
    FOLDERID_DeviceMetadataStore:
    Data.l $5CE4A5E9
    Data.w $E4EB,$479D
    Data.b $B8,$9F,$13,$0C,$02,$88,$61,$55
   
    FOLDERID_Libraries:
    Data.l $1B3EA5DC
    Data.w $B587,$4786
    Data.b $B4,$EF,$BD,$1D,$C3,$32,$AE,$AE
   
    FOLDERID_PublicLibraries:
    Data.l $48DAF80B
    Data.w $E6CF,$4F4E
    Data.b $B8,$00,$0E,$69,$D8,$4E,$E3,$84
   
    FOLDERID_UserPinned:
    Data.l $9E3995AB
    Data.w $1F9C,$4F13
    Data.b $B8,$27,$48,$B2,$4B,$6C,$71,$74
   
    FOLDERID_ImplicitAppShortcuts:
    Data.l $BCB5256F
    Data.w $79F6,$4CEE
    Data.b $B7,$25,$DC,$34,$E4,$2,$FD,$46
  EndDataSection
 
EndModule

; Demo

CompilerIf #PB_Compiler_IsMainFile
 
  EnableExplicit
 
  UseModule mAPI
 
  Enumeration #PB_Event_FirstCustomValue
    #WatchDir
  EndEnumeration
  Enumeration #PB_EventType_FirstCustomValue
    #WatchDir_Add
    #WatchDir_Mod
    #WatchDir_Del
    #WatchDir_Rename
  EndEnumeration
 
  ; Show SaveGame Directory Path
  Debug GetKnownFolderPath(#FID_SavedGames)
 
  ; Show Documents Directory Path
  Debug GetKnownFolderPath(#FID_Documents)
 
  ; Set your EventProcedure
  Procedure.i Event_WatchDir()
   
    Protected FileName.s, NewFile.s, OldFile.s
   
    If EventData()
     
      FileName = PeekS(EventData(), -1, #PB_Unicode)
     
      Select EventType()
        Case #WatchDir_Add
          Debug "File " + FileName + " was created in Directory " + GetSuperViserDirectory(EventGadget())
        Case #WatchDir_Mod
          Debug "File " + FileName + " was modified"
        Case #WatchDir_Del
          Debug "File " + FileName + " has been deleted"
        Case #WatchDir_Rename
          OldFile.s = StringField(FileName, 1, ":")
          NewFile.s = StringField(FileName, 2, ":")
          Debug "The File : " + OldFile + " was renamed to " + NewFile
      EndSelect
     
      ; Be sure, that you free the Memory !!! EventData contains an allocated memory block
      FreeMemory(EventData())
     
    EndIf
   
  EndProcedure
  
  Procedure Btn()
    
    StopSuperviseDirectory("C:\")
    Debug "Stop"

  EndProcedure
  
  ; Set your Event and the EventTypes
  Init_SuperVisorDirectory(#WatchDir, #WatchDir_Add, #WatchDir_Mod, #WatchDir_Del, #WatchDir_Rename)
 
  ; Open a window
  OpenWindow(0, 0, 0, 320, 200, "Test", #PB_Window_ScreenCentered|#PB_Window_SystemMenu)
  ButtonGadget(1,10,10,80,20,"Stop Thread")
  
  ; Bind the Event
  BindEvent(#WatchDir, @Event_WatchDir(), 0)
  BindGadgetEvent(1, @Btn())
  
  ; Start SuperVisorDirectory
  StartSuperviseDirectory("C:\", 0, #False)
 
  ; Eventloop
  Repeat : Until WaitWindowEvent() = #PB_Event_CloseWindow
 
  ; Stop SuperVisorDirectory
  StopSuperviseDirectory("C:\")
  
CompilerEndIf
Verbesserungsvorschläge/Kritik ? Immer her damit.

Edit: Dieser Thread ist auch im englischen Forum present.
Zuletzt geändert von Bisonte am 05.08.2018 11:57, insgesamt 9-mal geändert.
PureBasic 6.04 LTS (Windows x86/x64) | Windows10 Pro x64 | Asus TUF X570 Gaming Plus | R9 5900X | 64GB RAM | GeForce RTX 3080 TI iChill X4 | HAF XF Evo | build by vannicom​​
Benutzeravatar
RSBasic
Admin
Beiträge: 8022
Registriert: 05.10.2006 18:55
Wohnort: Gernsbach
Kontaktdaten:

Re: SuperviseDirectory() & GetKnownFolder() [Module][WIN]

Beitrag von RSBasic »

Super :allright:
Aus privaten Gründen habe ich leider nicht mehr so viel Zeit wie früher. Bitte habt Verständnis dafür.
Bild
Bild
oO0XX0Oo
Beiträge: 55
Registriert: 21.07.2017 22:36

Re: SuperviseDirectory() & GetKnownFolder() [Module][WIN]

Beitrag von oO0XX0Oo »

Cool >:)

Gibt es irgendein limit, wie viele Verzeichnisse man gleichzeitig damit überwachen darf?
Benutzeravatar
RSBasic
Admin
Beiträge: 8022
Registriert: 05.10.2006 18:55
Wohnort: Gernsbach
Kontaktdaten:

Re: SuperviseDirectory() & GetKnownFolder() [Module][WIN]

Beitrag von RSBasic »

Du kannst damit schon sehr viele Überwachungen erstellen, aber ist nur die Frage, ob es Sinn ergibt,
Meist überwacht man nur ein Stammverzeichnis oder -laufwerk (Unterordner werden ebenfalls automatisch überwacht) statt viele einzelne Unterordner bzw. hunderte Ordner.
Aber was es für Limitierungen geben kann, wurde in diesem Stackoverflow-Thread gut aufgelistet: https://stackoverflow.com/questions/101 ... 3#10197653
Aus privaten Gründen habe ich leider nicht mehr so viel Zeit wie früher. Bitte habt Verständnis dafür.
Bild
Bild
oO0XX0Oo
Beiträge: 55
Registriert: 21.07.2017 22:36

Re: SuperviseDirectory() & GetKnownFolder() [Module][WIN]

Beitrag von oO0XX0Oo »

Ich hatte eh vor, etwas regelbasiertes zu schreiben (genauer gesagt, zu portieren). Das erfordert aber Regeln pro Ordner (es geht hier z.B. um das automatische Verschieben / Kopieren / Umbenennen / oder generell: eine bestimmte Aktion auslösen, wenn ein Datei- / Ordnerevent auftritt), wobei die Rekursivität einem dabei nicht in die Quere kommen dürfte, z.B.:

Code: Alles auswählen

StartSuperviseDirectory("C:\Windows\Logs\", 0, #NON_RECURSIVE) ; Allgemeine Regeln für alle Ereignisse, .\DISM darf hier nicht eingeschlossen sein
StartSuperviseDirectory("C:\Windows\Logs\DISM\", 0, #RECURSIVE) ; Spezifische Regeln für Ereignisse speziell in diesem Unterordner
Danke für den link, wie man sieht dürfte auch das Überwachen vieler (einzelner) Ordner unproblematisch sein.

@Bisonte:
Ich weiß nicht, ob das überhaupt machbar ist, aber wäre es unter Umständen möglich, die Überwachung zu beschränken (Rekursivität abschalten / Ebenentiefe angeben), evtl. per flag beim Aufruf?

Code: Alles auswählen

Declare.i StartSuperviseDirectory(Directory.s, Window, Level=0)

Level = 0: Rekursiv
Level = 1: Nur das angegebene Verzeichnis (keine Rekursivität)
Level = 2, 3, x: Entsprechend viele Ebenen unterhalb von Directory (eingeschränkte Rekursivität)

Beispiele:
StartSuperviseDirectory("C:\Windows\Logs\", 0) ; Rekursiv
StartSuperviseDirectory("C:\Windows\System32\LogFiles\Firewall\", 0, 1) ; Nur dieses Verzeichnis, keine Unterverzeichnisse
StartSuperviseDirectory("C:\Windows\System32\Sysprep\Panther\, 0, 2) ; Das Verzeichnis + 1 Verzeichnistiefe drunter
Wenn Level = 2, 3, etc. technisch nicht machbar sind: Kein Problem!

Dann könnte man es auch einfach so halten:

Code: Alles auswählen

Declare.i StartSuperviseDirectory(Directory.s, Window, Recursive=#True)

Recursive = #True ; Rekursiv
Recursive = #False ; Nur das angegebene Verzeichnis (keine Rekursivität)
Ginge das und falls ja, könntest du das mit einbauen?
Benutzeravatar
Bisonte
Beiträge: 2427
Registriert: 01.04.2007 20:18

Re: SuperviseDirectory() & GetKnownFolder() [Module][WIN]

Beitrag von Bisonte »

@oO0XX0Oo:Das wäre nur mit einem Aufruf pro Verzeichnis möglich.

Also sagen wir Du hast 1 Verzeichnis mit 2 Unterverzeichnissen. Diese haben je 2 Unterverzeichnisse. Das wären 7 Aufrufe
von StartSuperViseDirectory().
Wäre möglich, geht aber auf die Leistung. Je mehr Verzeichnisse, desto mehr Rechenpower.

Ich werd mich mal dran versuchen.

@all:

Ich habe noch eine komplette Löschung des buffers eingefügt, um evt. Fehler dadurch zu vermeiden.
PureBasic 6.04 LTS (Windows x86/x64) | Windows10 Pro x64 | Asus TUF X570 Gaming Plus | R9 5900X | 64GB RAM | GeForce RTX 3080 TI iChill X4 | HAF XF Evo | build by vannicom​​
Benutzeravatar
RSBasic
Admin
Beiträge: 8022
Registriert: 05.10.2006 18:55
Wohnort: Gernsbach
Kontaktdaten:

Re: SuperviseDirectory() & GetKnownFolder() [Module][WIN]

Beitrag von RSBasic »

@oO0XX0Oo
Du kannst bei ReadDirectoryChangesW_() die Rekursivität auch manuell ausschalten und zwar mit dem Parameter "bWatchSubtree". Entweder auf #True oder #False setzen.
Aus privaten Gründen habe ich leider nicht mehr so viel Zeit wie früher. Bitte habt Verständnis dafür.
Bild
Bild
Benutzeravatar
Bisonte
Beiträge: 2427
Registriert: 01.04.2007 20:18

Re: SuperviseDirectory() & GetKnownFolder() [Module][WIN]

Beitrag von Bisonte »

Oh hab ich da was übersehen ? .... Da muss ich nochmal bei MSDN nachschlagen...
PureBasic 6.04 LTS (Windows x86/x64) | Windows10 Pro x64 | Asus TUF X570 Gaming Plus | R9 5900X | 64GB RAM | GeForce RTX 3080 TI iChill X4 | HAF XF Evo | build by vannicom​​
oO0XX0Oo
Beiträge: 55
Registriert: 21.07.2017 22:36

Re: SuperviseDirectory() & GetKnownFolder() [Module][WIN]

Beitrag von oO0XX0Oo »

@RSBasic
Danke sehr für den Hinweis!

@Bisonte
Nein, lass es uns nicht "überkomplizieren". Vergiss unterschiedliche Verzeichnistiefen.
Das wäre selbst hier ein Spezialfall.

An und abschalten der Rekursivität beim Aufruf von StartSuperviseDirectory() sollte
wohl für 99% der Fälle ausreichen. In meinem Fall wahrscheinlich auch einfach für 100% :allright:
Benutzeravatar
Bisonte
Beiträge: 2427
Registriert: 01.04.2007 20:18

Re: SuperviseDirectory() & GetKnownFolder() [Module][WIN]

Beitrag von Bisonte »

09.03.18 : V1.02 - ADD - Rekursivität ist optinional ein/ausschaltbar
Soweit so gut.
Allerdings immer nur komplett alle Subverzeichnisse in allen Ebenen die innerhalb des "Directory" liegen.
Alles andere wäre wie gesagt nur mit weiteren Aufrufen von StartSuperVise.... möglich.
PureBasic 6.04 LTS (Windows x86/x64) | Windows10 Pro x64 | Asus TUF X570 Gaming Plus | R9 5900X | 64GB RAM | GeForce RTX 3080 TI iChill X4 | HAF XF Evo | build by vannicom​​
Antworten