cmdlets/Get-FolderSizeFast.psm1

# Add C# code inline to PowerShell
Add-Type -TypeDefinition @"
using System;
using System.IO;
 
public static class FastFolderSize
{
    public static long GetFolderSize(string folderPath)
    {
        if (!Directory.Exists(folderPath))
            throw new DirectoryNotFoundException("Directory not found: " + folderPath);
         
        return GetDirectorySize(new DirectoryInfo(folderPath));
    }
     
    public static long GetFolderSizeWithSubfolders(string folderPath, out int fileCount, out int folderCount)
    {
        fileCount = 0;
        folderCount = 0;
         
        if (!Directory.Exists(folderPath))
            throw new DirectoryNotFoundException("Directory not found: " + folderPath);
         
        return GetDirectorySizeDetailed(new DirectoryInfo(folderPath), ref fileCount, ref folderCount);
    }
     
    private static long GetDirectorySize(DirectoryInfo directory)
    {
        long size = 0;
         
        try
        {
            // Add file sizes
            FileInfo[] files = directory.GetFiles();
            foreach (FileInfo file in files)
            {
                try
                {
                    size += file.Length;
                }
                catch
                {
                    // Skip files we can't access
                }
            }
             
            // Add subdirectory sizes
            DirectoryInfo[] subdirectories = directory.GetDirectories();
            foreach (DirectoryInfo subdirectory in subdirectories)
            {
                try
                {
                    size += GetDirectorySize(subdirectory);
                }
                catch
                {
                    // Skip directories we can't access
                }
            }
        }
        catch
        {
            // Skip if we can't enumerate the directory
        }
         
        return size;
    }
     
    private static long GetDirectorySizeDetailed(DirectoryInfo directory, ref int fileCount, ref int folderCount)
    {
        long size = 0;
         
        try
        {
            folderCount++;
             
            // Add file sizes
            FileInfo[] files = directory.GetFiles();
            foreach (FileInfo file in files)
            {
                try
                {
                    size += file.Length;
                    fileCount++;
                }
                catch
                {
                    // Skip files we can't access
                }
            }
             
            // Add subdirectory sizes
            DirectoryInfo[] subdirectories = directory.GetDirectories();
            foreach (DirectoryInfo subdirectory in subdirectories)
            {
                try
                {
                    size += GetDirectorySizeDetailed(subdirectory, ref fileCount, ref folderCount);
                }
                catch
                {
                    // Skip directories we can't access
                }
            }
        }
        catch
        {
            // Skip if we can't enumerate the directory
        }
         
        return size;
    }
}
"@


# PowerShell wrapper functions
function Get-FolderSizeFast {
    [CmdletBinding()]
    param(
        [Parameter(Mandatory = $true, ValueFromPipeline = $true)]
        [string]$Path,
        
        [switch]$Detailed
    )
    
    process {
        try {
            $resolvedPath = Resolve-Path $Path -ErrorAction Stop
            
            if ($Detailed) {
                $fileCount = 0
                $folderCount = 0
                $size = [FastFolderSize]::GetFolderSizeWithSubfolders($resolvedPath.Path, [ref]$fileCount, [ref]$folderCount)
                
                [PSCustomObject]@{
                    Path        = $resolvedPath.Path
                    SizeBytes   = $size
                    SizeMB      = [Math]::Round($size / 1MB, 2)
                    SizeGB      = [Math]::Round($size / 1GB, 3)
                    FileCount   = $fileCount
                    FolderCount = $folderCount - 1  # Subtract 1 to exclude root folder
                }
            }
            else {
                $size = [FastFolderSize]::GetFolderSize($resolvedPath.Path)
                
                [PSCustomObject]@{
                    Path      = $resolvedPath.Path
                    SizeBytes = $size
                    SizeMB    = [Math]::Round($size / 1MB, 2)
                    SizeGB    = [Math]::Round($size / 1GB, 3)
                }
            }
        }
        catch {
            Write-Error "Error calculating folder size for '$Path': $($_.Exception.Message)"
        }
    }
}

# Usage examples:
# Get-FolderSizeFast -Path "C:\Windows"
# Get-FolderSizeFast -Path "C:\Users" -Detailed
# "C:\Program Files", "C:\Windows" | Get-FolderSizeFast