Solved

VBScript: Analyze Volume Defragmentation

Posted on 2010-09-07
30
1,038 Views
Last Modified: 2012-05-10

Hi there,

I found this script at:
http://www.activexperts.com/activmonitor/windowsmanagement/scripts/storage/diskdrives/physical/#AVD.htm

But it does'nt work.

This script will run on a Windows 2003 server and XP.

It analyzes the defragmentation status of all the volumes on a computer. This is equivalent to running defrag.exe with the command-line options -a (analyze) and -v (verbose).

Thanks for your help,
Rene
strComputer = "."
Set objWMIService = GetObject("winmgmts:" _
    & "{impersonationLevel=impersonate}!\\" & strComputer & "\root\cimv2")

Set colVolumes = objWMIService.ExecQuery("Select * from Win32_Volume")

For Each objVolume in colVolumes
    errResult = objVolume.DefragAnalysis(blnRecommended, objReport)
    If errResult = 0 then
        Wscript.Echo "Average file size: " & objReport.AverageFileSize
        Wscript.Echo "Average fragments per file: " & _
            objReport.AverageFragmentsPerFile
        Wscript.Echo "Cluster size: " & objReport.ClusterSize
        Wscript.Echo "Excess folder fragments: " & _
            objReport.ExcessFolderFragments
        Wscript.Echo "File percent fragmentation: " & _
            objReport.FilePercentFragmentation
        Wscript.Echo "Fragmented folders: " & objReport.FragmentedFolders
        Wscript.Echo "Free soace: " & objReport.FreeSpace
        Wscript.Echo "Free space percent: " & objReport.FreeSpacePercent
        Wscript.Echo "Free space percent fragmentation: " & _
            objReport.FreeSpacePercentFragmentation
        Wscript.Echo "MFT percent in use: " & objReport.MFTPercentInUse
        Wscript.Echo "MFT record count: " & objReport.MFTRecordCount
        Wscript.Echo "Page file size: " & objReport.PageFileSize
        Wscript.Echo "Total excess fragments: " & _
            objReport.TotalExcessFragments
        Wscript.Echo "Total files: " & objReport.TotalFiles
        Wscript.Echo "Total folders: " & objReport.TotalFolders
        Wscript.Echo "Total fragmented files: " & _
            objReport.TotalFragmentedFiles
        Wscript.Echo "Total MFT fragments: " & objReport.TotalMFTFragments
        Wscript.Echo "Total MFT size: " & objReport.TotalMFTSize
        Wscript.Echo "Total page file fragments: " & _
            objReport.TotalPageFileFragments
        Wscript.Echo "Total percent fragmentation: " & _
            objReport.TotalPercentFragmentation
        Wscript.Echo "Used space: " & objReport.UsedSpace
        Wscript.Echo "Volume name: " & objReport.VolumeName
        Wscript.Echo "Volume size: " & objReport.VolumeSize       
        If blnRecommended = True Then
           Wscript.Echo "This volume should be defragged."
        Else
           Wscript.Echo "This volume does not need to be defragged."
        End If
        Wscript.Echo
    End If
Next

Open in new window

0
Comment
Question by:ReneGe
  • 13
  • 12
  • 5
30 Comments
 
LVL 14

Expert Comment

by:Psy053
ID: 33622577
Hey Rene,

The methods in the above script are the same as the ones I used to report Total Percentage Fragmentation and File PercentageFragmentation in the DiskSpace.VBS from your last question.

As per that previous script though, it will NOT work with XP, this is because the Win32_Volume Class was not available on XP and earlier.
0
 
LVL 10

Author Comment

by:ReneGe
ID: 33622723
Hey Psy,

It seems that I asked the wrong question.

Could there be another way to get fragmentation infos? Like maybe running Defrag.exe /A /V in the VBScript and capturing the infos?

Thanks,
Rene
0
 
LVL 65

Expert Comment

by:RobSampson
ID: 33623183
On XP, you will need to run
defrag c: -a > DefragAnalysis.txt

Regards,

Rob.
0
Use Case: Protecting a Hybrid Cloud Infrastructure

