When working in Visual Studio all sorts of temporary files get created in your workspace. From user specific
*.suo
, *.user
and *.docstates
files, to the build results in the bin/
and obj/
directories up to extension specific files for e.g. ReSharper. Just to name a few.
To get the situation under control again two things are necessary:
- A good
.gitignore
file (or the equivalent for the source control of your choice) - A script to wipe all temporary and unwanted files for a truly clean repository
Running Visual Studio's Clean Solution command doesn't do the trick. It's not configurable, only removes build artefacts and isn't even reliable in doing that always for good.
So, if you run into an odd issue and just want to compile a truly clean solution from scratch, Clean Solution just isn't an option.
Clean script
One of my all-time lifesaver scripts that I use quite frequently is this little PowerShell gem:
# Define files and directories to delete
$include = @("*.suo","*.user","*.cache","*.docstates","bin","obj","build")
# Define files and directories to exclude
$exclude = @()
$items = Get-ChildItem . -recurse -force -include $include -exclude $exclude
if ($items) {
foreach ($item in $items) {
Remove-Item $item.FullName -Force -Recurse -ErrorAction SilentlyContinue
Write-Host "Deleted" $item.FullName
}
}
Write-Host "Press any key to continue . . ."
$x = $host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown")
Placed in the root of your repository as
clean.ps1
you can execute it whenever you feel dirty (right mouse click and Run with PowerShell). Note that in order to run the script you might need to change your PowerShell script execution policy.
Let's have a quick look of what it does, shall we?
The variable
$include
holds an array of path elements or patterns to delete, such as *.suo
. Wildcards are permitted.
The variable
$exclude
holds an array of path elements or patterns to omit within the defined scope for deletion. It's empty in the example above but it could look like this:$exclude = @("ConnectionStrings.config.user")
The Cmdlet
Get-ChildItem
gets all the items and child items for the specified locations. Note that we're passing the $include
and $exclude
arrays as parameters.Get-ChildItem . -recurse -force -include $include -exclude $exclude
Next, it loops over all of these items and deletes them one by one using
Remove-Item
.Remove-Item $item.FullName -Force -Recurse -ErrorAction SilentlyContinue
The last line is not necessary and really just a preference of mine - how I usually execute it - so that the script pauses until you press any key on the keyboard.
$x = $host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown")
You can find the code on GitHub.