Code checks one drive for three different drive letters - vbscript

So I have created a code that reads the following text file:
Diskspace C:
Diskspace D:
Diskspace E:
Memory
CPU
And check usage for each type of "hardware" listed.
I only have a disk C: on my computer, so how can I put an error message for any disk that doesn't work?
What happens in my script now is since I have "On Error Resume Next", my code checks whatever disk it can analyze, and inputs that answer (aka disk C:) for each disk. For example, in my wscript.echo box, it says
Disk C: is 93.4% free.
Disk D: is 93.4% free.
Disk E: is 93.4% free.
I know that this is wrong.
On Error Resume Next
Set objFSO = CreateObject("Scripting.FileSystemObject")
Set objReadFile = objFSO.OpenTextFile("M:\vbscripts\ServerHealthCheck_Control.txt")
message = ""
Do While objReadFile.AtEndOfStream <> True
strLine = objReadFile.ReadLine
If Left(strLine, 1) = "D" then
letter = Mid(strLine, 11, 2)
Set fso = CreateObject("Scripting.FileSystemObject")
Set drive = fso.GetDrive(letter)
totalSpace = drive.TotalSize / 1024
freeSpace = drive.AvailableSpace / 1024
percentFree = freeSpace / totalSpace
number = FormatNumber(percentFree*100, 2)
'WARNING_MESSAGE = Mid(strLine, 14, 2)
'ERROR_MESSAGE = Mid(strLine, 17, 2)
message = message & "Drive " & letter & " is " & number & "% free." & vbCrlf
Elseif Left(strLine, 1) = "M" then
Const CONVERT = 1048576 ' This is total bytes in 1 MB.
Const strComputer = "."
Set objWMIService = GetObject("winmgmts:\\" & strComputer & "\root\CIMV2")
Set colSettings = objWMIService.ExecQuery ("Select * from Win32_OperatingSystem")
For Each objOperatingSystem in colSettings
intFreeMem = objOperatingSystem.FreePhysicalMemory / CONVERT
intTotalMem = objOperatingSystem.TotalVisibleMemorySize / CONVERT
Memory = intFreeMem / intTotalMem * 100
message = message & "Memory is " & FormatNumber(Memory,2) & "% free." & vbCrlf
Next
Elseif Left(strLine, 1) = "C" then
Set objWMIService = GetObject("winmgmts:\\localhost\root\CIMV2")
Set CPUInfo = objWMIService.ExecQuery("SELECT * FROM Win32_PerfFormattedData_PerfOS_Processor",,48)
For Each Item in CPUInfo
If Item.Name = "_Total" Then
message = message & "Total CPU usage is " & Item.PercentProcessorTime & "%."
End If
Next
End If
Loop
Wscript.Echo message
EDIT: I have tried the following but it doesn't seem to work:
If fso.GetDrive(letter) = error then
message = message & "The drive " & letter & " cannot be read."
Elseif fso.GetDrive(letter) <> error then
totalSpace = drive.TotalSize / 1024
freeSpace = drive.AvailableSpace / 1024
percentFree = freeSpace / totalSpace
number = FormatNumber(percentFree*100, 2)
message = message & "Drive " & letter & " is " & number & "% free." & vbCrlf
End If
It displays that E: is an error, but disk D still copies disk C.

Replace the EVIL global OERN with a strictly local one (a call of a Sub/Function containing the risky operation(s)). As in:
Option Explicit
Dim goFS : Set goFS= CreateObject("Scripting.FileSystemObject")
Function RiskyGetDrive(sDL)
' maybe lots of lines here, immediate exit on first error
Set RiskyGetDrive = goFS.GetDrive(sDL) ' could be unavailable
Dim dummy : dummy = RiskyGetDrive.TotalSize ' could be not ready
End Function
Dim sDL, oDrv, aErr
For Each sDL in Split("C D E Q")
' error hiding for just one risky operation and copy of (possible) error data
On Error Resume Next
Set oDrv = RiskyGetDrive(sDL)
aErr = Array(Err.Number, Err.Description)
On Error GoTo 0
If aErr(0) Then
WScript.Echo sDL, "Diag:", aErr(0), aErr(1)
Else
'not needed, if "not ready" is provoked in function
'If Not oDrv.IsReady Then
' WScript.Echo sDL, "Diag:", "not ready"
'Else
' WScript.Echo sDL, "Info:", oDrv.TotalSize / 1024
'End If
WScript.Echo sDL, "Info:", oDrv.TotalSize / 1024
End If
Next
output:
cscript 41173138.vbs
C Info: 41929616
D Diag: 71 Disk not ready
E Info: 227784528
Q Diag: 68 Device unavailable

