Jump to page sections
- Download
- Parameters
- Examples
- Showing Used/Free Space On Mount Points
- Including Root Drives
- Sorting By Drive Letter
- Code
In the latest version, v1.2 as of 2015-03-01, it also maps the physical disk index to the mount points and/or drive letters. This was not entirely trivial - and a PowerShell solution didn't exist in an easily accessible, public form until this early March / late February 2015 weekend. Read more in the "change log" in the downloads section (except the formatting is messed up, sorry...).
Note added 2022-02-28: I plan to rewrite this with a proper design. Looks like I put it off for 7 years so far. Will I make 8? The code does work, but it is not well-designed. The latched-on, monkey-patched PSRemoting to add the disk class is ugly.
This has a few side-effects, such as filtering out the default "System Reserved" partition entry (introduced in Win 7 / Server 2008 R2, I think) that's listed if you only look at the Win32_Volume class and filter on something like the DriveLetter property not being set.
It uses WMI against remote computers with the -ComputerName parameter. Specify the name "localhost" for data about the local host. You can specify multiple servers separated by commas. I'll look into writing a CIM version.I also added a parameter called -IncludeRootDrives which allows you to look at regular disk drive letters on the desired servers as well, in the same way.
The parameter -IncludeDiskInfo (v1.2+) requires PSRemoting to work.Output is by default sorted on free available space in percent, then descendingly on drive size (if the percentage is exactly the same), then by the label property and finally by caption.
I implemented it as functions, but didn't package it as a module. You can dot-source the ps1 file you download to get the functions in the currently available scope, or put it in your PowerShell profile. It is also possible to name the file Get-MountPointData.psm1 and put it in a subfolder of one of your $env:PSModulePath folders; if so, you would later import it with Import-Module, or have it autoloaded with PSv3 and up. You can also import it from a relative path with Import-Module.The script is written so it's fairly easy to add other properties that you might want to list.
Download
*Get-MountPointData.ps1.txt '''v1.1'''. Right click and save. PSv2-compatible. No -IncludeDiskInfo parameter.
''2015-03-01: Quickly spun around and added -Credential support for the Invoke-Command that's used when you supply the -IncludeDiskInfo parameter. The rest is WMI. I should look into a CIM version.''
''2014-11-07: Uploaded a new version I wrote months ago when I needed math operations on the space. Use the parameter -NoFormat for that. Also added support for specifying credentials with -Credential or -PromptForCredentials''
Parameters
|-
|ComputerName
|Target computer(s).
|-
|PromptForCredentials
|Prompts for credentials to use for the WMI calls, and for Invoke-Command with the -IncludeDiskInfo parameter.
|-
|Credential
|Pass a credentials object to use for the WMI calls, and for Invoke-Command with the -IncludeDiskInfo parameter.
|-
|IncludeRootDrives
|Includes volumes with drive letters.
|-
|NoFormat
|Do not format numbers, so you can do math operations easily (very useful in certain situations).
|-
|IncludeDiskInfo
|Includes disk index number of the disk the mount point or drive letter resides on (should also support spanned volumes and multiple indices, but that's untested). Requires administrator privileges.
Examples
Showing Used/Free Space On Mount Points
PS C:\> . .\scripts\Get-MountPointData.ps1 PS C:\> Get-MountPointData -ComputerName file_server01 | Format-Table -AutoSize Computer Label Caption FileSystem Size (GB) Free space Percent free -------- ----- ------- ---------- --------- ---------- ------------ file_server01 Dept0001 E:\foo\Dept0001 NTFS 250.00 37.73 15.09 file_server01 Dept0002 E:\foo\Dept0002 NTFS 500.00 83.13 16.63 file_server01 Dept0003 E:\foo\Dept0003 NTFS 350.00 73.38 20.97 file_server01 Dept0004 E:\bar\Dept0004 NTFS 150.00 50.37 33.58 file_server01 Dept0005 E:\bar\Dept0005 NTFS 150.00 56.89 37.93 file_server01 Dept0006 E:\bar\Dept0006 NTFS 300.00 124.42 41.47 file_server01 Dept0007 E:\baz\Dept0007 NTFS 100.00 45.10 45.11 file_server01 Dept0008 E:\baz\Dept0008 NTFS 70.00 31.90 45.57 file_server01 Dept0009 E:\foo\Dept0009 NTFS 300.00 157.08 52.36 file_server01 Dept0010 E:\foo\Dept0010 NTFS 200.00 109.37 54.68 file_server01 Dept0011 E:\foo\Dept0011 NTFS 300.00 191.93 63.98
Including Root Drives
PS C:\> Get-MountPointData -Comp filesrv2 -IncludeRootDrives | ft -a Computer Label Caption FileSystem Size (GB) Free space Percent free -------- ----- ------- ---------- --------- ---------- ------------ filesrv2 H:\ 0.00 0.00 filesrv2 USER D:\ NTFS 1,945.59 157.36 8.09 filesrv2 User3 F:\ NTFS 711.99 85.11 11.95 filesrv2 User4 G:\ NTFS 711.99 115.16 16.17 filesrv2 User2 E:\ NTFS 549.99 137.36 24.97 filesrv2 C:\ NTFS 48.83 22.24 45.54
"H:\" is an optical drive. The drives are sorted descendingly after percentage of free space by default, but you can use -Noformat and sort on size, free space, multiple values, or whatever you want.
Sorting By Drive Letter
To sort by drive letter, you can add "Sort Computer, Caption" to the pipeline before Format-Table -AutoSize. If you only target a single server, you can omit the "Computer" property and sort by caption only.
PS C:\> Get-MountPointData -Comp filesrv2 -IncludeRootDrives | Sort Computer, Caption | ft -a Computer Label Caption FileSystem Size (GB) Free space Percent free -------- ----- ------- ---------- --------- ---------- ------------ filesrv2 C:\ NTFS 48.83 22.24 45.54 filesrv2 USER D:\ NTFS 1,945.59 157.36 8.09 filesrv2 User2 E:\ NTFS 549.99 137.36 24.97 filesrv2 User3 F:\ NTFS 711.99 85.11 11.95 filesrv2 User4 G:\ NTFS 711.99 115.16 16.17 filesrv2 H:\ 0.00 0.00
Code
### Copyright (c) 2012-2014, Svendsen Tech
### Author: Joakim Svendsen
### Get-MountPointData v1.2
# "Change history": 1.0 -> 1.1 = -Credential, -PromptForCredentials and -NoFormat (the latter allows math operations)
# --- " ---: 1.1 -> 1.2 = -IncludeDiskInfo to show physical disk index number (this was not so trivial).
# Convert from one device ID format to another.
function Get-DeviceIDFromMP {
param([Parameter(Mandatory=$true)][string] $VolumeString,
[Parameter(Mandatory=$true)][string] $Directory)
if ($VolumeString -imatch '^\s*Win32_Volume\.DeviceID="([^"]+)"\s*$') {
# Return it in the wanted format.
$Matches[1] -replace '\\{2}', '\'
}
else {
# Return a presumably unique hashtable key if there's no match.
"Unknown device ID for " + $Directory
}
}
# Thanks to Justin Rich (jrich523) for this C# snippet.
# https://jrich523.wordpress.com/2015/02/27/powershell-getting-the-disk-drive-from-a-volume-or-mount-point/
$STGetDiskClass = @"
using System;
using Microsoft.Win32.SafeHandles;
using System.IO;
using System.Runtime.InteropServices;
public class STGetDisk
{
private const uint IoctlVolumeGetVolumeDiskExtents = 0x560000;
[StructLayout(LayoutKind.Sequential)]
public struct DiskExtent
{
public int DiskNumber;
public Int64 StartingOffset;
public Int64 ExtentLength;
}
[StructLayout(LayoutKind.Sequential)]
public struct DiskExtents
{
public int numberOfExtents;
public DiskExtent first;
}
[DllImport("Kernel32.dll", SetLastError = true, CharSet = CharSet.Auto)]
private static extern SafeFileHandle CreateFile(
string lpFileName,
[MarshalAs(UnmanagedType.U4)] FileAccess dwDesiredAccess,
[MarshalAs(UnmanagedType.U4)] FileShare dwShareMode,
IntPtr lpSecurityAttributes,
[MarshalAs(UnmanagedType.U4)] FileMode dwCreationDisposition,
[MarshalAs(UnmanagedType.U4)] FileAttributes dwFlagsAndAttributes,
IntPtr hTemplateFile);
[DllImport("Kernel32.dll", SetLastError = false, CharSet = CharSet.Auto)]
private static extern bool DeviceIoControl(
SafeFileHandle hDevice,
uint IoControlCode,
[MarshalAs(UnmanagedType.AsAny)] [In] object InBuffer,
uint nInBufferSize,
ref DiskExtents OutBuffer,
int nOutBufferSize,
ref uint pBytesReturned,
IntPtr Overlapped
);
public static string GetPhysicalDriveString(string path)
{
//clean path up
path = path.TrimEnd('\\');
if (!path.StartsWith(@"\\.\"))
path = @"\\.\" + path;
SafeFileHandle shwnd = CreateFile(path, FileAccess.Read, FileShare.Read | FileShare.Write, IntPtr.Zero, FileMode.Open, 0, IntPtr.Zero);
if (shwnd.IsInvalid)
{
//Marshal.ThrowExceptionForHR(Marshal.GetLastWin32Error());
Exception e = Marshal.GetExceptionForHR(Marshal.GetLastWin32Error());
}
uint bytesReturned = new uint();
DiskExtents de1 = new DiskExtents();
bool result = DeviceIoControl(shwnd, IoctlVolumeGetVolumeDiskExtents, IntPtr.Zero, 0, ref de1, Marshal.SizeOf(de1), ref bytesReturned, IntPtr.Zero);
shwnd.Close();
if (result)
return @"\\.\PhysicalDrive" + de1.first.DiskNumber;
return null;
}
}
"@
try {
Add-Type -TypeDefinition $STGetDiskClass -ErrorAction Stop
}
catch {
if (-not $Error[0].Exception -like '*The type name * already exists*') {
Write-Warning -Message "Error adding [STGetDisk] class locally."
}
}
function Get-MountPointData {
[CmdletBinding(
DefaultParameterSetName='NoPrompt'
)]
param(
[Parameter(Mandatory=$true)][string[]] $ComputerName,
[Parameter(ParameterSetName='Prompt')][switch] $PromptForCredentials,
[Parameter(ParameterSetName='NoPrompt')][System.Management.Automation.Credential()] $Credential = [System.Management.Automation.PSCredential]::Empty,
[switch] $IncludeRootDrives,
[switch] $NoFormat,
[switch] $IncludeDiskInfo
)
foreach ($Computer in $ComputerName) {
$WmiHash = @{
ComputerName = $Computer
ErrorAction = 'Stop'
}
#if ($PromptForCredentials -and $Credential.Username) {
# Write-Warning "You specified both -PromptForCredentials and -Credential. Prompting overrides."
#}
if ($PSCmdlet.ParameterSetName -eq 'Prompt') {
$WmiHash.Credential = Get-Credential
}
elseif ($Credential.Username) {
$WmiHash.Credential = $Credential
}
try {
# Collect mount point device IDs and populate a hashtable with IDs as keys
$MountPointData = @{}
Get-WmiObject @WmiHash -Class Win32_MountPoint |
Where-Object {
if ($IncludeRootDrives) {
$true
}
else {
$_.Directory -NotMatch '^\s*Win32_Directory\.Name="[a-z]:\\{2}"\s*$'
}
} |
ForEach-Object {
$MountPointData.(Get-DeviceIDFromMP -VolumeString $_.Volume -Directory $_.Directory) = $_.Directory
}
$Volumes = @(Get-WmiObject @WmiHash -Class Win32_Volume | Where-Object {
if ($IncludeRootDrives) { $true } else { -not $_.DriveLetter }
} |
Select-Object Label, Caption, Capacity, FreeSpace, FileSystem, DeviceID, @{n='Computer';e={$Computer}} )
}
catch {
Write-Error "${Computer}: Terminating WMI error (skipping): $_"
continue
}
if (-not $Volumes.Count) {
Write-Error "${Computer}: No mount points found. Skipping."
continue
}
if ($PSBoundParameters['IncludeDiskInfo']) {
$DiskDriveWmiInfo = Get-WmiObject @WmiHash -Class Win32_DiskDrive
}
$Volumes | ForEach-Object {
if ($MountPointData.ContainsKey($_.DeviceID)) {
# Let's avoid dividing by zero, it's so disruptive.
if ($_.Capacity) {
$PercentFree = $_.FreeSpace*100/$_.Capacity
}
else {
$PercentFree = 0
}
$_ | Select-Object -Property DeviceID, Computer, Label, Caption, FileSystem, @{n='Size (GB)';e={$_.Capacity/1GB}},
@{n='Free space';e={$_.FreeSpace/1GB}}, @{n='Percent free';e={$PercentFree}}
}
} | Sort-Object -Property 'Percent free', @{Descending=$true;e={$_.'Size (GB)'}}, Label, Caption |
Select-Object -Property $(if ($NoFormat) {
@{n='ComputerName'; e={$_.Computer}},
@{n='Label'; e={$_.Label}},
@{n='Caption'; e={$_.Caption}},
@{n='FileSystem'; e={$_.FileSystem}},
@{n='Size (GB)'; e={$_.'Size (GB)'}},
@{n='Free space'; e={$_.'Free space'}},
@{n='Percent free'; e={$_.'Percent free'}},
$(if ($PSBoundParameters['IncludeDiskInfo']) {
@{n='Disk Index'; e={
try {
$ScriptBlock = {
param($GetDiskClass, $DriveString)
try {
Add-Type -TypeDefinition $GetDiskClass -ErrorAction Stop
}
catch {
#Write-Error -Message "${Computer}: Error creating class [STGetDisk]"
return "Error creating [STGetDisk] class: $_"
}
return [STGetDisk]::GetPhysicalDriveString($DriveString)
}
if ($Credential.Username) {
$PhysicalDisk = Invoke-Command -ComputerName $Computer -Credential $Credential -ScriptBlock $ScriptBlock -ArgumentList $STGetDiskClass, $(if ($_.Caption -imatch '\A[a-z]:\\\z') { $_.Caption } else { $_.DeviceID.TrimStart('\?') })
}
else {
$PhysicalDisk = Invoke-Command -ComputerName $Computer -ScriptBlock $ScriptBlock -ArgumentList $STGetDiskClass, $(if ($_.Caption -imatch '\A[a-z]:\\\z') { $_.Caption } else { $_.DeviceID.TrimStart('\?') })
}
if ($PhysicalDisk -like 'Error*') {
"Error: $PhysicalDisk"
}
else {
($DiskDriveWmiInfo | Where-Object { $PhysicalDisk } | Where-Object { $PhysicalDisk.Trim() -eq $_.Name } | Select-Object -ExpandProperty Index) -join '; '
}
}
catch {
"Error: $_"
}
} # end of disk index expression
} # end of if disk index hashtable
}) # end of if includediskinfo parameter subexpression and if
}
else {
@{n='ComputerName'; e={$_.Computer}},
@{n='Label'; e={$_.Label}},
@{n='Caption'; e={$_.Caption}},
@{n='FileSystem'; e={$_.FileSystem}},
@{n='Size (GB)'; e={$_.'Size (GB)'.ToString('N')}},
@{n='Free space'; e={$_.'Free space'.ToString('N')}},
@{n='Percent free'; e={$_.'Percent free'.ToString('N')}},
$(if ($PSBoundParameters['IncludeDiskInfo']) {
@{n='Disk Index'; e={
try {
$ScriptBlock = {
param($GetDiskClass, $DriveString)
try {
Add-Type -TypeDefinition $GetDiskClass -ErrorAction Stop
}
catch {
#Write-Error -Message "${Computer}: Error creating class [STGetDisk]"
return "Error creating [STGetDisk] class: $_"
}
return [STGetDisk]::GetPhysicalDriveString($DriveString)
}
if ($Credential.Username) {
$PhysicalDisk = Invoke-Command -ComputerName $Computer -Credential $Credential -ScriptBlock $ScriptBlock -ArgumentList $STGetDiskClass, $(if ($_.Caption -imatch '\A[a-z]:\\\z') { $_.Caption } else { $_.DeviceID.TrimStart('\?') })
}
else {
$PhysicalDisk = Invoke-Command -ComputerName $Computer -ScriptBlock $ScriptBlock -ArgumentList $STGetDiskClass, $(if ($_.Caption -imatch '\A[a-z]:\\\z') { $_.Caption } else { $_.DeviceID.TrimStart('\?') })
}
if ($PhysicalDisk -like 'Error*') {
"Error: $PhysicalDisk"
}
else {
($DiskDriveWmiInfo | Where-Object { $PhysicalDisk } | Where-Object { $PhysicalDisk.Trim() -eq $_.Name } | Select-Object -ExpandProperty Index) -join '; '
}
}
catch {
"Error: $_"
}
} # end of disk index expression
} # end of if disk index hashtable
}) # end of if includediskinfo parameter subexpression and if
}) # end of if $NoFormat
}
}
Powershell
Windows
Blog articles in alphabetical order
A
- A Look at the KLP AksjeNorden Index Mutual Fund
- A primitive hex version of the seq gnu utility, written in perl
- Accessing the Bing Search API v5 using PowerShell
- Accessing the Google Custom Search API using PowerShell
- Active directory password expiration notification
- Aksje-, fonds- og ETF-utbytterapportgenerator for Nordnet-transaksjonslogg
- Ascii art characters powershell script
- Automatically delete old IIS logs with PowerShell
C
- Calculate and enumerate subnets with PSipcalc
- Calculate the trend for financial products based on close rates
- Check for open TCP ports using PowerShell
- Check if an AD user exists with Get-ADUser
- Check when servers were last patched with Windows Update via COM or WSUS
- Compiling or packaging an executable from perl code on windows
- Convert between Windows and Unix epoch with Python and Perl
- Convert file encoding using linux and iconv
- Convert from most encodings to utf8 with powershell
- ConvertTo-Json for PowerShell version 2
- Create cryptographically secure and pseudorandom data with PowerShell
- Crypto is here - and it is not going away
- Crypto logo analysis ftw
D
G
- Get rid of Psychology in the Stock Markets
- Get Folder Size with PowerShell, Blazingly Fast
- Get Linux disk space report in PowerShell
- Get-Weather cmdlet for PowerShell, using the OpenWeatherMap API
- Get-wmiobject wrapper
- Getting computer information using powershell
- Getting computer models in a domain using Powershell
- Getting computer names from AD using Powershell
- Getting usernames from active directory with powershell
- Gnu seq on steroids with hex support and descending ranges
- Gullpriser hos Gullbanken mot spotprisen til gull
H
- Have PowerShell trigger an action when CPU or memory usage reaches certain values
- Historical view of the SnP 500 Index since 1927, when corona is rampant in mid-March 2020
- How Many Bitcoins (BTC) Are Lost
- How many people own 1 full BTC
- How to check perl module version
- How to list all AD computer object properties
- Hva det innebærer at særkravet for lån til sekundærbolig bortfaller
I
L
M
P
- Parse openssl certificate date output into .NET DateTime objects
- Parse PsLoggedOn.exe Output with PowerShell
- Parse schtasks.exe Output with PowerShell
- Perl on windows
- Port scan subnets with PSnmap for PowerShell
- PowerShell Relative Strength Index (RSI) Calculator
- PowerShell .NET regex to validate IPv6 address (RFC-compliant)
- PowerShell benchmarking module built around Measure-Command
- Powershell change the wmi timeout value
- PowerShell check if file exists
- Powershell check if folder exists
- PowerShell Cmdlet for Splitting an Array
- PowerShell Executables File System Locations
- PowerShell foreach loops and ForEach-Object
- PowerShell Get-MountPointData Cmdlet
- PowerShell Java Auto-Update Script
- Powershell multi-line comments
- Powershell prompt for password convert securestring to plain text
- Powershell psexec wrapper
- PowerShell regex to accurately match IPv4 address (0-255 only)
- Powershell regular expressions
- Powershell split operator
- Powershell vs perl at text processing
- PS2CMD - embed PowerShell code in a batch file
R
- Recursively Remove Empty Folders, using PowerShell
- Remote control mom via PowerShell and TeamViewer
- Remove empty elements from an array in PowerShell
- Remove first or last n characters from a string in PowerShell
- Rename unix utility - windows port
- Renaming files using PowerShell
- Running perl one-liners and scripts from powershell
S
- Sammenlign gullpriser og sølvpriser hos norske forhandlere av edelmetall
- Self-contained batch file with perl code
- Silver - The Underrated Investment
- Simple Morningstar Fund Report Script
- Sølv - den undervurderte investeringen
- Sort a list of computers by domain first and then name, using PowerShell
- Sort strings with numbers more humanely in PowerShell
- Sorting in ascending and descending order simultaneously in PowerShell
- Spar en slant med en optimalisert kredittkortportefølje
- Spre finansiell risiko på en skattesmart måte med flere Aksjesparekontoer
- SSH from PowerShell using the SSH.NET library
- SSH-Sessions Add-on with SCP SFTP Support
- Static Mutual Fund Portfolio the Last 2 Years Up 43 Percent
- STOXR - Currency Conversion Software - Open Exchange Rates API