Extension/Tool to perform cleanup on project - visual-studio

I have been recently using Visual Studio 2017 and I'd like to have an external tool/extension/setting which deletes everything besides .sln, .vcxproj and sources. I have already tried CLean Project and Clean Solution extension but neither of those removes Debug folder. I have read something about PowerShell scripts but I have no idea how to use them and I don't want to run unknown code on my console.
PS: I know that VS has the cleanup function, but it only deletes executables. I also read something about modifying the project properties but that would be really unpleasant for many projects.
PSS: I am a student and I have many project directories. All I want is to have a neat way to store them.
PSSS: I have already configured my .gitignore file and I am using git. IS there a way to use it to perform cleanup?

You're using Git. You can simply reset your workspace to the last commit, removing all unversioned and ignored files. First make sure you have no pending changes, then perform a clean:
git clean -xdfn
-x: ignore the ignores (removes bin, obj, *.dll, ...)
-d: remove directories in addition to files
-f: force Git to actually do the job
-n: perform a dry run, which will list the files that will be removed.
Remove the n from the arguments to actually clean the workspace.
See also How do I clear my local working directory in git?.

Here a script I'm using that works well for me.
# PowerShell script that recursively deletes all 'bin' and 'obj' (or any other specified) folders inside current folder
$CurrentPath = (Get-Location -PSProvider FileSystem).ProviderPath
# recursively get all folders matching given includes, except ignored folders
$FoldersToRemove = Get-ChildItem .\ -include bin,obj -Recurse | where {$_ -notmatch '_tools' -and $_ -notmatch '_build'} | foreach {$_.fullname}
# recursively get all folders matching given includes
$AllFolders = Get-ChildItem .\ -include bin,obj -Recurse | foreach {$_.fullname}
# subtract arrays to calculate ignored ones
$IgnoredFolders = $AllFolders | where {$FoldersToRemove -notcontains $_}
# remove folders and print to output
if($FoldersToRemove -ne $null)
{
Write-Host
foreach ($item in $FoldersToRemove)
{
remove-item $item -Force -Recurse;
Write-Host "Removed: ." -nonewline;
Write-Host $item.replace($CurrentPath, "");
}
}
# print ignored folders to output
if($IgnoredFolders -ne $null)
{
Write-Host
foreach ($item in $IgnoredFolders)
{
Write-Host "Ignored: ." -nonewline;
Write-Host $item.replace($CurrentPath, "");
}
Write-Host
Write-Host $IgnoredFolders.count "folders ignored" -foregroundcolor yellow
}
# print summary of the operation
Write-Host
if($FoldersToRemove -ne $null)
{
Write-Host $FoldersToRemove.count "folders removed" -foregroundcolor green
}
else { Write-Host "No folders to remove" -foregroundcolor green }
Write-Host
# prevent closing the window immediately
$dummy = Read-Host "Completed, press enter to continue."
Copy and paste in a new file in the same directory of your .sln file.
I call it "CleanAll.ps1" but you can call it as you prefer.
The easiest way to run it?
Right-Click on the file > Run with powershell
It recursively delete bin and obj files of all sub-folders starting from the current path. You can of course personalize and add "debug" or any other folder once you get more familiar with the script.

Related

Windows Compare filenames and delete 1 version of the filename

