Cleaning .NET project folders.
Recently, I've been using Claude.ai, an artificial intelligence trained to help in code development.
Today, during a conversation, we came up with the following PowerShell script that cleans a tree of bin and obj folders if they are associated with a .NET project (.csproj
, .vbproj
, .fsproj
).
Here's the script.
[CmdletBinding(SupportsShouldProcess=$true)]
param(
[Parameter(Position=0)]
[string]$RootPath = ".",
[Parameter()]
[switch]$Force
)
function Write-ColorOutput($ForegroundColor) {
$fc = $host.UI.RawUI.ForegroundColor
$host.UI.RawUI.ForegroundColor = $ForegroundColor
if ($args) {
Write-Output $args
}
$host.UI.RawUI.ForegroundColor = $fc
}
function Test-IsDotNetProject {
param (
[string]$FolderPath
)
$projectFiles = Get-ChildItem -Path $FolderPath -File -Filter "*.*proj" |
Where-Object { $_.Name -match '\.(cs|fs|vb|sql|vcx)proj$' }
return $projectFiles.Count -gt 0
}
function Get-NuGetPackagesFolder {
$packagesFolders = @()
# Find all 'packages' folders in the solution directories
$solutionPackages = Get-ChildItem -Path $RootPath -Directory -Recurse -Filter "packages" |
Where-Object { $_.FullName -notlike "*\node_modules\*" }
if ($solutionPackages) {
$packagesFolders += $solutionPackages
}
# Add user-level .nuget folder if it exists
if (Test-Path (Join-Path $env:USERPROFILE ".nuget\packages")) {
$packagesFolders += Get-Item (Join-Path $env:USERPROFILE ".nuget\packages")
}
return $packagesFolders
}
function Get-DevFolders {
param (
[string]$Path
)
$folders = @()
# Find all .vs and .git folders recursively, including hidden ones
$devFolders = Get-ChildItem -Path $Path -Directory -Force -Recurse |
Where-Object { ($_.Name -like ".vs*" -or $_.Name -eq ".git") -and $_.Attributes -match "Hidden" }
if ($devFolders) {
$folders += $devFolders
}
return $folders
}
function Remove-BuildFolders {
param (
[string]$Path,
[bool]$ForceDelete
)
$absolutePath = Resolve-Path $Path
Write-Output "Scanning directory : $absolutePath"
try {
$foldersToDelete = @()
# Get bin/obj folders from .NET projects
$allBinObjFolders = Get-ChildItem -Path $Path -Include @("bin", "obj") -Directory -Recurse -Force -ErrorAction Stop
foreach ($folder in $allBinObjFolders) {
$parentPath = Split-Path -Parent $folder.FullName
if (Test-IsDotNetProject -FolderPath $parentPath) {
$foldersToDelete += $folder
}
else {
Write-ColorOutput Yellow "Skipping non-.NET folder : $($folder.FullName)"
}
}
# Add NuGet packages folder if found
$packagesFolders = Get-NuGetPackagesFolder
if ($packagesFolders) {
Write-ColorOutput Magenta "Found NuGet packages folders : "
foreach ($folder in $packagesFolders) {
Write-ColorOutput Magenta " $($folder.FullName)"
$foldersToDelete += $folder
}
}
# Add .vs and .git folders
$devFolders = Get-DevFolders -Path $Path
if ($devFolders) {
Write-ColorOutput Magenta "Found development folders : "
foreach ($folder in $devFolders) {
Write-ColorOutput Magenta " $($folder.FullName)"
$foldersToDelete += $folder
}
}
if ($foldersToDelete.Count -eq 0) {
Write-ColorOutput Yellow "No folders found to clean in : $Path"
return
}
Write-Output "`nFound $($foldersToDelete.Count) folders to clean :"
foreach ($folder in $foldersToDelete) {
$folderType = switch ($folder.Name) {
{ $_ -in @("bin", "obj") } { ".NET build folder" }
{ $_ -eq "packages" } { "NuGet packages folder" }
{ $_ -like ".vs*" } { "Visual Studio folder" }
{ $_ -eq ".git" } { "Git repository folder" }
default { "Development folder" }
}
Write-ColorOutput Cyan "Found $folderType : $($folder.FullName)"
if ($ForceDelete) {
if ($PSCmdlet.ShouldProcess($folder.FullName, "Delete folder")) {
try {
Remove-Item -Path $folder.FullName -Recurse -Force -ErrorAction Stop
Write-ColorOutput Green "Successfully deleted : $($folder.FullName)"
}
catch {
Write-ColorOutput Red "Failed to delete : $($folder.FullName)"
Write-ColorOutput Red "Error : $($_.Exception.Message)"
}
}
}
}
if (-not $ForceDelete) {
Write-ColorOutput Yellow "`nTo delete these folders, run the script with -Force parameter"
}
}
catch {
Write-ColorOutput Red "Error scanning directory : $($_.Exception.Message)"
exit 1
}
}
# Script execution starts here
$startTime = Get-Date
if (-not (Test-Path $RootPath)) {
Write-ColorOutput Red "Error : Path '$RootPath' does not exist!"
exit 1
}
Write-Output "Starting cleanup of development folders..."
Write-Output "Root path : $RootPath"
if ($Force) {
Write-ColorOutput Red "WARNING : Force parameter specified - folders will be deleted!"
}
Remove-BuildFolders -Path $RootPath -ForceDelete $Force
$endTime = Get-Date
$duration = $endTime - $startTime
Write-Output "`nOperation completed in $($duration.TotalSeconds) seconds"
Comments
Post a Comment