Sign in to follow this  
Followers 0
jazzyjeff

Estimate time remaining

6 posts in this topic

Hey All,

 

I am working on a script that will estimate how much time is remaining in a loop. To go a bit deeper, the script scans multiple folders for the permissions and the saves those permissions in a log. What I am looking for is to get an estimation of how long it will take to finish checking all the directories for permissions. I have the percentage calculations correct, but I feel like the time is creeping up, rather than coming down.

Here is my code for the script.

#include <Array.au3>
#include <File.au3>

MsgBox(0,"Permissions Search","You will be prompted first to enter a location to scan the permissions, and then you will need to select a location to save the log file.")
$fPath = FileSelectFolder("Select folder to search", "C:\")
SplashTextOn("Permission Search","Scanning directories to search...",220,70)
$arrayFolder = _FileListToArrayRec($fPath, "*", 14, 1, 0, 2)
SplashOff()
;_ArrayDisplay($arrayFolder)
Dim $arrayFinal[1][8]
;_ArrayDisplay($arrayFinal)
$lPath = FileSelectFolder("Select where to save the log file", "C:\")
$fOpen = FileOpen($lPath & "\Permissions_Log.csv",10)
FileWriteLine($fOpen,"User or Group,Path Number,Path,Inherited by Directories,Inherited by Files,Inherit Only,Inherited from Parent")
$percent = 0
$progress = ProgressOn("Permission Search", "Scanning Directory for permissions", $percent & "%","","",16)
$timeTaken = TimerInit()
$timeLoopEnd = 1; Estimating 1 second per loop for timer
For $i = 1 To $arrayFolder[0]
    $percent = $i / $arrayFolder[0] * 100 ; Calculate the percentage
    $timeRemaining = $timeLoopEnd * ($arrayFolder[0] - $i) ; 1 less item to scan so the countdown should be less
    $timeRemaining = $timeRemaining / 1000 ; Update Time in milliseconds to seconds remaining
    If $timeRemaining >= 60 Then ; If estimated time is minutes
        $timeRemainingMinutes = Round($timeRemaining/60,0)
        $timeRemainingSeconds = Mod($timeRemaining,60)
        ProgressSet($percent,$i & " of " & $arrayFolder[0] & " - " & Round($percent,1) & "% - " & $timeRemainingMinutes & " minutes and " & Round($timeRemainingSeconds,0) & " secs remaining" & @CRLF & $arrayFolder[$i])
    ElseIf $timeRemaining >= 3600 Then ; If estimated time is hours
        $timeRemainingHours = Round(($timeRemaining/60)/60,0)
        $timeRemainingMinutes = Mod($timeRemaining,60)
        ProgressSet($percent,$i & " of " & $arrayFolder[0] & " - " & Round($percent,1) & "% - " & $timeRemainingHours & " hours and " & Round($timeRemainingMinutes,0) & " minutes remaining" & @CRLF & $arrayFolder[$i])
    Else ; If estimated time is seconds
        $timeRemainingSeconds = $timeRemaining
        ProgressSet($percent,$i & " of " & $arrayFolder[0] & " - " & Round($percent,1) & "% - " & Round($timeRemainingSeconds,0) & " secs remaining" & @CRLF & $arrayFolder[$i])
    EndIf
    $timeRemaining = 0
    $timeLoopEnd = 0
    $timeRemainingHours = 0
    $timeRemainingMinutes = 0
    $timeRemainingSeconds = 0
    $timeLoopStart = TimerInit() ; Start calculating how long to complete a loop
    Local $iPID = Run(@ComSpec & ' /C cacls "' & $arrayFolder[$i] & '"', "", @SW_HIDE, $STDOUT_CHILD)
    ProcessWaitClose($iPID)
    Local $sOutput = StdoutRead($iPID)
    $sOutput = StringReplace($sOutput, $arrayFolder[$i], "")
    $sOutput = StringSplit($sOutput, @CR)
    If IsArray($sOutput) Then
        ;_ArrayDisplay($sOutput)
        Dim $array[$sOutput[0] + 1]
        For $x = 1 To $sOutput[0]
            ;MsgBox(0,$x,$sOutput[$x])
            $y = StringStripWS($sOutput[$x],4)
            $y = StringStripCR($y)
            If StringLeft($y, 1) = " " Then
                StringTrimLeft($y,1)
            EndIf
            ;MsgBox(0,$x,$y)
            $array[$x] = $y
            If StringIsSpace($array[$x]) Or $array[$x] = "" Then
                _ArrayDelete($array,$x)
                ;_ArrayDisplay($array, $x & "Empty value - Before")
                If $x = UBound($array) Then
                    $array[0] =  UBound($array) -1
                    ExitLoop
                Else
                    $x = $x - 1
                EndIf
            EndIf
        Next
        ;_ArrayDisplay($array,"Array")
        For $z = 1 To $array[0]
            $string = StringSplit($array[$z],":")
            If IsArray($string) Then
                If $string[0] > 0 Then
                    ;_ArrayDisplay($string,"String Array")
                    _ArrayAdd($arrayFinal,$string[1],0); user name or group

                Else
                    _ArrayAdd($arrayFinal,"Unknown user or group",0)
                EndIf
            Else
                _ArrayAdd($arrayFinal,"Unknown user or group",0)
            EndIf
            $v = UBound($arrayFinal) -1
            $arrayFinal[$v][1] = $i ; ID Number
            $arrayFinal[$v][2] = $arrayFolder[$i] ; File Path
            If StringInStr($array[$z], "(CI)") Then
                $arrayFinal[$v][3] = 1; CI - Container Inherit... The ACE will be inherited by directories
            Else
                $arrayFinal[$v][3] = 0
            EndIf
            If StringInStr($array[$z], "(OI)") Then
                $arrayFinal[$v][4] = 1; OI - Object Inherit... The ACE will be inherited by files
            Else
                $arrayFinal[$v][4] = 0
            EndIf
            If StringInStr($array[$z], "(IO)") Then
                $arrayFinal[$v][5] = 1; IO - Inherit Only... The ACE does not apply to the current file/directory
            Else
                $arrayFinal[$v][5] = 0
            EndIf
            If StringInStr($array[$z], "(ID)") Then
                $arrayFinal[$v][6] = 1; ID - Inheritrf... The ACE was inherited from the parent directory's ACL
            Else
                $arrayFinal[$v][6] = 0
            EndIf
            $stringStrip = StringStripWS($array[$z],2)
            If StringRight($stringStrip, 1) = "N" Then ; The permissions set. e.g. None, Read, Write, Change, Full Control
                $arrayFinal[$v][7] = "None"
            ElseIf StringRight($stringStrip, 1) = "R" Then
                $arrayFinal[$v][7] = "Read"
            ElseIf StringRight($stringStrip, 1) = "W" Then
                $arrayFinal[$v][7] = "Write"
            ElseIf StringRight($stringStrip, 1) = "C" Then
                $arrayFinal[$v][7] = "Change"
            ElseIf StringRight($stringStrip, 1) = "F" Then
                $arrayFinal[$v][7] = "Full Control"
            Else
                $arrayFinal[$v][7] = "None"
            EndIf
            FileWriteLine($fOpen,$arrayFinal[$v][0] & "," & $arrayFinal[$v][1] & "," & $arrayFinal[$v][2] & "," & $arrayFinal[$v][3] & "," & $arrayFinal[$v][4] & "," & $arrayFinal[$v][5] & "," & $arrayFinal[$v][6] & "," & $arrayFinal[$v][7])
        Next
    Else
        $array = $sOutput
        ;_ArrayDisplay($sOutput,$arrayFolder[$i])
    EndIf
    $timeLoopEnd = TimerDiff($timeLoopStart)
Next
ProgressSet(100,"Scan Complete",$arrayFolder[0] & " of " & $arrayFolder[0])
FileClose($fOpen)
ProgressOff()
$timer = TimerDiff($timeTaken) / 1000
If $timer >= 60 Then
    $timerMinutes = Round($timer/60, 0)
    $timerSeconds = Mod($timer, 60)
    If $timerMinutes > 1 Then
        MsgBox(0,"Complete","The permission scan is complete." & @CR & @CRLF & "The log file is located here: " & $lPath & "\Permissions_Log.csv" & @CR & @CRLF & "Time taken: " & $timerMinutes & " minutes and " & $timerSeconds & " seconds." )
    Else
        MsgBox(0,"Complete","The permission scan is complete." & @CR & @CRLF & "The log file is located here: " & $lPath & "\Permissions_Log.csv" & @CR & @CRLF & "Time taken: " & $timerMinutes & " minute and " & $timerSeconds & " seconds." )
    EndIf
Else
    MsgBox(0,"Complete","The permission scan is complete." & @CR & @CRLF & "The log file is located here: " & $lPath & "\Permissions_Log.csv" & @CR & @CRLF & "Time taken: " & $timerSeconds & " seconds." )
EndIf
_ArrayDisplay($arrayFinal,"Final Array")

 

This is the part of the script that is probably of interest for the time calculations.

$timeLoopEnd = 1; Estimating 1 second per loop for timer
For $i = 1 To $arrayFolder[0]
    $percent = $i / $arrayFolder[0] * 100 ; Calculate the percentage
    $timeRemaining = $timeLoopEnd * ($arrayFolder[0] - $i) ; 1 less item to scan so the countdown should be less
    $timeRemaining = $timeRemaining / 1000 ; Update Time in milliseconds to seconds remaining
    If $timeRemaining >= 60 Then ; If estimated time is minutes
        $timeRemainingMinutes = Round($timeRemaining/60,0)
        $timeRemainingSeconds = Mod($timeRemaining,60)
        ProgressSet($percent,$i & " of " & $arrayFolder[0] & " - " & Round($percent,1) & "% - " & $timeRemainingMinutes & " minutes and " & Round($timeRemainingSeconds,0) & " secs remaining" & @CRLF & $arrayFolder[$i])
    ElseIf $timeRemaining >= 3600 Then ; If estimated time is hours
        $timeRemainingHours = Round(($timeRemaining/60)/60,0)
        $timeRemainingMinutes = Mod($timeRemaining,60)
        ProgressSet($percent,$i & " of " & $arrayFolder[0] & " - " & Round($percent,1) & "% - " & $timeRemainingHours & " hours and " & Round($timeRemainingMinutes,0) & " minutes remaining" & @CRLF & $arrayFolder[$i])
    Else ; If estimated time is seconds
        $timeRemainingSeconds = $timeRemaining
        ProgressSet($percent,$i & " of " & $arrayFolder[0] & " - " & Round($percent,1) & "% - " & Round($timeRemainingSeconds,0) & " secs remaining" & @CRLF & $arrayFolder[$i])
    EndIf

I understand this more of a math problem, but I am having a hard time figuring it out. I'm hoping another set of eyes will be able to help.

 

Thanks,

 

Jeff

Share this post


Link to post
Share on other sites



It would be FAR easier to just use a progress bar without trying to figure out the time remaining too. Ever heard of Microsoft Time? I haven't seen an OS or program that gets the time remaining accurate enough to ever really pay attention to it.


If I posted any code, assume that code was written using the latest release version unless stated otherwise. Also, if it doesn't work on XP I can't help with that because I don't have access to XP, and I'm not going to.
Give a programmer the correct code and he can do his work for a day. Teach a programmer to debug and he can do his work for a lifetime - by Chirag Gude
How to ask questions the smart way!

I hereby grant any person the right to use any code I post, that I am the original author of, on the autoitscript.com forums, unless I've specifically stated otherwise in the code or the thread post. If you do use my code all I ask, as a courtesy, is to make note of where you got it from.

Back up and restore Windows user files _Array.au3 - Modified array functions that include support for 2D arrays.  -  ColorChooser - An add-on for SciTE that pops up a color dialog so you can select and paste a color code into a script.  -  Customizable Splashscreen GUI w/Progress Bar - Create a custom "splash screen" GUI with a progress bar and custom label.  -  _FileGetProperty - Retrieve the properties of a file  -  SciTE Toolbar - A toolbar demo for use with the SciTE editor  -  GUIRegisterMsg demo - Demo script to show how to use the Windows messages to interact with controls and your GUI.  -   Latin Square password generator

Share this post


Link to post
Share on other sites

#3 ·  Posted (edited)

Hi Jazzyjeff. One mistake you're making is in the conversions to minutes and hours. First you round to minutes or hours (which may go up or down), and then you calculate the remainder (as if you always rounded down). So use Floor or Int instead there.

Edited by RTFC

Share this post


Link to post
Share on other sites

haha BrewManNH. Yes, I know the time isn't going to be terribly accurate, but it gives a rough idea of how long you may have to wait.

 

Thanks RTFC. I will look at that and see how it works.

Share this post


Link to post
Share on other sites

You could just timerinit() when you started, and at any point 
$timesofar = timerdiff($inittime)
$timesofar / 100 * (100 - $percentDone) = approx time remaining
It won't be accurate for any task that runs at a non-linear speed, but for a rough idea it should work.


0x616e2069646561206973206c696b652061206d616e20776974686f7574206120626f64792c20746f206669676874206f6e6520697320746f206e657665722077696e2e2e2e2e

Share this post


Link to post
Share on other sites

Well, I got the time counting down, and it was "sort of close". Well I mean it started out at 80 minutes and it finished with 13 minutes to go :-)

Here is the final code I had. I'm going to try an tweak it a little further, but it seems a pain to do so I won't worry about it too much more. At the end it tells me how long it ran which is nice. Thanks for everyone's input.

#Region ;**** Directives created by AutoIt3Wrapper_GUI ****
#AutoIt3Wrapper_Outfile=C:\Temp\Permission Finder.Exe
#EndRegion ;**** Directives created by AutoIt3Wrapper_GUI ****
#include <Array.au3>
#include <File.au3>

MsgBox(0,"Permissions Search","You will be prompted first to enter a location to scan the permissions, and then you will need to select a location to save the log file.")
$fPath = FileSelectFolder("Select folder to search", "C:\")
SplashTextOn("Permission Search","Scanning directories to search...",220,70)
$arrayFolder = _FileListToArrayRec($fPath, "*", 14, 1, 0, 2)
SplashOff()
;_ArrayDisplay($arrayFolder)
Dim $arrayFinal[1][8]
;_ArrayDisplay($arrayFinal)
$lPath = FileSelectFolder("Select where to save the log file", "C:\")
$fOpen = FileOpen($lPath & "\Permissions_Log.csv",10)
FileWriteLine($fOpen,"User or Group,Path Number,Path,Inherited by Directories,Inherited by Files,Inherit Only,Inherited from Parent")
$percent = 0
$progress = ProgressOn("Permission Search", "Scanning Directory for permissions", $percent & "%","","",16)
$timeTaken = TimerInit()
$timeLoopEnd = 0.4; Estimating time in second per loop for timer on initial launch
$timeStarted = @HOUR & ":" & @MIN & ":" & @SEC
For $i = 1 To $arrayFolder[0]
    $percent = $i / $arrayFolder[0] * 100 ; Calculate the percentage
    If $i = 1 Then
        $timeRemaining = $arrayFolder[0];$timeLoopEnd* ($arrayFolder[0])
    Else
        $timeLoopEnd = $timeLoopEnd/1000
        $timeRemaining = $timeRemaining-$timeLoopEnd
    EndIf
    ;$timeRemaining = $timeRemaining / 1000 ; Update Time in milliseconds to seconds remaining
    If $timeRemaining >= 60 Then ; If estimated time is minutes
        $timeRemainingMinutes = Int($timeRemaining)/60
        $timeRemainingSeconds = Mod($timeRemaining,60)
        ProgressSet($percent,$i & " of " & $arrayFolder[0] & " - " & Round($percent,1) & "% - " & Round($timeRemainingMinutes,0) & " minutes and " & Round($timeRemainingSeconds,0) & " secs remaining" & @CRLF & $arrayFolder[$i])
    ElseIf $timeRemaining >= 3600 Then ; If estimated time is hours
        $timeRemainingHours = (Int($timeRemaining)/60)/60
        $timeRemainingMinutes = Mod($timeRemaining,60)
        ProgressSet($percent,$i & " of " & $arrayFolder[0] & " - " & Round($percent,1) & "% - " & Round($timeRemainingHours,0) & " hours and " & Round($timeRemainingMinutes,0) & " minutes remaining" & @CRLF & $arrayFolder[$i])
    Else ; If estimated time is seconds
        $timeRemainingSeconds = $timeRemaining
        ProgressSet($percent,$i & " of " & $arrayFolder[0] & " - " & Round($percent,1) & "% - " & Round($timeRemainingSeconds,0) & " secs remaining" & @CRLF & $arrayFolder[$i])
    EndIf
    $timeLoopEnd = 0
    $timeRemainingHours = 0
    $timeRemainingMinutes = 0
    $timeRemainingSeconds = 0
    $timeLoopStart = TimerInit() ; Start calculating how long to complete a loop
    Local $iPID = Run(@ComSpec & ' /C cacls "' & $arrayFolder[$i] & '"', "", @SW_HIDE, $STDOUT_CHILD)
    ProcessWaitClose($iPID)
    Local $sOutput = StdoutRead($iPID)
    $sOutput = StringReplace($sOutput, $arrayFolder[$i], "")
    $sOutput = StringSplit($sOutput, @CR)
    If IsArray($sOutput) Then
        ;_ArrayDisplay($sOutput)
        Dim $array[$sOutput[0] + 1]
        For $x = 1 To $sOutput[0]
            ;MsgBox(0,$x,$sOutput[$x])
            $y = StringStripWS($sOutput[$x],4)
            $y = StringStripCR($y)
            If StringLeft($y, 1) = " " Then
                StringTrimLeft($y,1)
            EndIf
            ;MsgBox(0,$x,$y)
            $array[$x] = $y
            If StringIsSpace($array[$x]) Or $array[$x] = "" Then
                _ArrayDelete($array,$x)
                ;_ArrayDisplay($array, $x & "Empty value - Before")
                If $x = UBound($array) Then
                    $array[0] =  UBound($array) -1
                    ExitLoop
                Else
                    $x = $x - 1
                EndIf
            EndIf
        Next
        ;_ArrayDisplay($array,"Array")
        For $z = 1 To $array[0]
            $string = StringSplit($array[$z],":")
            If IsArray($string) Then
                If $string[0] > 0 Then
                    ;_ArrayDisplay($string,"String Array")
                    _ArrayAdd($arrayFinal,$string[1],0); user name or group

                Else
                    _ArrayAdd($arrayFinal,"Unknown user or group",0)
                EndIf
            Else
                _ArrayAdd($arrayFinal,"Unknown user or group",0)
            EndIf
            $v = UBound($arrayFinal) -1
            $arrayFinal[$v][1] = $i ; ID Number
            $arrayFinal[$v][2] = $arrayFolder[$i] ; File Path
            If StringInStr($array[$z], "(CI)") Then
                $arrayFinal[$v][3] = 1; CI - Container Inherit... The ACE will be inherited by directories
            Else
                $arrayFinal[$v][3] = 0
            EndIf
            If StringInStr($array[$z], "(OI)") Then
                $arrayFinal[$v][4] = 1; OI - Object Inherit... The ACE will be inherited by files
            Else
                $arrayFinal[$v][4] = 0
            EndIf
            If StringInStr($array[$z], "(IO)") Then
                $arrayFinal[$v][5] = 1; IO - Inherit Only... The ACE does not apply to the current file/directory
            Else
                $arrayFinal[$v][5] = 0
            EndIf
            If StringInStr($array[$z], "(ID)") Then
                $arrayFinal[$v][6] = 1; ID - Inheritrf... The ACE was inherited from the parent directory's ACL
            Else
                $arrayFinal[$v][6] = 0
            EndIf
            $stringStrip = StringStripWS($array[$z],2)
            If StringRight($stringStrip, 1) = "N" Then ; The permissions set. e.g. None, Read, Write, Change, Full Control
                $arrayFinal[$v][7] = "None"
            ElseIf StringRight($stringStrip, 1) = "R" Then
                $arrayFinal[$v][7] = "Read"
            ElseIf StringRight($stringStrip, 1) = "W" Then
                $arrayFinal[$v][7] = "Write"
            ElseIf StringRight($stringStrip, 1) = "C" Then
                $arrayFinal[$v][7] = "Change"
            ElseIf StringRight($stringStrip, 1) = "F" Then
                $arrayFinal[$v][7] = "Full Control"
            Else
                $arrayFinal[$v][7] = "None"
            EndIf
            $stringFinal = StringStripCR($arrayFinal[$v][0] & "," & $arrayFinal[$v][1] & "," & $arrayFinal[$v][2] & "," & $arrayFinal[$v][3] & "," & $arrayFinal[$v][4] & "," & $arrayFinal[$v][5] & "," & $arrayFinal[$v][6] & "," & $arrayFinal[$v][7])
            $stringFinal = StringStripWS($stringFinal,3)
            FileWriteLine($fOpen,$stringFinal)
        Next
    Else
        $array = $sOutput
        ;_ArrayDisplay($sOutput,$arrayFolder[$i])
    EndIf
    $timeLoopEnd = TimerDiff($timeLoopStart)
Next
ProgressSet(100,"Scan Complete",$arrayFolder[0] & " of " & $arrayFolder[0])
FileClose($fOpen)
ProgressOff()
$timer = TimerDiff($timeTaken) / 1000
If $timer >= 60 Then
    $timerMinutes = Round($timer/60, 0)
    $timerSeconds = Mod($timer, 60)
    If $timerMinutes > 1 Then
        MsgBox(0,"Complete","The permission scan is complete." & @CR & @CRLF & "The log file is located here: " & $lPath & "\Permissions_Log.csv" & @CR & @CRLF & "Time Started: " & $timeStarted & @CRLF & "Time Finished: " & @HOUR & ":" & @MIN & ":" & @SEC & @CRLF & "Time taken: " & $timerMinutes & " minutes and " & Round($timerSeconds,0) & " seconds." )
    ElseIf $timerMinutes > 60 Then
        $timerHours = Floor($timerMinutes)
        $timerMinutes = Mod($timerMinutes,60)
        MsgBox(0,"Complete","The permission scan is complete." & @CR & @CRLF & "The log file is located here: " & $lPath & "\Permissions_Log.csv" & @CR & @CRLF & "Time Started: " & $timeStarted & @CRLF & "Time Finished: " & @HOUR & ":" & @MIN & ":" & @SEC & @CRLF & "Time taken: " & $timerHours & " hours and " & Round($timerMinutes,0) & " minutes." )
    Else
        MsgBox(0,"Complete","The permission scan is complete." & @CR & @CRLF & "The log file is located here: " & $lPath & "\Permissions_Log.csv" & @CR & @CRLF & "Time Started: " & $timeStarted & @CRLF & "Time Finished: " & @HOUR & ":" & @MIN & ":" & @SEC & @CRLF & "Time taken: " & $timerMinutes & " minute and " & Round($timerSeconds,0) & " seconds." )
    EndIf
Else
    MsgBox(0,"Complete","The permission scan is complete." & @CR & @CRLF & "The log file is located here: " & $lPath & "\Permissions_Log.csv" & @CR & @CRLF & "Time Started: " & $timeStarted & @CRLF & "Time Finished: " & @HOUR & ":" & @MIN & ":" & @SEC & @CRLF & "Time taken: " & Round($timer,0) & " seconds." )
EndIf
_ArrayDisplay($arrayFinal,"Final Array")

 

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