You can get help on WMI by using the command line utility wmic /? and wmic logicaldisk get /?
wmic logicaldisk get caption,freespace
outputs the freespace on ALL drives. In VBScript the above becomes
Set colSettings = objWMIService.ExecQuery ("Select * from Win32_LogicalDisk")
For Each objdisk in colSettings
wscript.echo objdisk.caption & " " & objdisk.freespace
Next
You can use a where clause in both VBScript or WMIC.
wmic logicaldisk where (caption="C:" or caption="D:" or caption="E:") get caption,freespace

Related

Convert batch to VBS script

I am running this command remotely in a VBS script file. The problem I am having is that it generates a CMD window momentarily and it distracts some users. How can I run this without generating the CMD window? Preferably, I want to get the WMI data in native VBS language without using oShell.run? I rather not use CMD. Thanks.
oShell.run "cmd /c wmic logicaldisk get name,providername,description,volumename,filesystem /format:list > c:\users\%username%\drives.txt"
Or you could just use what you've already got and pass the 'hidden window' parameter to the Run command (see the second parameter of 0 below):
Dim objShell : Set objShell = WScript.CreateObject("WScript.Shell")
objShell.Run "cmd /c wmic logicaldisk get name,providername,description,volumename,filesystem /format:list > c:\users\%username%\drives.txt", 0, true
Set objShell = Nothing
You can give a try for this code in pure vbscript :
Option Explicit
Dim Ws,ReportFile,strHomeFolder
Set Ws = CreateObject("WScript.Shell")
strHomeFolder = Ws.ExpandEnvironmentStrings("%USERPROFILE%")
ReportFile = strHomeFolder & "\drives.txt"
'MsgBox GetDrives_Information
Call WriteReport(GetDrives_Information,ReportFile)
'-------------------------------------------------------
Function GetDrives_Information()
Dim oFSO,report,objWMIService,objLogicalDisk
Set oFSO = CreateObject("Scripting.FileSystemObject")
Dim oDrives
Set oDrives = oFSO.Drives
Dim oDrive
Dim strLectType
on error resume next
For Each oDrive in oDrives
If oDrive.IsReady Then
Select Case oDrive.DriveType
Case 0: strLectType = "Unknown"
Case 1: strLectType = "Amovible (USB)"
Case 2: strLectType = "Fixe (Hard Drive)"
Case 3: strLectType = "Network"
Case 4: strLectType = "CD-Rom"
Case 5: strLectType = "Virtuel"
End Select
report = report & "- Drive letter: " & oDrive.DriveLetter & vbCrLf
report = report & "- serial number: " & oDrive.SerialNumber & vbCrLf
report = report & "- Drive Type: " & oDrive.strLectType & vbCrLf
If (oDrive.FileSystem <> "") Then
report = report & "- File system used : " & oDrive.FileSystem & vbCrLf
End If
Set objWMIService = GetObject("winmgmts:")
Set objLogicalDisk = objWMIService.Get("Win32_LogicalDisk.DeviceID='" & oDrive.DriveLetter & ":'")
report = report & "- There is " & objLogicalDisk.FreeSpace /1024\1024+1 & " Mo remaining space on this drive / disk" & vbCrLf
report = report & "- There is " & objLogicalDisk.Size /1024\1024+1 & " Mo total space on this drive / disk" & vbCrLf
End If
report = report & vbCrLf
Next
GetDrives_Information = report
End Function
'-------------------------------------------------------
Sub WriteReport(strText,ReportFile)
Dim fs,ts
Const ForWriting = 2
Set fs = CreateObject("Scripting.FileSystemObject")
Set ts = fs.OpenTextFile(ReportFile,ForWriting,True)
ts.WriteLine strText
ts.Close
End Sub
'------------------------------------------------------

Check free space of C drive in multiple computers via ip address

