February 2nd, 2009

Hey, Scripting Guy! How Can I Tell How Much Free Disk Space a User Has?

Hey, Scripting Guy! Question

I know most people have heard of Moore’s Law that is named after Gordon Moore, but have you ever heard of Bob’s law? Bob was the senior network administrator when I first became an IT pro, and he created what he called Bob’s Law. Briefly stated it says this: “A user’s demand for storage space will always expand to meet the available storage space, plus 10 percent.” In other words, we can never have too much disk space for users.

Well, at work, we are currently being ravaged by Bob’s Law; our users are constantly running out of disk space on their work stations, their laptops, and even their Windows smart phones. I go into some offices, and they have USB sticks stuck in every available port on their laptops, and some users have even gone so far as to buy external USB hubs and stick stuff in there as well. The things look like some kind of infernal terminator porcupine. I know we cannot suspend Bob`s Law, but I need a script that I can run remotely that will tell me how much free disk space a user has. Can you help me?

– EC

SpacerHey, Scripting Guy! Answer

Hi EC,

So your users say they do not have enough free disk space? Tell them to open Windows PowerShell and type Format c…just kidding. That command will delete all their files. That is an old IT joke, about as old as Bob’s law.

This week is Desktop Week—a rather vague series of loosely connected articles that may or may not be related to desktops. But the articles were written on a desktop, so maybe that counts. If you want to see some VBScript examples of Desktop Management scripts, check out these scripts in the Script Center Script Repository. The Community-Submitted Scripts Center also has a collection of scripts related to desktop management. In addition, there is the Desktop Management archive of “Hey Scripting Guy!” articles, which include scripts and explanations as well. The scripts this week will be using Windows PowerShell. To download Windows PowerShell and to find getting started information, see the Windows PowerShell hub.

To aid you in managing your users’ incessant demands for disk space, it might be useful to be able to retrieve the amount of free disk space from a remote computer before it becomes a crisis. We can use the Win32_LogicalDisk WMI class with the Get-WmiObject cmdlet from Windows PowerShell. An example of doing this is seen in the GetFreeDiskSpace.ps1 script.

Get-FreeDiskSpace.ps1

Function Get-FreeDiskSpace($drive,$computer)
{
 $driveData = Get-WmiObject -class win32_LogicalDisk `
 -computername $computer -filter "Name = '$drive'"
"$computer free disk space on drive $drive"
"{0:n2}" -f ($driveData.FreeSpace/1MB) + " MegaBytes"
}
Get-FreeDiskSpace -drive "C:" -computer "vista"

The first thing we do in the Get-FreeDiskSpace.ps1 script is to create a function. To create a function that uses multiple input parameters we use the Function keyword, specify the name of the function, use variables for each input parameter, and define the script block within the curly brackets.

The Get-FreeDiskSpace.ps1 script begins with the Function keyword, the name of the function, and the two input parameters. The first input parameter is the drive name, and the second is the name of the computer. The input parameters are placed inside smooth parentheses with a variable used to hold the data that comes in when the function is called:

