Here is some better code for diskmonitoring.
For each disk to monitor a thread is created. The thread terminates as soon as disk activity is less the limit.
Because of restriction to threaded function you have to pass the limit multiplied by 100 to the thread. Disk activity is measured disk access/minute for each disk. When the thread function terminates the last activity value is passed, so store it before you close the thread. If you want to use removable disk, be careful, check if a medium is inserted before you bring up the corresponding thread.
Have fun with the code:
Code:
#COMPILE EXE #DIM ALL #INCLUDE "win32api.inc" 'GLOBAL gLock AS CRITICAL_SECTION GLOBAL gKillThreads AS LONG MACRO ActiveWait IF PeekMessage (MSG, %NULL, 0,0, %PM_REMOVE) THEN TranslateMessage MSG DispatchMessage MSG END IF END MACRO '------------------------------------------------------------------------------- ' Function thDiskActivity ' threaded disk activity check ' thread ends up automatically when HDD activity decreases below limit ' in DrvAct: drive to observe, 0=cancel/end, 1=A:, 2=B:,... ' DrvAct \ 100 => HDD-activity-limit (disk hits / minute) ' out DrvAct: activity => THREAD STATUS '------------------------------------------------------------------------------- FUNCTION thDiskActivity(BYVAL DrvAct AS LONG) AS LONG ON ERROR GOTO EndThread LOCAL hDir AS DWORD LOCAL ret AS DWORD LOCAL drv AS ASCIIZ * 4 LOCAL t, td AS QUAD LOCAL i AS LONG LOCAL hitCount AS LONG LOCAL MSG AS tagMSG LOCAL HDDAct AS LONG LOCAL HDDAct1 AS LONG LOCAL ActLimit AS LONG 'fill activity limits ActLimit = DrvAct \ 100 HDDAct = ActLimit HDDAct1 = ActLimit 'build drive letter drv = CHR$(DrvAct-HDDAct*100+64) + ":\" hitCount = 0 MSGBOX "observing " + drv + " low-activity-limit:"+STR$(HDDAct) t = TIMER DO hDir = FindFirstChangeNotification(drv, %True, _ %FILE_NOTIFY_CHANGE_SIZE OR _ %FILE_NOTIFY_CHANGE_FILE_NAME OR _ %FILE_NOTIFY_CHANGE_DIR_NAME OR _ %FILE_NOTIFY_CHANGE_LAST_WRITE OR _ %FILE_NOTIFY_CHANGE_LAST_ACCESS OR _ %FILE_NOTIFY_CHANGE_CREATION) DO ret = WaitForSingleObject(hDir, 200) ActiveWait td = TIMER - t 'EnterCriticalSection(gLock) IF gKillThreads = %True OR HDDAct < ActLimit THEN GOTO EndThread END IF IF td > 9 THEN HDDAct1= HDDAct HDDAct = (hitCount * 6 + HDDAct1) / 2 'MSGBOX "hitCount/HDD-activity per minute:"+STR$(hitCount)+" / "+STR$(HDDAct) hitCount = 0 t = TIMER END IF 'LeaveCriticalSection(gLock) LOOP WHILE ret <> 0 DO INCR hitCount 'EnterCriticalSection(gLock) IF gKillThreads = %True OR HDDAct < ActLimit THEN GOTO EndThread END IF 'td = TIMER - t 'HDDAct1= HDDAct 'HDDAct = (hitCount * 6 + HDDAct1) / 2 'MSGBOX "change: hits="+STR$(hitCount)+" time="+STR$(td)+" / activity="+STR$(HDDAct) ' IF td > 9 THEN ' hitCount = 0 ' t = TIMER ' END IF 'LeaveCriticalSection(gLock) ret = FindNextChangeNotification(hDir) ret = WaitForSingleObject(hDir, 200) EXIT DO LOOP 'ActiveWait LOOP EndThread: 'LeaveCriticalSection(gLock) ret = FindCloseChangeNotification( hDir ) 'msgbox drv + " Thread terminated regularily. HDDAct="+str$(HDDAct) FUNCTION = HDDAct END FUNCTION '----------------------------------------------------------------------- ' Function GetLocalDrives ' retrieve all local attached driveletters as one string ' you can add a filter with one or more elements (use OR) ' in optional Filter, Filter2, Filter3, Filter4, Filter5 ' %DRIVE_REMOVABLE The drive can be removed from the drive. ' %DRIVE_FIXED The disk cannot be removed from the drive. ' %DRIVE_REMOTE The drive is a remote (network) drive. ' %DRIVE_CDROM The drive is a CD-ROM drive. ' %DRIVE_RAMDISK The drive is a RAM disk. ' out string with driveletters '------------------------------------------------------------------------ FUNCTION GetAllDrivesString(OPT BYVAL Filter AS LONG, _ OPT BYVAL Filter2 AS LONG, _ OPT BYVAL Filter3 AS LONG, _ OPT BYVAL Filter4 AS LONG, _ OPT BYVAL Filter5 AS LONG) AS STRING LOCAL i AS LONG LOCAL buffer AS STRING LOCAL chz AS ASCIIZ * 3 LOCAL ch AS STRING LOCAL AllDrives AS STRING LOCAL FilterDrives AS STRING LOCAL ret AS LONG LOCAL nResult AS LONG ret = GetLogicalDriveStrings(0, BYVAL %Null) buffer = STRING$(ret, $NUL) nResult = GetLogicalDriveStrings( ret, BYVAL STRPTR(buffer)) AllDrives = REMOVE$( buffer, ANY ":\"+CHR$(0)) IF Filter = 0 THEN FUNCTION = AllDrives ELSE ret = LEN(AllDrives) FOR i = 1 TO ret ch = MID$(AllDrives,i,1) chz= ch + ":" ret = GetDriveType(chz) IF ret > 1 AND (ret = Filter OR ret = Filter2 OR ret = Filter3 OR ret = Filter4 OR ret = Filter5) THEN FilterDrives = FilterDrives + ch END IF NEXT i FUNCTION = FilterDrives END IF END FUNCTION '############################################################################### FUNCTION PBMAIN() AS LONG ON ERROR GOTO eOut LOCAL hThread() AS LONG LOCAL lState() AS LONG LOCAL lResult AS LONG LOCAL i, sum AS LONG LOCAL Mittel AS LONG LOCAL sText AS STRING LOCAL ObsDrv AS STRING LOCAL ObsDrvCount AS LONG LOCAL elem AS STRING LOCAL DrvNr AS LONG LOCAL MaxHDD AS LONG DIM hThread(1 TO 26) DIM lState( 1 TO 26) 'ObsDrv = GetAllDrivesString(%DRIVE_FIXED) ObsDrv = "C" ObsDrvCount = LEN(ObsDrv) MaxHDD= 15 'max. disk changes/minute 'bring up threads FOR i = 1 TO ObsDrvCount elem = MID$(ObsDrv,i,1) DrvNr = ASC(elem)-64 + MaxHDD * 100 THREAD CREATE thDiskActivity(DrvNr) TO hThread(i) NEXT i SLEEP 100 'lResult = MSGBOX("Überwachung beenden mit OK.", %MB_OK, "Observing Disk "+CHR$(DrvNr)+":") 'Wait until threads ended regular sum = 0 FOR i = 1 TO ObsDrvCount THREAD STATUS hThread(i) TO lState(i) DO WHILE lState(i) = &H103 SLEEP 100 THREAD STATUS hThread(i) TO lState(i) LOOP THREAD STATUS hThread(i) TO lState(i) sum = sum + lState(i) THREAD CLOSE hThread(i) TO lResult NEXT i Mittel = sum / ObsDrvCount IF Mittel < MaxHDD THEN MSGBOX "Stopped because of low disk activity: Hits/Min.:"+STR$(Mittel) + $CRLF + sText ELSE MSGBOX "User initiated stop: Hits/Min.:"+STR$(Mittel) + $CRLF + sText END IF 'DeleteCriticalSection(gLock) EXIT FUNCTION eOut: MSGBOX "Error occured:"+STR$(ERR) + " " + ERROR$(ERR) RESUME NEXT END FUNCTION
Leave a comment: