Announcement

Collapse
No announcement yet.

Defrag/Cleanup Domain Computers

Collapse
X
  • Filter
  • Time
  • Show
Clear All
new posts

  • Defrag/Cleanup Domain Computers

    I'm looking to create scheduled tasks for defrag and disk cleanup on most domain computers. Some have XP, others have 2000. I'm trying to avoid copy/pasting tasks manually on hundreds of systems.

    I found this post by Rems, but is there a way I can modify it to affect multiple (or all) computers on a domain from the server? Or is there another way to do this without third-party software?


    Thank you for any help!



    Originally posted by Rems View Post
    No, a scheduled 'run now' is not even possible.

    When you add a scheduledTask (by script or using a commandline or manually), it is very recommended to set the starttime at least two minutes from now (local computer time) to assure it will run.
    The Job then will start somewhere between one and two minutes.

    The reason for this behaviour is because the scheduler does not realy count time but it monitors the flipping minutes from the systemclock. It waits for the event that the minutes changes, that moment it compares the new pattern of minutes/hours/day/month/year with the start time of the job (at that moment the seconds are exact 00). When if you scheduled the job only one minute from now, there is a real change that during the creation of the Job, the minutes of the clock changes and the Job misses its moment to be launched.


    If you want an InputBox where you can type the name of the target computer to run the defrag on, a vbscript can be a good option.
    Then you can use objectshell.Run to run the psexec command line.
    Or, you can use the "Win32_ScheduledJob" class to add a scheduled Job (the 2 minutes it takes at the most to schedule the job is really nothing if you compare it with time the complete defragmentation takes).


    This is an example how you can use inputboxes for computernames and also for choosing a drive letter.
    Code:
    ' RemoteDefrag.vbs
    ' by Remco Simons [nl] 2007
    ' 
    ' http://forums.petri.com/showthread.php?t=16849
    
    strComputer = _
    InputBox(vbNewline&vbNewline&vbNewline&vbNewline&vbNewline& _
    "Computer Name:","Run Defrag on remote computer","?",xpos,ypos)
    If strComputer = Cancel Then cancelscript("")
    
    With WScript.CreateObject("WScript.Shell")
     'http://msdn2.microsoft.com/en-us/library/x83z1d9f.aspx
      BtnCode = .Popup("Connecting....", 1," Please wait", 0+64)
    End With
    
    On Error Resume Next
    Set objWMIService = GetObject("winmgmts:" _
       & "{impersonationLevel=impersonate}!\\" & _
       strComputer & "\root\cimv2")
    Set colDisks = objWMIService.ExecQuery _
       ("SELECT * FROM Win32_LogicalDisk where mediatype = '12'")
     For each objDisk in colDisks
       strDrives = objDisk.DeviceID & "  " & strDrives
     Next
    If err.Number then cancelscript("")
    
    strDrive = _
    InputBox(vbNewline&vbNewline&"Select a drive to Defrag"& _
    vbNewline&vbNewline&vbNewline&"Choose one of the following drives " & _
    "available on '"&Ucase(strComputer)&"' :"&vbNewline&strDrives,"Run " & _
    "Defrag on remote station","C:",xpos,ypos)
    If strDrive = Cancel Then cancelscript("")
    
    strJob = "defrag.exe "& strDrive &" -f"
    
    schtask strComputer, strJob, "false" 
                  '| the third parameter (true/false) tells whether the job 
                  '| should run INTERACTIVE with the user's desktop or not.
    '(The jobs starts within 2 minutes from now)
    
    wscript.quit
    
    
    Sub cancelscript(errJobCreated)
      With WScript.CreateObject("WScript.Shell")
       BtnCode=.Popup("Script aborted", 5,"[ "&errJobCreated & _
       " ]  * * * * * * * * * *", 0+16)
       wscript.quit
      End With
    End Sub
    
    
    Sub schtask(strComputer, Job, interAct)
     On Error Resume Next
     wait = 2 '(= amount of minute 'flippings')
    '___
    '// dlsBIAS, according to the timezone on your! computer
    
    Set objSWbemServices = GetObject("winmgmts:" _
     & "{impersonationLevel=impersonate}!\\.\root\cimv2")
    
    Set colComputer = objSWbemServices.ExecQuery _
     ("SELECT CurrentTimeZone FROM Win32_ComputerSystem")
      For Each objComputer in colComputer
        BiasGMT = objComputer.CurrentTimeZone
        Exit For
      Next
    Set objSWbemServices = Nothing
    If Int(instr(Cstr(BiasGMT),"-"))=1 Then a="-" Else a="+"
    BiasGMT = a & Right(1000 + Abs(BiasGMT),3)
    '___
    '// determine the CURRENT_TIME from the target! computer
    
    Set objWMIService = GetObject("winmgmts:" _
     & "{impersonationLevel=impersonate}!\\" & strComputer & "\root\cimv2")
    Set colItems = objWMIService.ExecQuery("Select * from Win32_LocalTime")
    
    For Each objItem in colItems
      strtTime = (objItem.Hour*100) + (objItem.Minute + wait)
      Exit For
    Next
    '___
    '// create a new SCHEDULEDJOB on the target computer
    '   http://msdn2.microsoft.com/en-us/library/aa394601.aspx
    
    Set objService = GetObject("winmgmts:\\" & strComputer)
    Set objNewJob  = objService.Get("Win32_ScheduledJob")
    
    sScheduled = "********" & Right(10000 + strtTime,4) _
                 & "00.000000" & BiasGMT
    
    errJobCreated = objNewJob.Create _
     (Job, sScheduled, , , , InterAct, JobID)
    
    If Err.Number = 0 Then
     Wscript.Echo "Defragmentation of drive "&strDrive& " on " & _
     UCase(strComputer) & vbNewLine & "will start within 2 minutes."& _
     vbNewLine&vbTab&"( Job ID: " & JobID &" )"
    Else
     cancelscript(errJobCreated)
    End If
    End Sub
    
    Sub cancelscript(errJobCreated)
      With WScript.CreateObject("WScript.Shell")
       BtnCode=.Popup("Script aborted", 5,"[ "&errJobCreated & _
       " ]  * * * * * * * * * *", 0+16)
       wscript.quit
      End With
    End Sub
    This script use the Win32_ScheduledJob,
    but if you don't want that, just remove the Subroutine "Sub schtask(... " completely.
    And also, replace the 4 lines 36 - 39
    (first line (34) = schtask strComputer, strJob, "false"
    last line (39) = '(The jobs starts within 2 minutes from now)

    with these five new lines:
    Code:
    With WScript.CreateObject("WScript.Shell")
    strCommand = "c:\pstools\PSEXEC -i -d -s \\" & strComputer
    strCommand = strCommand & " " & strJob
          .Run strCommand, 1, TRUE
    End With
    \Rems

  • #2
    Re: Defrag/Cleanup Domain Computers

    I don't know if this will help or not but you could try creating a scheduled task on a computer with all needed parameters including the run as permissions if users do not have permissions to run a defrag. Once this has been created copy the task from %systemroot%\tasks to a network share somewhere.

    Once you have this task in a network share you could create a login script of some kind that copies the task from the share to the users local PC and put it in their %systemroot%\tasks folder. This will then put the task on their computer.

    I am not big on scripting so I don't really think I should post a script to do this, perhaps someone else would be able to provide the appropriate code? It would be something like

    Code:
    if %systemroot%\tasks\task exists goto :end
    else copy "\\server\share\task %systemroot%\task\
    :end
    Once again I do not believe that is anywhere close to the right syntax, just a starter idea. I hope this helps out!
    Justin
    A+ Net+ MCP

    Comment


    • #3
      Re: Defrag/Cleanup Domain Computers

      Originally posted by jmk1713 View Post
      I'm looking to create scheduled tasks for defrag and disk cleanup on most domain computers. Some have XP, others have 2000. I'm trying to avoid copy/pasting tasks manually on hundreds of systems.

      I found this post by Rems, but is there a way I can modify it to affect multiple (or all) computers on a domain from the server? Or is there another way to do this without third-party software?

      Thank you for any help!
      This thread http://forums.petri.com/showthread.php?t=17592 shows how a script can enumerate computers from active directory, and then use the computer names to run the command. In your case the command will be one of the two:
      - 1. add a scheduled task on the remote computer
      - 2. use psexec to the remote computer
      to run cleanmgr.exe and the defragmenter on the remote computer.

      command-line cleanmgr.exe
      - Windows XP
      - Windows 2000

      command-line defrag.exe
      - Windows XP
      - no defrag command-line option in Win2000

      If you have Windows XP and Windows 2000 clients, you can only schedule defrag.exe on the first ones.

      For Windows 2000 I think you best can use a thirdparty tool! (e.g. http://www.kessels.com/JkDefrag/) if you want to run the defragmenter by command-line.

      You could try to script the MMC snap-in "dfrg.msc" that comes with Windows 2000 if only starting the job is sufficient to your needs.
      example:
      Code:
      'Automate the start of Defrag on Windows 2000 
      'name: Defrag.vbs
      '
      'commandline:
      '       wscript.exe  Defrag.vbs driveletter timeout
      
      ' (where 'driveletter:' and 'timeout' are optional parameters)
      
      strCMD   = "mmc.exe dfrg.msc"
      
      On Error Resume Next
      
      ' reading commanline parameters     
      If WScript.Arguments.Count > 0 Then
         strDrive = WScript.Arguments(0)
      Else
         strDrive = "c:"  '= default
      End If
      If WScript.Arguments.Count > 1 Then
         sTimeOut =  wscript.Arguments(1)  ' in minutes
      Else
         sTimeOut =  vbEmpty
      End If
      
      strComputer = "."
      
      Set objWMIService = GetObject("winmgmts:" _
         & "{impersonationLevel=impersonate}!\\" & _
         strComputer & "\root\cimv2")
      Set colDisks = objWMIService.ExecQuery _
         ("SELECT DeviceID, VolumeName FROM Win32_LogicalDisk " & _
          "Where mediatype = 12 AND DeviceID = '" & strDrive & "'")
      
       For each objDisk in colDisks
         sDrive = "(" & objDisk.DeviceID & ")"
         sLabel = objDisk.VolumeName
         If Not sLabel = "" Then _
         sDrive = Trim(sLabel & " " & sDrive)
       Next
      
      Set WshShell = CreateObject("Wscript.Shell")
      
      With GetObject("winmgmts:Win32_Process")
        Set oInParams = .Methods_("Create").InParameters.SpawnInstance_
           oInParams.CommandLine = strCMD
        Set oOutParams = .ExecMethod_("Create", oInParams)
           strPID = oOutParams.ProcessId
           returned = oOutParams.ReturnValue
      End With
      
      While WshShell.AppActivate(strPID) = FALSE
      wscript.sleep 1000
      Wend
      
      If returned = 0 Then
         sDrive = Replace(sDrive,"(","{(}")
         sDrive = Replace(sDrive,")","{)}")
      
         wscript.sleep 50
         WshShell.AppActivate strPID
         If WshShell.AppActivate(strPID) then _
            WshShell.SendKeys "{TAB 2}" & sDrive
         wscript.sleep 50
         WshShell.AppActivate strPID
         If WshShell.AppActivate(strPID) then _
            WshShell.SendKeys "%AD"
         wscript.sleep 300
         WshShell.AppActivate strPID
         If WshShell.AppActivate(strPID) then _ 
         WshShell.SendKeys "%( )N"
      End If
      
      If Not sTimeOut = 0 then
        Set colProcess = objWMIService.ExecQuery _
          ("Select * from Win32_Process Where Handle = " & strPID )
        wscript.sleep (sTimeOut * 60000)
        For Each objProcess in colProcess
          objProcess.Terminate()
        Next 
      End If
      
      Set WshShell = Nothing
      Set objWMIService = Nothing
      Note that the script above is far from perfect;
      - it is missing a routine at the beginning to check if an other defrag job is active,
      - it can not deal with popup messages from the process
      - it cannot determine when the process is ready to close the window.
      - it must run interactive! (started by a local administrator)

      (check also this link with similar vbscripts: http://www.compu-docs.com/W2KDfrag.htm
      note: the process-windowtitles there are depending on the language of the OS! )

      \Rems
      Last edited by Rems; 13th August 2007, 15:46. Reason: enclosed the parentheses-characters that are around the driveletter, within braces: "{(}" and "{)}"

      This posting is provided "AS IS" with no warranties, and confers no rights.

      __________________

      ** Remember to give credit where credit's due **
      and leave Reputation Points for meaningful posts

      Comment

      Working...
      X