Jump to content

PMS


laidback01
 Share

Recommended Posts

This is my first useful script. Its in use at our facility. Thanks belongs to autoit, the forums, and the people who answered my questions. I used code from the Help File, Koshy John's hd maintenance script, and someone else's DiskMax. Script is still really rather young, and not complete - hence the v0.3, but it's a work in progress, and maybe someone else can get some use out of it.

again thanks, and I will post more at time goes on.

#cs **********

Preventative Maintenance System

Written By: Jack

16 Jan 2008

Call this program from command line as such:  <path>\pms.exe <choice>
the content you put after the command line is optional, if you put nothing, the system will bring up a GUI and run interactively.
If, however, you give it a number 0 to 16, it will perform various functions.

In Binary:    Decimal:
0 0 0 0 0 0  =0               Leftmost column is Bit1 and rightmost column is Bit5, the others follow accordingly.
0 0 0 0 0 1  =1               A "1" in a column is a "Yes" or "Affirmative".  A "0" in a column is a "No" or Negative
0 0 0 0 1 0  =2               bit0 is for GUI
0 0 0 0 1 1  =3               bit1 is for Defrag
0 0 0 1 0 0  =4               bit2 is for DiskClean
0 0 0 1 0 1  =5               bit3 is for UserClean
0 0 0 1 1 0  =6               bit4 is for WindowsUpdates
0 0 0 1 1 1  =7               bit5 is for PageFile
0 0 1 0 0 0  =8               
0 0 1 0 0 1  =9
0 0 1 0 1 0  =10
0 0 1 0 1 1  =11

and so on... please determine the right combo on your own.
0 1 1 1 1 1  =95; No GUI, do everything else (basically silent operation)
1 0 0 0 0 0  =96  ; you might as well just double click the exe, as it's the same result - run the GUI, select nothing.
1 1 1 1 1 1  =127 ; don't exceed 127, it'll just drop to 127. This means run the GUI and preselect everything.

#ce **********

#cs **********
INCLUDES, OPTIONS & VARIABLES
#ce **********
#include <GUIConstants.au3>
#include <Array.au3>

Opt("TrayIconHide", 1)
Opt("RunErrorsFatal", 0) ; Don't really need this script quitting because Run or RunWait freaked out.
Opt("TrayIconDebug", 0)
Opt('MustDeclareVars', 1)

Global $version="PMS v0.3", $scrollText[16], $scrollPos=0, $needReboot=0
Global $svr="\\autoit", $share="\PMS", $user="user", $pass="pass"
Global $localLog=@TempDir ; For the case that the machine this script runs on is not able to log to the autoit server.
Global $REG_pageFileLoc="HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\Memory Management", $REG_pageFileName="PagingFiles" ; page file key information
Global $localDriveLetter="T:" ; T: is one we don't use much in KRMC... so why not wink.gif
Global $hdd="c:", $choice[6], $drivemapped=0
; IF YOU MODIFIY THIS ARRAY, YOU NEED TO MODIFY THE SELECT STATEMENT BELOW AND CREATE CORRESPONDING FUNCTIONS...
Global $choices[6][3] = [["Gui",0,0],["Clean Temp Files, Recycle Bin",0,0],["Set Virtual Memory Correctly",0,0],["Clean User Profiles",0,0],["Windows Updates - Broken",0,0],["Run Defrag (generally takes a long time)",0,0]]
Global Const $arrayend = 5 ; the array starts at 0 always.  Make sure you change this to 1 less than your max size if you change the amount of options.
Global $count ; needed this for the handles and setting GUICtrlSetOnEvent for the checkboxes
Global Const $test = 0  ; set to 0 to have script actually do anything besides mount/umount drives and some logging.
Global $pfkeyloc="HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\Memory Management" ; Paging File Registry Keys
Global $pfkeyname="PagingFiles" ; Paging File Registry Keys

Local  $mem="", $pagefilesize=0, $i=0, $buffer=0