I have several hundred folders where I will have multiple files called filename.ext but also another file called filename.ext.url
I need a way of checking if filename.pdf.url exists does filename.ext exist. If they both exist delete filename.ext.url
I can't just do a search and delete all *.url files as they will be needed if the normal file does not exist
I then need to repeat that in all subdirectories of a specific directory.
I don't mind its its a batch script, powershell script that does it or any other way really. I'm just stumped on how to do what I want.
Currently I'm doing it folder by folder, manually comparing file names, file size and file icon.
foreach ($file in ls -Recurse c:\files\*.url) {
if (ls -ErrorAction Ignore "$($file.PSParentPath)\$($file.basename)") {
remove-item $file.fullname -whatif
}
}
remove whatif when ready to delete.
the basename removes the extension, so if they are all .ext.url then it will check if that file exists. It also removes the path, so we pull that as well.
an alternative way (that more matches what you're explaining) is something like
foreach ($file in ls -Recurse "c:\files\*.url") {
### replacing '.url$' means .url at the end of the line in Regex
if (ls -ErrorAction Ignore ($file.FullName -replace '\.url$')) {
remove-item $file.fullname -whatif
}
}
for /r "startingdirectoryname" %b in (*.url) do if exist "%~dpnb" ECHO del "%b"
This is expected to be executed directly from the prompt. If the requirement is as a batch line, each % needs to be doubled (ie. %%).
This also assumes that the whatever.ext file is to be in the same directory as the whatever.ext.url file.
Note that the filenames that are to be deleted will merely be echoed to the console. To actually delete the files, remove the echo keyword.
Test against a test directory first!
[untested]
To check for "filename.ext", check for "filename.ext.", they are the same file.
In CMD.EXE, you can do "IF EXIST "filename.ext." CALL :DoIt

Check if multiple directories exist in Powershell and then execute command

I am using this command to remove multiple files in two different directories:
Remove-Item -path c:\tmp\folder1\*, c:\tmp\folder1\* -Force -Recurse
both folders contain some zip files and sub folders which i want te remove
I need to check if those folders (folder1 and folder2) exist and not empty before executing this command. Can't figure it out :(
Any help would be appreciated.
If you want to check multiple conditions with an if then -and the results:
if ((Test-Path 'C:\tmp\folder1\*') -and
(Test-Path 'C:\tmp\folder2\*') ){
Remove-Item -path c:\tmp\folder1\*, c:\tmp\folder1\* -Force -Recurse
} else {
"not all conditions met."
}
An explicit Test-Path for the folders isn't neccessary as it is implied with items in the folders.
I suggest using the command "test-path", and then using a | (a pipe) to output a true or false value for proceeding to executing the command that you are using to delete a directory.

List files that are in the TFS repository but not in the Visual Studio solution

We have big solution(300+ projets), which is evolving since a long time(7 years), and over the time, there has been a lot of refactoring(projects removed, moved, ...). We did notice that sometimes when some projects are deleted from the solution, they are not deleted from the solution, and also that we have some leftover files.
We would like to find all those kind of files in order to delete most of them(not all).
Is there a way to list all those files?
(We have Visual Studio 2015 enterprise)
Check this PowerShell script from this case, which should do what you are looking for. It parses the project file to get the included code files. Then it compares that list to the actual files on disk. The remaining files are your unused/obsolete files.
The script can either delete the unused files from disk or pend them as deletes in TFS.
<#
.SYNOPSIS
Find and process files in a project folder that are not included in the project.
.DESCRIPTION
Find and process files in a project folder that are not included in the project.
Options to delete the files or to add them as pending deletes for TFS. Use TF.exe to pend the deletes and start the check-in process for the files.
This is necessary when trying to delete files that are not currently included in a Visual Studio project.
.PARAMETER Project
The path/name for the project file.
.PARAMETER VsVersion
The Visual Studio version (10, 11, 12). Used to locate the tf.exe file.
.PARAMETER DeleteFromDisk
Just delete the files from disk. No interaction with any source control.
.PARAMETER TfsCheckin
After pending the deletes, open the check-in dialog.
#>
[CmdletBinding()]
param(
[Parameter(Position=0, Mandatory=$true)]
[string]$Project,
[Parameter(Mandatory=$false)]
[ValidateRange(10,12)]
[int] $VsVersion = 12,
[switch]$DeleteFromDisk,
[switch]$TfsCheckin
)
$ErrorActionPreference = "Stop"
$tfPath = "${env:ProgramFiles(X86)}\Microsoft Visual Studio $VsVersion.0\Common7\IDE\TF.exe"
$projectPath = Split-Path $project
if($Project.EndsWith("csproj"))
{
$fileType = "*.cs"
}
else
{
$fileType = "*.vb"
}
$fileType
$projectFiles = Select-String -Path $project -Pattern '<compile' | % { $_.Line -split '\t' } | `
% {$_ -replace "(<Compile Include=|\s|/>|["">])", ""} | % { "{0}\{1}" -f $projectPath, $_ }
Write-Host "Project files:" $projectFiles.Count
$diskFiles = gci -Path $path -Recurse -Filter $fileType | % { $_.FullName}
Write-Host "Disk files:" $diskFiles.Count
$diff = (compare-object $diskFiles $projectFiles -PassThru)
Write-Host "Excluded Files:" $diff.Count
#create a text file for log purposes
$diffFilePath = Join-Path $projectPath "DiffFileList.txt"
$diff | Out-File $diffFilePath -Encoding UTF8
notepad $diffFilePath
#just remove the files from disk
if($DeleteFileOnly)
{
$diff | % { Remove-Item -Path $_ -Force -Verbose}
}
else #TFS options
{
#this will add the files as pending deletes in TFS (awaiting check-in)
$diff | % {
[Array]$arguments = #("delete", "`"$_`"")
& "$tfPath" $arguments
}
if($Checkin)
{
#start the check-in process for the pending deletes
[Array]$arguments = "checkin", "/recursive", "$projectPath"
& $tfPath $arguments
}
}
Also, other community members expend this script and share the scripts at:
#Marc Climent: I used this script to create a more detailed one that includes other types of files and does not use TFS: https://gist.github.com/mcliment/d9008a9288cea9d088af
#mikesigs: I too used this file as well as #MarcCliment's to create yet another PowerShell script that takes a .sln file instead of a single proj file. It deletes all files excluded from all projects in the provided solution: https://gist.github.com/mikesigs/3512dbccc1767d447977#file-deleteexcludedfiles-ps1