Function Get-FreeDiskSpace($drive,$computer)
{

Inside the curly brackets the Get-FreeDiskSpace function uses the Get-WmiObject cmdlet to query the Win32_LogicalDisk WMI class. It connects to the computer specified in the $computer parameter, and it filters out only the drive that is specified in the $drive parameter. When the function is called, the parameters are specified as –drive and –computer. In the function definition, the variables $drive and $computer are used to hold the values supplied to the parameters.

The –filter parameter from the Get-WmiObject cmdlet is used to limit the number of instances that are returned by the WMI query. The filter takes the place of the whereclause from VBScript WMI Query Language (WQL) statements. The filter in our script limits the number of instances that are returned to only the one specified in the $drive variable. Here is our filter:

-filter "Name = '$drive'

The thing that is perhaps surprising is that the value contained in the $drive variable still gets read. You may recall from previous “Hey, Scriting Guy!” articles that I went on and on at great length about the difference between literal quotation marks and expanding quotation marks. We also have this documented as a Windows PowerShell tip. Well, you can forget that here. When you are working with the filter parameter of the Get-WmiObject cmdlet, you are using WQL syntax, not Windows PowerShell syntax. This is why you use the equal sign instead of –eq. It is also why the single quotation mark is not a literal quotation mark, so we still have access to the value of the $drive variable.

An excellent reference for learning WMI is the Microsoft Press book, Microsoft Windows Scripting with WMI: Self-Paced Learning Guide. While the examples are all written in VBScript, WMI technology is still the same.

If we were to use the Get-WmiObject cmdlet by itself and query the Win32_Logicaldisk WMI class, we would see an output similar to this:

Output of the Win32_Logicaldisk WMI class queried by the Get-WmiObject cmdlet

 

There is more data returned from the WMI query than that which is displayed in the preceding image. Windows PowerShell creates s a nice display of information that is considered to be most useful to the network administrator. If you want to see more information, you can easily obtain it by using either the methods or properties seen in Table 1.

After the data from WMI is retrieved, it is stored in the $driveData variable. The data that is stored in the $driveData variable is an instance of the Win32_LogicalDisk. This variable contains a complete instance of the class. The members of this class are seen in Table 1.

Table 1 Members of the Win32_LogicalDisk class

Name Member Type Definition

Chkdsk

Method

System.Management.ManagementBaseObject Chkdsk(System.Boolean FixErrors, System.Boolean VigorousIndexCheck, System.Boolean SkipFolderCycle, System.Boolean ForceDismount, System.Boolean RecoverBadSectors, System.Boolean OkToRunAtBootUp)

Reset

Method

System.Management.ManagementBaseObject Reset()

SetPowerState

Method

System.Management.ManagementBaseObject SetPowerState(System.UInt16 PowerState, System.String Time)

Access

Property

System.UInt16 Access {get;set;}

Availability

Property

System.UInt16 Availability {get;set;}

BlockSize

Property

System.UInt64 BlockSize {get;set;}

Caption

Property

System.String Caption {get;set;}

Compressed

Property

System.Boolean Compressed {get;set;}

ConfigManagerErrorCode

Property

System.UInt32 ConfigManagerErrorCode {get;set;}

ConfigManagerUserConfig

Property

System.Boolean ConfigManagerUserConfig {get;set;}

CreationClassName

Property

System.String CreationClassName {get;set;}

Description

Property

System.String Description {get;set;}

DeviceID

Property

System.String DeviceID {get;set;}

DriveType

Property

System.UInt32 DriveType {get;set;}

ErrorCleared

Property

System.Boolean ErrorCleared {get;set;}

ErrorDescription

Property

System.String ErrorDescription {get;set;}

ErrorMethodology

Property

System.String ErrorMethodology {get;set;}

FileSystem

Property

System.String FileSystem {get;set;}

FreeSpace

Property

System.UInt64 FreeSpace {get;set;}

InstallDate

Property

System.String InstallDate {get;set;}

LastErrorCode

Property

System.UInt32 LastErrorCode {get;set;}

MaximumComponentLength

Property

System.UInt32 MaximumComponentLength {get;set;}

MediaType

Property

System.UInt32 MediaType {get;set;}

Name

Property

System.String Name {get;set;}

NumberOfBlocks

Property

System.UInt64 NumberOfBlocks {get;set;}

PNPDeviceID

Property

System.String PNPDeviceID {get;set;}

PowerManagementCapabilities

Property

System.UInt16[] PowerManagementCapabilities {get;set;}

PowerManagementSupported

Property

System.Boolean PowerManagementSupported {get;set;}

ProviderName

Property

System.String ProviderName {get;set;}

Purpose

Property

System.String Purpose {get;set;}

QuotasDisabled

Property

System.Boolean QuotasDisabled {get;set;}

QuotasIncomplete

Property

System.Boolean QuotasIncomplete {get;set;}

QuotasRebuilding

Property

System.Boolean QuotasRebuilding {get;set;}

Size

Property

System.UInt64 Size {get;set;}

Status

Property

System.String Status {get;set;}

StatusInfo

Property

System.UInt16 StatusInfo {get;set;}

SupportsDiskQuotas

Property

System.Boolean SupportsDiskQuotas {get;set;}

SupportsFileBasedCompression

Property

System.Boolean SupportsFileBasedCompression {get;set;}

SystemCreationClassName

Property

System.String SystemCreationClassName {get;set;}

SystemName

Property

System.String SystemName {get;set;}

VolumeDirty

Property

System.Boolean VolumeDirty {get;set;}

VolumeName

Property

System.String VolumeName {get;set;}

VolumeSerialNumber

Property

System.String VolumeSerialNumber {get;set;}

__CLASS

Property

System.String __CLASS {get;set;}

__DERIVATION

Property

System.String[] __DERIVATION {get;set;}

__DYNASTY

Property

System.String __DYNASTY {get;set;}

__GENUS

Property

System.Int32 __GENUS {get;set;}

__NAMESPACE

Property

System.String __NAMESPACE {get;set;}

__PATH

Property

System.String __PATH {get;set;}

__PROPERTY_COUNT

Property

System.Int32 __PROPERTY_COUNT {get;set;}

__RELPATH

Property

System.String __RELPATH {get;set;}

__SERVER

Property

System.String __SERVER {get;set;}

__SUPERCLASS

Property

System.String __SUPERCLASS {get;set;}

PSStatus

PropertySet

PSStatus {Status, Availability, DeviceID, StatusInfo}

ConvertFromDateTime

ScriptMethod

System.Object ConvertFromDateTime();

ConvertToDateTime

ScriptMethod

System.Object ConvertToDateTime();

After you have the data stored in the $driveData variable, you will want to print out some information to the user of the script. The first thing to do is print out the name of the computer and the name of the drive. To do this, you can place the variables inside double quotation marks. Double quotation marks are expanding strings, and variables placed inside double quotation marks emit their value, not their name. This is seen here:

"$computer free disk space on drive $drive"

The next thing you will want to do is to format the data that is returned. To do this, use the .NET Framework format strings to specify two decimal places. We will need to use smooth parentheses to force the evaluation of the free disk space prior to formatting it to two decimal places. This is seen here:

"{0:n2}" -f ($driveData.FreeSpace/1MB) + " MegaBytes"

When you run the script you see the name of the computer, the name of the drive, and the amount of free disk space expressed in megabytes:

office free disk space on drive C:
54,108.36 MegaBytes

Well, EC, that is about it for using WMI to obtain free disk space. Join us tomorrow as Desktop Week continues. Until then, peace.

 

Ed Wilson and Craig Liebendorfer, Scripting Guys

Author

0 comments

Discussion are closed.