; Check for XP First of all.
if @OSVersion <> "WIN_XP" Then
    MsgBox(0,"Damn!","Sorry, I can't support anything but Windows XP so far...")
    Exit
endif

; Read the first argument from the command line
if $cmdline[0] > 0 Then ; Check to see that there is at least one arg.
    $buffer = $cmdline[1] ; because we cannot modify $cmdline
    if StringRegExp($buffer,"^\d+$") then ; this tests for positive integers
        if ( $buffer > 127) Then
            $buffer = 127 ; keep it sane
        EndIf
        $choice = bin($buffer) ; retrieve the array
        for $i=0 to $arrayend
            $choices[$i][1]=$choice[$i] ; modify the main array accordingly
        Next
    Else
        logthis("Use a number between 1 and 127", $localLog)
        exit
    endif
EndIf
; Maybe later check for more than one $cmdline argument, and use those for something else handy.
   
; However, if it's just clicked on from the icon, start the gui, but just wait for the user.
if $cmdline[0]=0 Then
    $choices[0][1]=1
    for $i=1 to $arrayend ; starting from 1 because the "gui" is a func that's marked int the array as well, perhaps not the best way to do this...
        $choices[$i][1]=0 ; default them all.
    Next
EndIf

; map the drives - so we can log and do windows updates
mapAutoIT($localDriveLetter)

if $choices[0][1] Then
    gui()
    unMapAutoIT($localDriveLetter)
Else 
    doFuncs() ; split out to a function because it's reuseable that way.
endif

; close drives.. no need to leave these on the user's PC.
unMapAutoIT($localDriveLetter)



#cs **********
Functions
#ce **********


Func gui()
Local $windowW = 700
Local $windowH = 400
Local $mainWindow, $okbutton
   
Opt("GUIOnEventMode",1)
$mainWindow = GUICreate("Preventive Maintenance System", $windowW, $windowH)
GUISetOnEvent($GUI_EVENT_CLOSE, "CLOSEClicked")
GUICtrlCreateLabel("Check your choices, then click 'Do Selected'.", 5, 10)
$okbutton = GUICtrlCreateButton("Do Selected",($windowW-75),($windowH-30),70)
GUICtrlSetOnEvent($okbutton,"OKButton")
for $count = 1 to $arrayend ; Go from 1 because we don't want to display a checkbox for "gui" & use Global $count because of limitation of GUICtrlSetOnEvent
    ; capture the ControlID into the same array for later use.
    $choices[$count][2]= GUICtrlCreateCheckbox($choices[$count][0], 5, ($count*25)+5)
    GUICtrlSetOnEvent(-1, "changestate")
    if $choices[$count][1]=1 Then
        GUICtrlSetState(-1,$GUI_CHECKED)
       
    EndIf
    ; create state chage calls...
    
Next
Global $guiText = GUICtrlCreateEdit("",$windowW/2,5,$windowW/2-7,$windowH-40, BitOr($ES_MULTILINE,$ES_READONLY))
GUISetState(@SW_SHOW)

logThis("Gui Initialized")

while 1
 Sleep(1000)
 
WEnd
   
EndFunc

Func changestate() ; Rotten error checking... look this over better later.
    Local $i=0
    ; ControlID is @GUI_CTRLID
    for $i=1 to $arrayend
        if $choices[$i][2] = @GUI_CTRLID Then
            if $choices[$i][1] Then
                $choices[$i][1] = 0
            Else
                $choices[$i][1] = 1
            EndIf
        EndIf
    Next
EndFunc


Func logThis($text)
    local $log,$loc,$success=0,$error=0 ; location of logfile.
    if $choices[0][1] Then ; see if the GUI is initialized.
        updateGUI($text)
    EndIf
    if $drivemapped Then
        $loc = $localDriveLetter&"\logs\"
        $log = FileOpen ( $loc & @ComputerName & ".log", 1 )
        $success=FileWrite($log, $text& " | " & @HOUR & ":" & @MIN &" "& @MON &"/"& @MDAY &"/"& @YEAR & @CRLF)
        if $success <> 1 Then
            $error=1
        EndIf
        FileClose($log)
    EndIf
    if $drivemapped=0 OR $error<>0 then
        $loc = $localLog&"\"
        $log = FileOpen ( $loc & @ComputerName & ".log", 1 )
        $success=FileWrite($log, $text &" "& @HOUR & ":" &  @MIN &" "& @MON &"/"& @MDAY &"/"& @YEAR & @CRLF)
        if $success <> 1 Then
            MsgBox(0,"","Cannot log remotely or locally... something is really screwed up here.")
        EndIf
        FileClose($log)
    EndIf   
