#PSTip Get the size of a file on disk

Note: This tip requires PowerShell 2.0 or above.

In an earlier post, I wrote about compressing / uncompressing files using WMI. Towards the end of that article, the image showed the difference in file size on disk before and after the compression. So, how can we retrieve that value using PowerShell? Let us look at Get-Item and WMI to see if we can retrieve the file size on disk.

compress

In both cases above, we see that the file size is not the actual compressed size on the disk.

So, to retrieve the file size on disk, we need to use a low-level Win32 function called GetCompressedFileSize. There are at least two ways of using this in PowerShell – P/Invoke and .NET Interop Services. Since PowerShell 2.0 and above include the Add-Type cmdlet, let us see how we can use that and .NET interop services to achieve what we want.

add-type -type  @'
using System;
using System.Runtime.InteropServices;
using System.ComponentModel;

namespace Disk
{
    public class SizeInfo
    {
        [DllImport("kernel32.dll", SetLastError=true, EntryPoint="GetCompressedFileSize")]
        static extern uint GetCompressedFileSizeAPI(string lpFileName, out uint lpFileSizeHigh);

        public static ulong GetCompressedFlieSize(string FileName,bool SizeInMB)
        {
            uint HighOrder;
            uint LowOrder;
            LowOrder = GetCompressedFileSizeAPI(FileName, out HighOrder);
            int error = Marshal.GetLastWin32Error();
            if (HighOrder == 0 && LowOrder == 0xFFFFFFFF && error != 0)
                throw new Win32Exception(error);
            else
                if (SizeInMB)
                    return ((((ulong)HighOrder << 32) + LowOrder)/1024)/1024;
                else
                    return ((ulong)HighOrder << 32) + LowOrder;
        }
    }
}
'@

The above snippet will create the Disk.SizeInfo namespace in the current PowerShell session. We can use this namespace to retrieve the file size on disk.

[Disk.SizeInfo]::GetCompressedFlieSize( "C:\scripts\test.vhd",$false)
[Disk.SizeInfo]::GetCompressedFlieSize( "C:\scripts\test.vhd",$true)

If the second parameter is set to $true, the value of the file size will be returned in megabytes.

About the author: Ravikanth C

Ravikanth is the founder and editor of the PowerShell Magazine. He is also a PowerShell MVP who works at Dell Inc. He blogs at http://www.ravichaganti.com/blog and you can follow him on Twitter @ravikanth.

Related Posts

%d bloggers like this: