Solved

VBScript: Analyze Volume Defragmentation

Posted on 2010-09-07
30
1,033 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
 
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
What Security Threats Are You Missing?

Enhance your security with threat intelligence from the web. Get trending threat insights on hackers, exploits, and suspicious IP addresses delivered to your inbox with our free Cyber Daily.

 
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

How your wiki can always stay up-to-date

Quip doubles as a “living” wiki and a project management tool that evolves with your organization. As you finish projects in Quip, the work remains, easily accessible to all team members, new and old.
- Increase transparency
- Onboard new hires faster
- Access from mobile/offline

Join & Write a Comment

Not long ago I saw a question in the VB Script forum that I thought would not take much time. You can read that question (Question ID  (http://www.experts-exchange.com/Programming/Languages/Visual_Basic/VB_Script/Q_28455246.html)28455246) Here (http…
Go is an acronym of golang, is a programming language developed Google in 2007. Go is a new language that is mostly in the C family, with significant input from Pascal/Modula/Oberon family. Hence Go arisen as low-level language with fast compilation…
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 seventh video of the Xpdf series, we discuss and demonstrate the PDFfonts utility, which lists all the fonts used in a PDF file. It does this via a command line interface, making it suitable for use in programs, scripts, batch files — any pl…

757 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

Need Help in Real-Time?

Connect with top rated Experts

21 Experts available now in Live!

Get 1:1 Help Now