Microsoft Azure is rapidly becoming the norm in dynamic IT environments. This document describes the challenges that organizations face when protecting data in a hybrid cloud IT environment and presents a use case to demonstrate how Acronis Backup protects all data.

 
LVL 65

Expert Comment

by:RobSampson
ID: 33623195
Something like this would capture it.

Regards,

Rob.
Set objShell = CreateObject("WScript.Shell")
Set objExec = objShell.Exec("defrag c: -a -v")
While objExec.Status
	WScript.Sleep 100
Wend
strDetails = objExec.StdOut.ReadAll
WScript.Echo strDetails

Open in new window

0
 
LVL 10

Author Comment

by:ReneGe
ID: 33623259
Thanks Rob,

Can this script:
-Get the info on all local drives
-Parse the data so I can get the output as:
Drive,FileFragmentation,TotalFragmentation

Thanks again,
Rene
0
 
LVL 65

Expert Comment

by:RobSampson
ID: 33623480
OK, this should work.

Regards,

Rob.
strComputer = "."
strOutput = "C:\Temp\Temp\Test Script\DefragReport.csv"
Set objFSO = CreateObject("Scripting.FileSystemObject")
Const intForReading = 1
Set objShell = CreateObject("WScript.Shell")
Set objWMIService = GetObject("winmgmts:" _
    & "{impersonationLevel=impersonate}!\\" & strComputer & "\root\cimv2")
strTempFile = objFSO.GetFolder(Replace(WScript.ScriptFullName, WScript.ScriptName, "")).ShortPath & "DefragOutputTemp.txt"
Set colDrives = objWMIService.ExecQuery("SELECT DeviceID FROM Win32_LogicalDisk WHERE DriveType='3'")
Set objOutput = objFSO.CreateTextFile(strOutput, True)
objOutput.WriteLine "Drive,Size,Free,Fragmentation,File Fragmentation"
For Each objDrive In colDrives
	strCommand = "cmd /c defrag " & objDrive.DeviceID & " -a > " & strTempFile
	objShell.Run strCommand, 0, True
	Set objDefrag = objFSO.OpenTextFile(strTempFile, intForReading, False)
	While Not objDefrag.AtEndOfStream
		strLine = objDefrag.ReadLine
		If InStr(strLine, "Fragmented") > 0 Then
			strSize = Trim(Split(Trim(strLine), ",")(0))
			strFree = Trim(Split(Trim(strLine), ",")(1))
			strFragmented = Split(Trim(strLine), ",")(2)
			strFileFragmented = Mid(strFragmented, InStr(strFragmented, "(") + 1)
			strFileFragmented = Trim(Left(strFileFragmented, Len(strFileFragmented) - 1))
			strFragmented = Trim(Left(strFragmented, InStr(strFragmented, "(") - 1))
			'WScript.Echo objDrive.DeviceID & "," & strSize & "," & strFree & "," & strFragmented & "," & strFileFragmented
			objOutput.WriteLine objDrive.DeviceID & "," & strSize & "," & strFree & "," & strFragmented & "," & strFileFragmented
		ElseIf InStr(strLine, "this volume") > 0 Then
			objOutput.WriteLine strLine
		End If
	Wend
	objDefrag.Close
	objFSO.DeleteFile strTempFile, True
Next
objShell.Run "excel """ & strOutput & """"

Open in new window

0
 
LVL 10

Author Comment

by:ReneGe
ID: 33623522
Rob,

Your script works, however, I get the following error message.

Many thanks and cheers,
Rene
ErrorMessage.png
0
 
LVL 65

Expert Comment

by:RobSampson
ID: 33623542
Slightly odd.....what is the output of the command when you run
defrag c: -a

Mine is

Analysis Report                         
    37.21 GB Total,  6.10 GB (16%) Free,  16% Fragmented (32% file fragmentation)

You should defragment this volume.


The error you get suggests there is no (XXX file fragmentation) section.

Regards,

Rob.
strComputer = "."
strOutput = "C:\Temp\Temp\Test Script\DefragReport.csv"
Set objFSO = CreateObject("Scripting.FileSystemObject")
Const intForReading = 1
Set objShell = CreateObject("WScript.Shell")
Set objWMIService = GetObject("winmgmts:" _
    & "{impersonationLevel=impersonate}!\\" & strComputer & "\root\cimv2")
strTempFile = objFSO.GetFolder(Replace(WScript.ScriptFullName, WScript.ScriptName, "")).ShortPath & "DefragOutputTemp.txt"
Set colDrives = objWMIService.ExecQuery("SELECT DeviceID FROM Win32_LogicalDisk WHERE DriveType='3'")
Set objOutput = objFSO.CreateTextFile(strOutput, True)
objOutput.WriteLine "Drive,Size,Free,Fragmentation,File Fragmentation"
For Each objDrive In colDrives
	strCommand = "cmd /c defrag " & objDrive.DeviceID & " -a > " & strTempFile
	objShell.Run strCommand, 0, True
	Set objDefrag = objFSO.OpenTextFile(strTempFile, intForReading, False)
	While Not objDefrag.AtEndOfStream
		strLine = objDefrag.ReadLine
		If InStr(strLine, "Fragmented") > 0 Then
			strSize = Trim(Split(Trim(strLine), ",")(0))
			strFree = Trim(Split(Trim(strLine), ",")(1))
			strFragmented = Split(Trim(strLine), ",")(2)
			intPos = InStr(strFragmented, "(")
			If intPos > 0 Then
				strFileFragmented = Mid(strFragmented, intPos + 1)
				strFileFragmented = Trim(Left(strFileFragmented, Len(strFileFragmented) - 1))
				strFragmented = Trim(Left(strFragmented, intPos - 1))
			Else
				strFileFragmented = ""
			End If
			'WScript.Echo objDrive.DeviceID & "," & strSize & "," & strFree & "," & strFragmented & "," & strFileFragmented
			objOutput.WriteLine objDrive.DeviceID & "," & strSize & "," & strFree & "," & strFragmented & "," & strFileFragmented
		ElseIf InStr(strLine, "this volume") > 0 Then
			objOutput.WriteLine strLine
		End If
	Wend
	objDefrag.Close
	objFSO.DeleteFile strTempFile, True
Next
objShell.Run "excel """ & strOutput & """"

Open in new window

0
 
LVL 10

Author Comment

by:ReneGe
ID: 33623599
I have a drive of 2.7TB. It's output is 2,795 GB

Therefore, since there is a ","  may I assume it may interfere with the parsing?

Thanks,
Rene
0
 
LVL 10

Author Comment

by:ReneGe
ID: 33623610
FYI: With your last modified script, I did not get the 800A0005 error.
0
 
LVL 65

Expert Comment

by:RobSampson
ID: 33623611
Yes, that is correct......in that case, I'll change the way it's parsing....
0
 
LVL 14

Assisted Solution

by:Psy053
Psy053 earned 100 total points
ID: 33623626
I've modified the previous script that I gave you so that it will detect XP or lower, and then use Defrag.exe to get the File Fragmentation and Total Fragmentation values
DiskSpace.vbs
0
 
LVL 65

Expert Comment

by:RobSampson
ID: 33623667
This should work now.

Regards,

Rob.
strComputer = "."
strOutput = "C:\Temp\Temp\Test Script\DefragReport.csv"
Set objFSO = CreateObject("Scripting.FileSystemObject")
Const intForReading = 1
Set objShell = CreateObject("WScript.Shell")
Set objWMIService = GetObject("winmgmts:" _
    & "{impersonationLevel=impersonate}!\\" & strComputer & "\root\cimv2")
strTempFile = objFSO.GetFolder(Replace(WScript.ScriptFullName, WScript.ScriptName, "")).ShortPath & "DefragOutputTemp.txt"
Set colDrives = objWMIService.ExecQuery("SELECT DeviceID FROM Win32_LogicalDisk WHERE DriveType='3'")
Set objOutput = objFSO.CreateTextFile(strOutput, True)
objOutput.WriteLine "Drive,Size,Free,Fragmentation,File Fragmentation"
For Each objDrive In colDrives
	strCommand = "cmd /c defrag " & objDrive.DeviceID & " -a > " & strTempFile
	objShell.Run strCommand, 0, True
	Set objDefrag = objFSO.OpenTextFile(strTempFile, intForReading, False)
	While Not objDefrag.AtEndOfStream
		strLine = objDefrag.ReadLine
		If InStr(strLine, "Fragmented") > 0 Then
			intSize = InStr(strLine, "Total,")
			strSize = Trim(Left(strLine, intSize + 4))
			intFree = InStr(strLine, "Free,")
			strFree = Trim(Mid(strLine, intSize + 7, (intFree + 4) - (intSize + 7)))
			strFragmented = Trim(Mid(strLine, intFree + 6))
			intPos = InStr(strFragmented, "(")
			If intPos > 0 Then
				strFileFragmented = Mid(strFragmented, intPos + 1)
				strFileFragmented = Trim(Left(strFileFragmented, Len(strFileFragmented) - 1))
				strFragmented = Trim(Left(strFragmented, intPos - 1))
			Else
				strFileFragmented = ""
			End If
			'WScript.Echo objDrive.DeviceID & VbCrLf & strSize & VbCrLf & strFree & VbCrLf & strFragmented & VbCrLf & strFileFragmented
			objOutput.WriteLine objDrive.DeviceID & "," & strSize & "," & strFree & "," & strFragmented & "," & strFileFragmented
		ElseIf InStr(strLine, "this volume") > 0 Then
			objOutput.WriteLine strLine
		End If
	Wend
	objDefrag.Close
	objFSO.DeleteFile strTempFile, True
Next
objShell.Run "excel """ & strOutput & """"

Open in new window

0
 
LVL 10

Author Comment

by:ReneGe
ID: 33623673
Cool that you thought about it... Thanks!

1) On my Server 2003, works like a charm
2) On my XP Pro,  I get the following error (see image)
3) I will use this script with "cscript" in a batch file. Would you mind modifying it so it can output on screen, not in a file?

Thanks again,
Rene
ErrorMessage.png
0
 
LVL 10

Author Comment

by:ReneGe
ID: 33623679
0
 
LVL 65

Expert Comment

by:RobSampson
ID: 33623686
Psy and I are writing different versions....my latest one should work standalone, writing to CSV....
0
 
LVL 10

Author Comment

by:ReneGe
ID: 33623707
==>psy
Sorry man, I did not realize it was you. I guess working 14h in a row does not help.
So my previous 2 messages were for you

==> Rob
Running your last script on both 2003 and XP, I get the following message

Thanks guys,
Rene
ErrorMessage.png
0
 
LVL 10

Author Comment

by:ReneGe
ID: 33623713
ErrorMessage in english
ErrorMessage.png
0
 
LVL 65

Expert Comment

by:RobSampson
ID: 33623717
That would mean Excel does not exist on that system, but you should still find the output file.  Change
objShell.Run "excel """ & strOutput & """"
to
objShell.Run "notepad """ & strOutput & """"

to have the file open in Notepad.

Rob.
0
 
LVL 10

Author Comment

by:ReneGe
ID: 33623729
==>Rob

I get it. I don't have Excel on that machine. So your script does work.
I need the output to be on screen anyway, would you mind changing the script to do so, and remove the Excel part?

Thanks,
Rene
0
 
LVL 65

Accepted Solution

by:
RobSampson earned 400 total points
ID: 33623741
Sure, run this with
cscript DefragStats.vbs

Regards,

Rob.
strComputer = "."
Set objFSO = CreateObject("Scripting.FileSystemObject")
Const intForReading = 1
Set objShell = CreateObject("WScript.Shell")
Set objWMIService = GetObject("winmgmts:" _
    & "{impersonationLevel=impersonate}!\\" & strComputer & "\root\cimv2")
strTempFile = objFSO.GetFolder(Replace(WScript.ScriptFullName, WScript.ScriptName, "")).ShortPath & "DefragOutputTemp.txt"
Set colDrives = objWMIService.ExecQuery("SELECT DeviceID FROM Win32_LogicalDisk WHERE DriveType='3'")
WScript.Echo "Drive,Size,Free,Fragmentation,File Fragmentation"
For Each objDrive In colDrives
	strCommand = "cmd /c defrag " & objDrive.DeviceID & " -a > " & strTempFile
	objShell.Run strCommand, 0, True
	Set objDefrag = objFSO.OpenTextFile(strTempFile, intForReading, False)
	While Not objDefrag.AtEndOfStream
		strLine = objDefrag.ReadLine
		If InStr(strLine, "Fragmented") > 0 Then
			intSize = InStr(strLine, "Total,")
			strSize = Trim(Left(strLine, intSize + 4))
			intFree = InStr(strLine, "Free,")
			strFree = Trim(Mid(strLine, intSize + 7, (intFree + 4) - (intSize + 7)))
			strFragmented = Trim(Mid(strLine, intFree + 6))
			intPos = InStr(strFragmented, "(")
			If intPos > 0 Then
				strFileFragmented = Mid(strFragmented, intPos + 1)
				strFileFragmented = Trim(Left(strFileFragmented, Len(strFileFragmented) - 1))
				strFragmented = Trim(Left(strFragmented, intPos - 1))
			Else
				strFileFragmented = ""
			End If
			WScript.Echo objDrive.DeviceID & "," & strSize & "," & strFree & "," & strFragmented & "," & strFileFragmented
		ElseIf InStr(strLine, "this volume") > 0 Then
			WScript.Echo strLine
		End If
	Wend
	objDefrag.Close
	objFSO.DeleteFile strTempFile, True
Next

Open in new window

0
 
LVL 10

Author Comment

by:ReneGe
ID: 33623775
Thanks guys,

I have what I need and you are geniuses!!!!!

Many thanks and lots of cheers,
Rene
0
 
LVL 14

Expert Comment

by:Psy053
ID: 33623783
Here's an updated version of my script that will write to screen.

Just to troubleshoot the issue you had with it earlier, I have included an extra line that shows what the Version is, can you please report that version back here?
DiskSpace-ToScreen.vbs
0
 
LVL 65

Expert Comment

by:RobSampson
ID: 33623784
No problem. Thanks for the grade.

Regards,

Rob.
0
 
LVL 65

Expert Comment

by:RobSampson
ID: 33623789
Psy, if you want to ask for points for an assist, I won't object....

Rob.
0
 
LVL 14

Expert Comment

by:Psy053
ID: 33623799
Rob, would you mind telling my why you chose to write the output to file for processing as opposed to using the StdOut that you had initially?
0
 
LVL 65

Expert Comment

by:RobSampson
ID: 33623804
I did that just so the output was silent, and you don't have the DOS prompt appear with the defrag, waiting for the StdOut.

Rob.
0
 
LVL 14

Expert Comment

by:Psy053
ID: 33623812
Good thinking! Thankyou for responding.
0
 
LVL 10

Author Comment

by:ReneGe
ID: 33624032
Hi guys,

I arrived not long ago from work.

As for the points, I splitted them according to the level of contribution in this thread at the moment of closing it. I just hope it was fair. You both deserve 500 points and I feel bad not being able to give more.

==>Psy,
Windows Server 2003 : Version 5.2
Microsoft (R) Windows Script Host Version 5.6
>Get degrad infos works

Windows XP Pro : Version 5.1
Microsoft (R) Windows Script Host Version 5.7
>Get degrad infos does not work


Thanks and cheers,
Rene
0
 
LVL 65

Expert Comment

by:RobSampson
ID: 33624091
Oh yeah, I didn't notice you gave Psy an assist....that's fine with me.
0

Featured Post

Netscaler Common Configuration How To guides

If you use NetScaler you will want to see these guides. The NetScaler How To Guides show administrators how to get NetScaler up and configured by providing instructions for common scenarios and some not so common ones.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Does the idea of dealing with bits scare or confuse you? Does it seem like a waste of time in an age where we all have terabytes of storage? If so, you're missing out on one of the core tools in every professional programmer's toolbox. Learn how to …
Entering a date in Microsoft Access can be tricky. A typo can cause month and day to be shuffled, entering the day only causes an error, as does entering, say, day 31 in June. This article shows how an inputmask supported by code can help the user a…
An introduction to basic programming syntax in Java by creating a simple program. Viewers can follow the tutorial as they create their first class in Java. Definitions and explanations about each element are given to help prepare viewers for future …
In this fourth video of the Xpdf series, we discuss and demonstrate the PDFinfo utility, which retrieves the contents of a PDF's Info Dictionary, as well as some other information, including the page count. We show how to isolate the page count in a…

770 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question