Remove TFS Connection From Solution

How to make solution as clean copy without mapping to TFS ? The problem is that this message shows when I am trying to open it. I want to open it as normal without TFS connection.
To completely remove TFS source control binding follow these two steps:
Go to your solution's folder, find and delete all files with *.vssscc and *.vspscc extensions.
Open your solution's .sln file in Notepad, and find & remove the GlobalSection(TeamFoundationVersionControl) section.
More details on reference Link
If you want to permanently and completely detach the solution from source control, then try the following:
Click the 'No' button to avoid connecting to TFS.
In the file menu, go to the source control options and clear the bindings. You'll specifically want File - Source Control - Advanced - Change Source Control...
Save the solution.
Next time you open the solution you won't be prompted to connect to TFS.
Edit the solution file and remove the following section from it. It won't be the same but will be similar.
Note:To edit the solution file go to the project folder then open the YouSolutionName.sln file with notepad.
GlobalSection(TeamFoundationVersionControl) = preSolution
SccNumberOfProjects = 2
SccEnterpriseProvider = {4CA58AB2-18FA-4F8D-95D4-32DDF27D184C}
SccTeamFoundationServer = <YourTFSURL>
SccLocalPath0 = .
SccProjectUniqueName1 = .
SccLocalPath1 = .
EndGlobalSection
I don't have enough reputation to comment, but just wanted to add that Tabish's solution does in fact work correctly to completely remove the solution from source control, especially when the TFS server is not reachable for one reason or another (e.g. you downloaded a project that the author did not remove from their own source control before uploading).
However, to completely remove all traces of source control from the project and avoid the warnings that are noted in the other comments to that answer (e.g. "The mappings for the solution could not be found..."), you must also remove the following lines from every project file in the solution (apparently these used to be in the solution file in earlier versions of VS, but in VS2017 they are found in the project file for each project in the solution - e.g. [project].csproj):
SccProjectName = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
SccAuxPath = "x"
SccLocalPath = "xxx"
SccProvider = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
Thanks to the marked answer and other comments here for pointing this out:
visual source safe - how to remove bindings from solution w/o opening in visual studio
Combining this with Tabish's answer seems to be the most complete method of manually removing a solution from source control.
To remove the binding you can use Visual Studio : Menu File / Source Control / Advanced / Change Source Control.
You can also do it yourself by removing any SCC... from sln and csproj.
If you often export source files, you can use ExportSrc. It has many options such as remove TFS binding (ON by default).
Most of the answers provided a solution, but I would rather use a solution provided by Visual Studio 2017.
On the Menu bar of Visual Studio, go to Team and select Disconnect from Team Foundation Server.
That's it.
I just inherited a collection of TeamFoundation projects following an M&A buyout and tech transfer. There were like 30+ solutions and a buttload of *.vssscc and *.vspscc files.
Based on everyone's input above, I wrote a PowerShell function to recurse a specified root folder, delete the files, then edit the solution files to remove the TeamFoundationVersionControl section.
Usage is Remove_TFSfiles "pathname" $booleanflag.
To see what files would be affected, use $false (uses -whatif):
Remove_TFSfiles "C:\MyDevFolder" $false
To actually delete those files, use $true:
Remove_TFSfiles "C:\MyDevFolder" $true
Here's the function:
Function Remove_TFSfiles {
param(
[string]$FolderName = $(throw "-FolderName is required."),
[bool]$RemoveFiles = $(throw "-RemoveFiles (either $true or $false) is required.")
)
$TFSExtensions = '*.vspscc', '*.vssscc'
if ($RemoveFiles) {
Get-ChildItem -path $FolderName -force -include $TFSExtensions -Recurse | Remove-Item -Force
# Now iterate through any solution files, and whack the TeamFoundationVersionControl section
Get-ChildItem -Path $FolderName -Filter "*.sln" -Recurse | ForEach-Object {
$slnFilename = $_.Fullname
Write-Host -NoNewline "Editing $slnFilename... "
$File = Get-Content $slnFilename -raw
$Filestr = [regex]::escape("" + $File + "")
# The regex escapes must themselves be meta-escaped, therefore "\(" becomes "\\" + "\(" = "\\\(". Did I mention I hate regex?
$Result = $Filestr -replace "\\tGlobalSection\\\(TeamFoundationVersionControl\\\).*?EndGlobalSection\\r\\n", ""
$result = [regex]::unescape($result)
Set-ItemProperty $slnFilename IsReadOnly $false
$result | Set-Content $slnFilename
Write-Host "Done"
}
Write-Host -f red "Finished actually removing files and editing *.sln files"
}
else {
Get-ChildItem -path $FolderName -force -include $TFSExtensions -Recurse | Remove-Item -WhatIf
Write-Host -f green "Finished pretending to remove files"
# Now iterate through any solution files, and whack the TeamFoundationVersionControl section
Get-ChildItem -Path $FolderName -Filter "*.sln" -Recurse | ForEach-Object {
$slnFilename = $_.Fullname
Write-Host "Not Editing $slnFilename"
}
}
}

