Need Accurate result Size on Disk using Powershell Script, When Bytes are Null

Ashish Jaya Karkera 0 Reputation points
2025-07-16T11:32:48.76+00:00

Problem Statement:

Not able to get accurate value for Size on Disk for App-V folder , I tried using below PS Command based on the length

Get-ChildItem -Path $path -Recurse -File -ErrorAction SilentlyContinue | ForEach-Object {

try{

$size = $_.Length

if($null -ne $size -and $size -gt 0)

{

$cl = [math]::Ceiling($size / $cSize)

$SizeOnDisk = $cl * $cSize

$totalSizeOnDisk += $SizeOnDisk

$filecount++

}

Also checked on null and size condition to filter out the empty and 0 check , Still having some problem on getting the accurate value.

PS code:

function Get-FolderSizEOnDisk {

param (

[Parameter(Mandatory = $true)]

[string]$path

)

$ap = (Resolve-Path $path).Path

$ite = Get-Item $ap

$volume = Get-Volume $ite.PSDrive.Name

$cSize = $volume.AllocationUnitSize

$defaultCS = 4096

$totalSizeOnDisk = 0

$filecount =0

$defaultcount = 0

$failedcount = 0

Get-ChildItem -Path $path -Recurse -File -ErrorAction SilentlyContinue | ForEach-Object {

try{

$size = $_.Length

if($null -ne $size -and $size -gt 0)

{

$cl = [math]::Ceiling($size / $cSize)

$SizeOnDisk = $cl * $cSize

$totalSizeOnDisk += $SizeOnDisk

$filecount++

}

else {

$totalSizeOnDisk += $defaultCS

$defaultcount++

}

}

catch {

$failedcount++

}

}

$folderCount = (Get-ChildItem -Path $path -Recurse -Directory -ErrorAction SilentlyContinue).Count

[PSCustomObject]@{

Folder =$ap

Files = $filecount

defaultLength_Zero = $defaultcount

FailedFiles = $failedcount

Folders = $folderCount

SizeOnDisk = $totalSizeOnDisk

SizeOnDiskKB =[math]::Round($totalSizeOnDisk / 1KB, 2)

SizeOnDiskGB =[math]::Round($totalSizeOnDisk / 1GB, 2)

SizeOnDiskMB =[math]::Round($totalSizeOnDisk / 1MB, 2)

}

}

Please let me know if any other solution without any Admin access. And also let me know if anything i am missing on above PS code.

Waiting for your reply.

Thanks! Ashish

Windows for business | Windows Server | User experience | PowerShell
{count} votes

1 answer

Sort by: Most helpful
  1. MotoX80 36,536 Reputation points
    2025-07-16T17:48:16.5733333+00:00

    I don't know what files you have in your App-V folder, so I created a few files in a test folder to examine.

    I found 2 issues. The first is that really small files don't occupy any space. Their data is stored in the MFT. Explorer properties show 0 bytes for size on disk.

    User's image

    The second issue is for files that have been compressed. You can set the explorer options to have them show in blue.

    User's image

    I found a StackOverflow article that demonstrated how to call GetCompressedFileSizeW. That works for compressed files, but the only way that I found to find the MFT resident files was to call fsutil and look for the number of extents.

    This was tested on Win11.

    # Source: https://stackoverflow.com/questions/22507523/getting-size-on-disk-for-small-files-in-powershell
    add-type -type  @'
    using System;
    using System.Runtime.InteropServices;
    using System.ComponentModel;
    using System.IO;
    namespace Win32Functions
    {
      public class ExtendedFileInfo
      {    
        public static long GetFileSizeOnDisk(string file)
        {
            FileInfo info = new FileInfo(file);
            uint dummy, sectorsPerCluster, bytesPerSector;
            int result = GetDiskFreeSpaceW(info.Directory.Root.FullName, out sectorsPerCluster, out bytesPerSector, out dummy, out dummy);
            if (result == 0) throw new Win32Exception();
            uint clusterSize = sectorsPerCluster * bytesPerSector;
            uint hosize;
            uint losize = GetCompressedFileSizeW(file, out hosize);
            long size;
            size = (long)hosize << 32 | losize;
            return ((size + clusterSize - 1) / clusterSize) * clusterSize;
        }
        [DllImport("kernel32.dll")]
        static extern uint GetCompressedFileSizeW([In, MarshalAs(UnmanagedType.LPWStr)] string lpFileName,
           [Out, MarshalAs(UnmanagedType.U4)] out uint lpFileSizeHigh);
        [DllImport("kernel32.dll", SetLastError = true, PreserveSig = true)]
        static extern int GetDiskFreeSpaceW([In, MarshalAs(UnmanagedType.LPWStr)] string lpRootPathName,
           out uint lpSectorsPerCluster, out uint lpBytesPerSector, out uint lpNumberOfFreeClusters,
           out uint lpTotalNumberOfClusters);  
      }
    }
    '@
    function Get-FolderSizEOnDisk {
    param (
    [Parameter(Mandatory = $true)]
    [string]$path
    )
        $ap = (Resolve-Path $path).Path
        $ite = Get-Item $ap
        $volume = Get-Volume $ite.PSDrive.Name
        $cSize = $volume.AllocationUnitSize
        $defaultCS = 4096
        $totalSizeOnDisk = 0
        $filecount =0
        $defaultcount = 0
        $failedcount = 0
        Get-ChildItem -Path $path -Recurse -File -ErrorAction SilentlyContinue | ForEach-Object {
        
        try {
            $size = $_.Length
            if($null -ne $size -and $size -gt 0)
            {
                # $cl = [math]::Ceiling($size / $cSize)
                # $SizeOnDisk = $cl * $cSize
                $SizeOnDisk = [Win32Functions.ExtendedFileInfo]::GetFileSizeOnDisk( $_.FullName)
     
                if ($size -lt 1024) {                    # really small files can be stored in the MFT 
                    $fsu = fsutil file queryExtents "$($_.FullName)"
                    if ($fsu.contains("No extents")) {
                        $SizeOnDisk = 0                  # data stored in MFT 
                    }
                }  
                $totalSizeOnDisk += $SizeOnDisk
                $filecount++
                "{0} - {1} - {2}" -f $size, $SizeOnDisk, $_.Name
            }
        else {
            $totalSizeOnDisk += $defaultCS
            $defaultcount++
            }
        } catch {
            $failedcount++
        }
    }
    $folderCount = (Get-ChildItem -Path $path -Recurse -Directory -ErrorAction SilentlyContinue).Count
    [PSCustomObject]@{
        Folder =$ap
        Files = $filecount
        defaultLength_Zero = $defaultcount
        FailedFiles = $failedcount
        Folders = $folderCount
        SizeOnDisk = $totalSizeOnDisk
        SizeOnDiskKB =[math]::Round($totalSizeOnDisk / 1KB, 2)
        SizeOnDiskGB =[math]::Round($totalSizeOnDisk / 1GB, 2)
        SizeOnDiskMB =[math]::Round($totalSizeOnDisk / 1MB, 2)
        }
    }
    Get-FolderSizEOnDisk "C:\Temp\store"
    
    1 person found this answer helpful.
    0 comments No comments

Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.