I want script that check free space of C drive in multiple computers via set list of IP's.. from text. file
I want the script for windows 7 environment..
and the script should check the free space of C drive, and if is less than 10gb, then it will show me that ip...
I tried with fsutil but this work just in local machine, and I have a lot computers.
Hope some can help me with that.
Create the following files:
computers.txt
computername1
10.40.1.60
You can specify computers name or their ips.
CheckDiskFree.vbs
'
' Check drive c free space
'
On Error Resume Next
Const MIN_FREE = 10 ' Gb
Const ForAppending = 8
Const HARD_DISK = 3
Const ForReading = 1
CONST ForWriting = 2
Set objFSO = CreateObject("Scripting.FileSystemObject")
Set SrvList = objFSO.OpenTextFile("computers.txt", ForReading)
Set oShell = CreateObject("WScript.Shell")
Set ReportFile = objFSO.OpenTextFile ("FreeSpaceReport.csv", ForAppending, True)
'
' Report headers
'
ReportFile.writeline "Computer" & vbTAB & "Drive C Free (Gb)" & vbTAB & "Status"
'
' Loop
'
Do Until SrvList.AtEndOfStream
StrComputer = SrvList.Readline
wscript.echo now & vbTAB & StrComputer
If Not IsConnectible(strComputer, "", "") Then
ReportFile.writeline(strComputer & vbTAB & " no available")
Else
Set objWMIService = GetObject("winmgmts:" _
& "{impersonationLevel=impersonate}!\\" & strComputer & "\root\cimv2")
Set colDisks = objWMIService.ExecQuery _
("Select * from Win32_LogicalDisk Where DriveType = " & HARD_DISK & " AND DeviceID = 'C:' ")
For Each objDisk in colDisks
FreeGB = objDisk.FreeSpace / (1024 * 1024 * 1024)
strStatus = "ok"
If FreeGB < MIN_FREE Then strStatus = "Low disk"
ReportFile.writeline(strComputer & vbTAB & Round(FreeGB,2) & vbTAB & strStatus)
Next
End If
Loop
'
Wscript.Quit
Function WMIDateStringToDate(dtmBootup)
WMIDateStringToDate = CDate(Mid(dtmBootup, 7, 2) & "/" & _
Mid(dtmBootup, 5, 2) & "/" & Left(dtmBootup, 4) _
& " " & Mid (dtmBootup, 9, 2) & ":" & _
Mid(dtmBootup, 11, 2) & ":" & Mid(dtmBootup, _
13, 2))
End Function
Function IsConnectible(sHost, iPings, iTO)
' Returns True or False based on the output from ping.exe
'
' Author: Alex Angelopoulos/Torgeir Bakken
' Works an "all" WSH versions
' sHost is a hostname or IP
' iPings is number of ping attempts
' iTO is timeout in milliseconds
' if values are set to "", then defaults below used
Const OpenAsASCII = 0
Const FailIfNotExist = 0
Const ForReading = 1
Dim sTempFile, fFile
If iPings = "" Then iPings = 2
If iTO = "" Then iTO = 750
sTempFile = objFSO.GetSpecialFolder(2).ShortPath & "\" & objFSO.GetTempName
oShell.Run "%comspec% /c ping.exe -n " & iPings & " -w " & iTO & " " & sHost & ">" & sTempFile, 0 , True
Set fFile = objFSO.OpenTextFile(sTempFile, ForReading, FailIfNotExist, OpenAsASCII)
Select Case InStr(fFile.ReadAll, "TTL=")
Case 0 IsConnectible = False
Case Else IsConnectible = True
End Select
fFile.Close
objFSO.DeleteFile(sTempFile)
End Function
To run script you must execute the following command: cscript CheckDiskFree.vbs
The script will create FreeSpaceReport.csv with the results.

vbscript need to detect drive letter and ask for user input