EndFunc

Func updateGUI($text)
    local $updatetxt = ""
    if $scrollpos < 15 AND $scrollpos > 0 then
        $scrollpos = $scrollpos + 1
        $scrolltext[$scrollpos] = $text
    elseif $scrollpos = 0 Then
        $scrolltext[$scrollpos] = $text
        $scrollpos = $scrollpos + 1
    Elseif $scrollpos >= 15 then
        _ArrayPush ($scrolltext, $text ,0 )
    endif
    for $i = 0 to $scrollpos
        $updatetxt = $updatetxt&$scrolltext[$i]&@CRLF
    Next
    GUICtrlSetData($guiText,$updatetxt)
EndFunc

Func mapAutoIT($driveLetter)
    Local $success=0,$error=0
    $success = DriveMapAdd($driveletter,$svr&$share,0,$user,$pass)
    $error = @error
    Select
     case $success=1 AND $error=0
        $drivemapped=1
     case $error=1
        $success = DriveMapAdd($driveletter,$svr&$share,0); sometimes it gets screwy if you try to hand it credentials all the time.
        $error=@error
        if $success=1 AND $error=0 then
            $drivemapped=1
        else
            MsgBox(0,"","Cannot map drive: Undefined / Other error. @extended set with Windows API return", 2)
        EndIf
     case $error=2
        MsgBox(0,"","Cannot map drive: Access to the remote share was denied", 2)
     case $error=3
        MsgBox(0,"","Cannot map drive: The device is already assigned", 2)
     case $error=4
        MsgBox(0,"","Cannot map drive: Invalid device name", 2)
     case $error=5
        MsgBox(0,"","Cannot map drive: Invalid remote share", 2)
     case $error=6
        MsgBox(0,"","Cannot map drive: Invalid password", 2)
    EndSelect
EndFunc

Func unMapAutoIT($driveLetter)
    local $val=0
    $val = DriveMapDel($driveletter)
    $drivemapped=0
EndFunc

Func bin($decimal)
    local $retVal[6], $startVal=String($decimal), $work, $work2
    ; very limited - only goes to decimal(127) - 6 "columns"
    ; good enough for this run though..
    for $i = 5 to 0 step -1
        $retVal[$i] = Int(Mod($decimal,2))
        $decimal = $decimal / 2
    next
    
    return $retVal
EndFunc

Func OKButton()
    ;MsgBox(0,"GUI Event","OK Clicked...")
    ; read thru the $choices array and find out which ones are checked and run those functions...
    DoFuncs()
EndFunc

Func CLOSEClicked()
    unMapAutoIT($localDriveLetter)
    Exit
EndFunc