Compare two folders recursively and save repeated files

I'm trying to do something pretty weird. Any alternative solution could be analyzed but the process where I'm working is very difficult to change.
I have a folder to deploy in an IIS web server. This folder can contain any file such as dll, asmx, web.config, .exe, etc. We have a bat script that performs a full backup but a simple file deploy can last for an hour because of this.
I want some utility or to make a powershell script to compare the folder to deploy with the destination folder, and only backup the files (or folder) that has the same files on the first folder. This has to be done recursively and it also has to preserve folder structure in the destination server.
Edit: I'm currently working on a powershell script that will go like this (i'm definitely not a powershell expert):
Compare-Object $d1 $d2 | Where-Object {$_.SideIndicator -ne "=>" -and $_.InputObject -ne "*.ok*" -and $_.InputObject -ne "*.bat*" }
Any help or recommendation would be appreciated!
Regards
You won't be able to maintain file structure using compare-object... I got bored so here you go.
$sPath = "C:\test\"
$dPath = "C:\test2\"
$src = gci -recurse $sPath
$dest = gci -recurse $dPath
$src | % {
foreach($item in $dest) {
$t1 = ($item.FullName).trimStart($dpath)
$t2 = ($_.FullName).trimStart($sPath)
if($t1 -eq $t2) {copy-item $item.FullName $_.FullName -Force}
}
}
Just set $spath to src directory and $dPath to your deployment directory, and let her rip.

Resources