I already have the script that ask user input to install the file "install1.exe" to "install6.exe" with default drive letter path D:\, I have another drive can get the drive letter like "C:", not sure how to integrate
First I need to have drive letter check to confirm the computer have drive D physical local disk (not cdrom), if yes prompt user confirm to proceed
or user can click no to enter a drive letter, the drive letter also need to update on current install script {D}:\temp\install1.exe
drive letter script
Dim query
Dim objWMI
Dim diskDrives
Dim diskDrive
Dim partitions
Dim partition ' will contain the drive & partition numbers
Dim logicalDisks
Dim logicalDisk ' will contain the drive letter
Set objWMI = GetObject("winmgmts:\\.\root\cimv2")
Set diskDrives = objWMI.ExecQuery("SELECT * FROM Win32_DiskDrive") ' First get out the physical drives
For Each diskDrive In diskDrives
query = "ASSOCIATORS OF {Win32_DiskDrive.DeviceID='" + diskDrive.DeviceID + "'} WHERE AssocClass = Win32_DiskDriveToDiskPartition" ' link the
physical drives to the partitions
Set partitions = objWMI.ExecQuery(query)
For Each partition In partitions
query = "ASSOCIATORS OF {Win32_DiskPartition.DeviceID='" + partition.DeviceID + "'} WHERE AssocClass = Win32_LogicalDiskToPartition" ' link
the partitions to the logical disks
Set logicalDisks = objWMI.ExecQuery (query)
For Each logicalDisk In logicalDisks
' Wscript.Echo logicalDisk.DeviceID & " - " & partition.Caption
Wscript.Echo logicalDisk.DeviceID
'else
Next
Next
Next
Install script
Dim objShell
Dim Message, result
Dim Title, Text1, Text2
' Define dialog box variables.
Message = "Please enter a path"
Title = "Install Started"
Text1 = "Install Cancelled"
Text2 = "You entered value is incorrect, please select from 1,2,3,4,5 or 6" & vbCrLf
result = InputBox("Please select the by number"& Chr(13) & "A" & Chr(13) & "B" & Chr(13) & "C" & Chr(13) & "D" & Chr(13) & "E" & Chr(13) & "F", Title, "Please enter the number", 100, 100)
Set objShell = WScript.CreateObject( "WScript.Shell" )
' Evaluate the user input.
If result = "" Then ' Canceled by the user
WScript.Echo Text1
ElseIf result = "1" Then
objShell.Run("7z.exe x temp.7z -oD:\ -bd -y")
wscript.sleep (3000)
objShell.Run("D:\temp\install1.exe")
wscript.sleep (150000)
wScript.Echo "install Completed"
ElseIf result = "2" Then
......
......
......
Else
WScript.Echo Text2 & result
End If
wscript.quit
thank you

Check if a drive is mapped and active

