Drag and Drop PowerShell
Today I'm going back to my old school DOS batch file days and bring back an automation technique to the PowerShell world. Let me show you how to bring drag and drop automation to your PowerShell scripts. This technique doesn't necessarily scale very well, but it is an interesting way to pass data to your code. After reading this and testing it out, you'll have to think about where it makes sense for you.
Dropping to a File
Back in the day you could create a simple batch file like this:
@echo off
REM DropIt.bat
echo You dropped %1
pause
The only thing this batch file does is echo the argument, %1.
C:\> c:\work\drop\dropit.bat "Testing 123"
You dropped "Testing 123"
Press any key to continue . . .
I've copied this batch file to C:\Work\Drop.

From here, I can drag and drop an item from the file explorer on to the batch file. I'll drag my Downloads folder and drop it on the DropIt.bat file.

You can see the prompt that I'm going to open the dropped item with DropIt.bat. As soon as I release my mouse, a DOS prompt will open and echo the dropped item.

This suggests that I could pass the path of a file or folder to a script by dragging and dropping it on to the script file. However, there is a catch for our PowerShell needs. For security reasons, you can't arbitrarily invoke a PowerShell script. Which means you can't simply replace the DOS batch file with a PowerShell script. Instead, you'll need to wrap the PowerShell script in a batch file.
I'm going to test with this function.
#requires -version 7.5
#Get-FileExtensionInfo.ps1
using namespace System.Collections.generic
Function Get-FileExtensionInfo {
    [cmdletbinding()]
    [alias("gfei")]
    [OutputType("FileExtensionInfo")]
    Param(
        [Parameter(
            Position = 0,
            ValueFromPipeline,
            HelpMessage = "Specify the root directory path to search"
        )]
        [ValidateNotNullOrEmpty()]
        [ValidateScript( { Test-Path $_ })]
        [string]$Path = ".",
        [Parameter(HelpMessage = "Recurse through all folders.")]
        [switch]$Recurse,
        [Parameter(HelpMessage = "Include files in hidden folders")]
        [switch]$Hidden,
        [Parameter(HelpMessage = "Add the corresponding collection of files")]
        [Switch]$IncludeFiles
    )
    Begin {
        $ver = "1.1.0"
        Write-Verbose "[$((Get-Date).TimeOfDay) BEGIN  ] Starting $($MyInvocation.MyCommand) v$ver"
        Write-Verbose "[$((Get-Date).TimeOfDay) BEGIN  ] Running PowerShell version $($PSVersionTable.PSVersion)"
        Write-Verbose "[$((Get-Date).TimeOfDay) BEGIN  ] Using PowerShell Host $($Host.Name)"
        #capture the current date and time for the audit date
        $report = Get-Date
        $enumOpt = [System.IO.EnumerationOptions]::new()
        if ($Recurse) {
            Write-Verbose "[$((Get-Date).TimeOfDay) BEGIN  ] Getting files recursively"
        }
        $enumOpt.RecurseSubdirectories = $Recurse
        if ($Hidden) {
            Write-Verbose "[$((Get-Date).TimeOfDay) BEGIN  ] Including hidden files"
            $enumOpt.AttributesToSkip -= 2
        }
        #initialize a list to hold the results
        $list = [list[object]]::new()
    } #begin
    Process {
        #convert the path to a file system path
        $cPath = Convert-Path -Path $Path
        Write-Verbose "[$((Get-Date).TimeOfDay) PROCESS] Processing $cPath"
        $dir = Get-Item -Path $cPath
        $files = $dir.GetFiles('*', $enumOpt)
        Write-Verbose "[$((Get-Date).TimeOfDay) PROCESS] Found $($files.count) files"
        $group = $files | Group-Object -Property extension
        #Group and measure
        foreach ($item in $group) {
            Write-Verbose "[$((Get-Date).TimeOfDay) PROCESS] Measuring $($item.count) $($item.name) files"
            $measure = $item.Group | Measure-Object -Property length -Minimum -Maximum -Average -Sum
            #create a custom object
            $out = [PSCustomObject]@{
                PSTypeName   = "FileExtensionInfo"
                Path         = $cPath
                Extension    = $item.Name.Replace('.', '')
                Count        = $item.Count
                TotalSize    = $measure.Sum
                SmallestSize = $measure.Minimum
                LargestSize  = $measure.Maximum
                AverageSize  = $measure.Average
                Computername = [System.Environment]::MachineName
                ReportDate   = $report
                Files        = $IncludeFiles ? $item.group : $null
                IsLargest    = $False
            }
            $list.Add($out)
        }
    } #process
    End {
        #mark the extension with the largest total size
        ($list | Sort-Object -Property TotalSize,Count)[-1].IsLargest = $true
        #write the results to the pipeline
        $list
        Write-Verbose "[$((Get-Date).TimeOfDay) END    ] Ending $($MyInvocation.MyCommand)"
    } #end
}
Update-TypeData -TypeName FileExtensionInfo -MemberType AliasProperty -MemberName Total -Value TotalSize -Force
The function breaks down file extensions in a given folder and provides a summary.
PS C:\> Get-FileExtensionInfo d:\temp -Recurse
   Path: D:\temp [PROSPERO]
Extension Count TotalSize Smallest Average Largest
--------- ----- --------- -------- ------- -------
html          1       836      836     836     836
png           1    154085   154085  154085  154085
txt           2   2069090      290 1034545 2068800
The function also includes a custom format file which will highlight the extension with the largest total size.