Func DoFuncs()
    Local $success=0, $count, $hddfound, $return[10]
    for $i = 1 to $arrayend
        ;MsgBox(0,"Stuff",$choices[$i][0])
        if $choices[$i][1] Then
            Select
              ;cleanTempFiles   
                case $choices[$i][0] = $choices[1][0] ; Variable name in position 1,0 of $choices, this case: "Clean Temp Files, Recycle Bin".  Done this way to keep you from
                    ;cleantempfiles()              ; needing to change select choices when you change the names in the $choices array.
                    logThis("Called: cleanTempFiles()")
                    if $test Then
                        MsgBox(0,"Would do:","cleanTempFiles()")
                    Else
                        $success = cleanTempFiles($hdd)
                    endif
                    if $success Then
                        logThis("cleanTempFiles() Successful")
                    ElseIf $test=1 Then
                        logThis("In TEST mode, nothing actually done...")
                    ElseIf ($success=0 AND $test=0) Then
                        logThis("Broken: cleanTempFiles(), please repair.")
                    EndIf
              ;setVirtualMem
                case $choices[$i][0] = $choices[2][0]
                    logThis("Called: setVirtualMem()")
                    if $test Then
                        MsgBox(0,"Would do:","setVirtualMem()")
                    Else
                        ; Get size of available memory.  Do formula:
                        ; The recommended size is 2.5 times your RAM size, and my choice is to set the Initial Size and Maximum Size values equal, to get a fixed size swap file
                        ; We'll follow this till 4G in size for a swap file... past that's it a pain for windows to address the file size.
                        $mem = MemGetStats()
                        $pagefilesize = int(($mem[1] * 2.5) / 1000)
                        $success = setVirtualMem($hdd, $pagefilesize)
                    endif
                    if $success Then
                        logThis("setVirtualMem() Successful")
                    elseif $test=1 Then
                        logThis("In TEST mode, nothing actually done...")
                    ElseIf ($success=0 AND $test=0) Then
                        logThis("Broken: setVirtualMem(), please repair.")
                    EndIf
              ;cleanUserProfiles
                case $choices[$i][0] = $choices[3][0]
                    logThis("Called: cleanUserProfiles()")
                    if $test Then
                        MsgBox(0,"Would do:","cleanUserProfiles()")
                    Else
                        $success = cleanUserProfiles($hdd)
                    endif
                    if $success Then
                        logThis("cleanUserProfiles() Successful")
                    elseif $test=1 Then
                        logThis("In TEST mode, nothing actually done...")
                    ElseIf ($success=0 AND $test=0) Then
                        logThis("Broken: cleanUserProfiles(), please repair.")
                    EndIf
              ;doUpdates
                case $choices[$i][0] = $choices[4][0]
                    logThis("Called: doUpdates()")
                    if $test Then
                        MsgBox(0,"Would do:","doUpdates()")
                    Else
                        $success = doUpdates()
                    endif
                    if $success Then
                        logThis("doUpdates() Successful")
                    elseif $test=1 Then
                        logThis("In TEST mode, nothing actually done...")
                    ElseIf ($success=0 AND $test=0) Then
                        logThis("Broken: doUpdates(), please repair.")
                    EndIf
              ;defrag
                case $choices[$i][0] = $choices[5][0]
                    logThis("Called: defrag()")
                    if $test Then
                        MsgBox(0,"Would do:","defrag()")
                    Else
                        ; just in case there's more than one drive...
                        $hddfound=DriveGetDrive("FIXED")
                        If NOT @error Then
                            logThis("Found " & $hddfound[0] & " drives")
                            For $count = 1 to $hddfound[0]
                                $return[$i]=defrag($hddfound[$count])
                            Next
                        EndIf
                        ; kind of a hack to see if it was successful or not...
                        for $count = 1 to $return[0] ; array end
                            $success = 1 
                            $success = $return[$i] * $success
                        Next
                    endif
                    if $success Then
                        logThis("defrag() Successful")
                    elseif $test=1 Then
                        logThis("In TEST mode, nothing actually done...")
                    ElseIf ($success=0 AND $test=0) Then
                        logThis("Broken defrag(), please repair.")
                    EndIf
                case Else
                    MsgBox (0, "Whoops", "Next time try to fix the select statement...")
            EndSelect
        EndIf
    next
EndFunc

Func defrag($drive)
    local $process="", $count=0, $success=0, $remainder
    if IsAdmin() then
        if FileExists(@SystemDir&"\defrag.exe") Then
            $process=Run("defrag -f "&$drive,"",@SW_HIDE)
            logThis("Starting & Running Defrag on "&$drive)
            While ProcessExists($process)
                Sleep(1000)
                $count=$count+1
                $remainder = mod($count,30)
                if $remainder = 0 Then ; repeat message every 30 secs...
                    logThis("Defrag is still running on "&$drive&". Current time in seconds: "&$count)
                EndIf
            Wend
            logThis("Defrag complete; total runtime: "&($count/60)&" minutes")
            $success=1
        Else
            logThis("Defrag not found")
        
        EndIf
    Else
        logThis("You need to be an admin to run defrag on drives...")
    EndIf
    return $success