I have a requirement within my VBScript to ensure that a drive is mapped and contactable.
Initially I was using only the DriveExists() method of the FileSystemObject, but this fell short as in certain scenarios users start the day in the office but then take their laptops on tour, without shutting down; thus the drive in question is still listed as mapped, but is not contactable.
To Address this I have created the below function, but it seems a bit dirty due to the use of On Error Resume Next.
So my question is this; is there a method that achieves my goal built in to VBS, or is my approach (or similar) the only way it can be done?
Function CheckDriveExists(drive)
CheckDriveExists = false
If FSO.DriveExists(drive) Then ' A drive is mapped for the required 'drive'
'** Create a file name for the test file *'
Dim tfDate, tfName
tfDate = Year(Now) & Month(Now) & Day(Now) & Hour(Now) & Minute(Now) & Second(Now)
tfName = "tstfile-" & tfDate & ".bucf"
'** Try to create and then delete a file on the usrs backup drive *'
On Error Resume Next
FSO.CreateTextFile(drive & ":\" & tfName)
FSO.DeleteFile(drive & ":\" & tfName)
CheckDriveExists = (Err.Number = 0) ' Check to see if the file was created and deleted successfully
Err.Clear ' Clear any possible error
On Error GoTo 0 ' Reset error handling
End If
End Function
from Windows Scripting documentation
Function ShowDriveList
Dim fso, d, dc, s, n
Set fso = CreateObject("Scripting.FileSystemObject")
Set dc = fso.Drives
For Each d in dc
n = ""
s = s & d.DriveLetter & " - "
If d.DriveType = 3 Then
n = d.ShareName
ElseIf d.IsReady Then
n = d.VolumeName
Else
n = "[Drive not ready]"
End If
s = s & n & "<BR>"
Next
ShowDriveList = s
End Function
perhaps you also need
Function ShowDriveType(drvpath)
Dim fso, d, t
Set fso = CreateObject("Scripting.FileSystemObject")
Set d = fso.GetDrive(drvpath)
Select Case d.DriveType
Case 0: t = "Unknown"
Case 1: t = "Removable"
Case 2: t = "Fixed"
Case 3: t = "Network"
Case 4: t = "CD-ROM"
Case 5: t = "RAM Disk"
End Select
ShowDriveType = "Drive " & d.DriveLetter & ": - " & t
End Function

Enumerating Sub-Folder Properties with VBscript

This is somewhat related to Microsoft System Center Configuration Manager 2007, but it's really about an issue with VBScript, the FileSystemObject API and reading sub-folder properties.
I am trying to run a script to enumerate the folders and folder sizes on one of our Distribution Points (every folder beneath the Package Share). I'm using the FileSystemObject API, with VBscript, I can crawl about 60% of the sub-folders, and get their names and sizes, but then the rest return "error 70 / Permission Denied". It doesn't matter what account I execute the script as, and I've tried adding a Sleep() delay between each sub-folder object reference. It still won't get them all.
If I manually explore the folders, I can view their properties without any problem. Is this a known issue with FSO or maybe Windows Scripting Host? I've attached the script code below. TIA!
'****************************************************************
' Filename..: fso_subfolder_sizes.vbs
' Author....: skatterbrainz
' Date......: 02/10/2013
' Purpose...: enumerate package folders and tally disk space
'****************************************************************
Option Explicit
Const rootFolder = "\\SERVER123\ShareName$"
Dim time1, folderCount, totalSpace
Dim objFSO, objFolder, objSub
Dim GBsize, folderName, folderSIze
time1 = Timer
Set objFSO = CreateObject("Scripting.FileSystemObject")
folderCount = 0
totalSpace = 0
On Error Resume Next
Set objFolder = objFSO.GetFolder(rootFolder)
If err.Number = 0 Then
wscript.echo "<folders>"
For each objSub in objFolder.SubFolders
folderName = objSub.Name
folderSize = objSub.Size
GBsize = FormatNumber(Bytes2Gbytes(folderSize), 2) & " GB"
wscript.echo "<folder name=""" & folderName & """ size=""" & GBsize & """/>"
folderCount = folderCount + 1
totalSpace = totalSpace + folderSize
Next
Set objFolder = Nothing
wscript.echo "</folders>"
wscript.echo "--------------------------"
wscript.echo "sub-folders: " & folderCount
wscript.echo "total space: " & FormatNumber(Bytes2GBytes(totalSpace),2) & " GB"
Else
wscript.echo "root folder not found"
End If
Set objFSO = Nothing
wscript.echo "runtime: " & FormatNumber(Timer - time1, 2) & " Msecs"
Function Bytes2Gbytes(n)
If n > 0 Then
Bytes2Gbytes = (n / 1024 / 1024 / 1024)
Else
Bytes2Gbytes = 0
End If
End Function
Yes this is a known issue, on folders with security issues (like eg your c:\windows folder) you get errors when you use .count of .size on folder. Instead enumerate each file and sum the count and size.
I had the same problem when trying to get profile size of each UserProfile from a share. I used excel and was looping through rows with usernames that I knew had a profile in the share, like this:
strUserName = ActiveCell.Value
objP = "\\SERVER\SHARE$\" & strUserName & "\UPM_Profile"
ActiveCell.Offset(0, 1).Value = (FormatNumber(objFSO.GetFolder(objP).Size, 0, , , 0) / 1024) / 1024
Just some of the thousands folders gave "Path Not Found"
It all worked when I instead mapped the Share to a driveletter:
objP = "Z:\" & strUserName '& "\UPM_Profile"
I found an interesting, yet reproducible behavior with this topic. At least in our production environment: If I specify the root path as the root hidden share (i.e. "\SERVER\Share$") it gets really bogged down. But if I go one level deeper, such as "\SERVER\Share$\Apps") it seems to run much better. I also modified the script to print the sub-folder name first, and THEN query the .Size property, and that seems to point to the performance bottleneck. Note the change in statement ordering in the updated example below...
For each objSub in objFolder.SubFolders
folderName = objSub.Name
wscript.echo vbTab & "<folder>"
wscript.echo vbTab & vbTab & "<folderName>" & folderName & "</folderName>"
folderSize = objSub.Size
GBsize = FormatNumber(Bytes2Gbytes(folderSize), 2) & " GB"
wscript.echo vbTab & vbTab & "<folderSize>" & GBsize & "</folderSize>"
wscript.echo vbTab & "</folder>"
folderCount = folderCount + 1
totalSpace = totalSpace + folderSize
Next

Resources