EndFunc

Func doUpdates()
    return 0
EndFunc

Func cleanUserProfiles($hdrive)
    ;finding user directories
    Local $i = 0, $find, $success
    $find = FileFindFirstFile($hdrive&"\Documents and Settings\*")
    If $find <> -1 Then
        While 1
            $i = $i + 1
            If $i > 75 Then
                logThis(" Warning: Only first 75 users are processed.")
                Return
            EndIf
            $user = FileFindNextFile($find)
            If @error = 1 Then ExitLoop
            If StringInStr(FileGetAttrib($hdrive&"\Documents and Settings\"&$user)&FileGetAttrib($hdrive&"\Users\"&$user),"D") = 0 Or $user = "." Or $user = ".." Or $user = "All Users" Or $user = "Local Settings" Or $user = "Default User" Or $user = "Public" Or $user = "Default" Or $user = "LocalService" Or $user = "NetworkService" Then ContinueLoop
            logThis(" Scanning "&$user&"'s account...")
        
            logThis("Clearing history...")
            rd($hdrive&"\Documents and Settings\"&$user&"\Local Settings\History")
            logThis("Cleared history.")
           
            logThis("Deleting temporary files...")
            rd($hdrive&"\Documents and Settings\"&$user&"\Local Settings\Temp")
            logThis("Deleted temporary files.")
           
            logThis("Emptying temporary internet files folder...")
            rd($hdrive&"\Documents and Settings\"&$user&"\Local Settings\Temporary Internet Files")
            logThis("Emptied temporary internet files folder.")
           
            logThis("Clearing cookies...")
            rd($hdrive&"\Documents and Settings\"&$user&"\Cookies")
            logThis("Cleared cookies.")
           
            logThis("Clearing recently opened documents list...")
            rd($hdrive&"\Documents and Settings\"&$user&"\Recent")
            rd($hdrive&"\Documents and Settings\"&$user&"\Application Data\Microsoft\Office\Recent")
            logThis("Cleared recently opened documents list.")
           
        WEnd
        FileClose($find)
        $success =1
    EndIf
    return 1
EndFunc

Func cleanTempFiles($drive)
    Local $file, $search, $verify, $v1, $v2, $size, $v3, $return, $folder
    
    logThis("Cleaning Temporary Files from " & $drive)
    
    ; Empty RecycleBin from $drive
    logThis("Emptying RecycleBin for "&$drive)
    $v1 = FileRecycleEmpty($drive&"\") ; If we profide no drive letter, this will empt recycle bins from all drives.
    if $v1 = 0 Then
        logThis ("Empty RecycleBin failed for drive "&$drive&"\")
    EndIf
    
    ; Remove the crap in the \MSOCache directory
    logThis("Removing Files from "&$drive&"\MSOCache")
    $search = FileFindFirstFile($drive&"\MSOCache\*.*")
    If $search = -1 Then
        ; Dir is empty, move on...
        logThis("MSOCache empty, leaving.")
        $v2 = 1
    Else
        DirRemove($drive&"\MSOCache",1) ; DO NOT MAKE TYPOS IN THIS AREA...
        $size = DirGetSize($drive&"\MSOCache",1) ; DirGetSize in extended mode returns an array, of which the second element is filecount: $array[1] = Files count
        if $size[1] = 0 Then
            $v2 = 1
        Else
            $v2 = 0
        EndIf
    EndIf
    FileClose($search)
    
    ; Remove the crap in the \Windows\Temp directory
    logThis("Removing Files from "&$drive&"\Windows\Temp")
    $search = FileFindFirstFile($drive&"\Windows\Temp\*.*") ; Finds Dirs and Files.
    If $search = -1 Then
        ; this should provide -1 on not finding \Windows as well.
        ; Dir is empty, move on...
        logThis("Windows Temp empty, leaving.")
        $v3 = 1
    Else
        FileDelete($drive&"\Windows\Temp\*.*"); Removes only the top level files.. nothing else so far...  Need to handle the dirs as well.
    EndIf
    FileClose($search); Close the filehandle as soon as you are done with it...
    ; check  to see that dir is actually empty.
    $search = FileFindFirstFile($drive&"\Windows\Temp\*.*") ; Finds Dirs and Files.
    While 1
        $folder = FileFindNextFile($search) 
        If @error Then ExitLoop
        ; Delete \Windows\Temp\$folder and all subdirs and files
        DirRemove($drive&"\Windows\Temp\"&$folder, 1)
    WEnd
    FileClose($search); Close the filehandle as soon as you are done with it...
    $size = DirGetSize($drive&"\Windows\Temp",1) ; DirGetSize in extended mode returns an array, of which the second element is filecount: $array[1] = Files count
    if ($size[1] + $size[2]) = 0 Then ; Amount of files + Amount of dirs
        $v3 = 1
    Else
        $v3 = 0
    EndIf
    ; FEATURE ADD HERE!!!
    ; Remove Windows Updates log files from Windows dir.
    ; logThis("Removing Windows Updates clutter.")
    ; FEATURE ADD HERE!!!
    $verify = $v1 * $v2 * $v3
    if $verify Then
        return 1
    Else
        return 0
    EndIf
EndFunc

Func setVirtualMem($hdd, $pfsize)
    local $success=0, $key=""
    
    ; max pagefile can be is 4G - we make one less than 4096 just to make sure we are safe.
    if $pfsize > 4095 Then
        $pfsize = 4095
    endif
    
    logThis("Setting pagefile to: "&$pfsize)
    $key =""$hdd&"\pagefile.sys "&$pfsize&" "&$pfsize&
    $success = RegWrite($pfkeyloc, $pfkeyname, "REG_MULTI_SZ", $key)
    if $success Then
        logThis("Pagefile Set to: "&$pfsize)
    Else
        if $success = 0 Then
            Select
            case @error = -2
                logThis("value type not supported")
            case @error = -1
                logThis("unable to open requested value")
            case @error = 1
                logThis("unable to open requested key")
            case @error = 2
                logThis("unable to open requested main key")
            case @error = 3
                logThis("unable to remote connect to the registry")
            EndSelect
        EndIf
    EndIf
    return $success
EndFunc

Func rd($dir,$loop = 0,$indent = "     ") ; Recurse Directory
    If $loop > 50 Then Return
    If FileExists ($dir) = 0 Then Return
    FileDelete($dir&"\*")
    logThis($indent&"+ "&$dir)
    Local $file,$find
    $find = FileFindFirstFile ($dir&"\*")
    If $find <> -1 Then
        While 1
            $file = FileFindNextFile ($find)
            If @error = 1 Then ExitLoop
            If $file = "." Or $file = ".." Then ContinueLoop
            If FileDelete($dir&"\"&$file) = 0 And DirRemove($dir&"\"&$file,1) = 0 Then rd($dir&"\"&$file,$loop+1,$indent&"   ")
        WEnd
        FileClose($find)
    EndIf
EndFunc
Edited by laidback01
Link to comment
Share on other sites

Man there is some error,I try to correct it ^^

You need to customize it for your environment - It logs what it does to a network server for later parsing and/or troubleshooting.

Near the top, you'll see a line:

Global $svr="\\autoit", $share="\PMS", $user="user", $pass="pass"

change that to suit. Other than that, should be good to go.

Edited by laidback01
Link to comment
Share on other sites

LOL, and here I thought this was a cool idea - being able to control whether or not the gui show up or not depending on command line args... Guess it's all been done and done better... before. Only one guy comments to say there's errors, heh, and only cause he didn't read the code. Must not have fit anyone's "gotta have it" needs... Oh well.

Link to comment
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
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...