How to fully clean bin and obj folders within Visual Studio? - visual-studio

If you right click on a folder, you will see a "Clean" menu item. I assumed this would clean (remove) the obj and bin directory.
However, as far as I can see, it does nothing.
Is there another way?
(please don't tell me to go to Windows Explorer or the cmd.exe)
I'd like to remove the obj and bin folder so that I can easily zip the whole thing.

As others have responded already Clean will remove all artifacts that are generated by the build. But it will leave behind everything else.
If you have some customizations in your MSBuild project this could spell trouble and leave behind stuff you would think it should have deleted.
You can circumvent this problem with a simple change to your .*proj by adding this somewhere near the end :
<Target Name="SpicNSpan"
AfterTargets="Clean">
<RemoveDir Directories="$(OUTDIR)"/>
</Target>
Which will remove everything in your bin folder of the current platform/configuration.
------ Edit
Slight evolution based on Shaman's answer below (share the votes and give him some too)
<Target Name="SpicNSpan" AfterTargets="Clean">
<!-- Remove obj folder -->
<RemoveDir Directories="$(BaseIntermediateOutputPath)" />
<!-- Remove bin folder -->
<RemoveDir Directories="$(BaseOutputPath)" />
</Target>
---- Edit again with parts from xDisruptor but I removed the .vs deletion as this would be better served in a .gitignore (or equivalent)
Updated for VS 2015.
<Target Name="SpicNSpan" AfterTargets="Clean"> <!-- common vars https://msdn.microsoft.com/en-us/library/c02as0cs.aspx?f=255&MSPPError=-2147217396 -->
<RemoveDir Directories="$(TargetDir)" /> <!-- bin -->
<RemoveDir Directories="$(ProjectDir)$(BaseIntermediateOutputPath)" /> <!-- obj -->
</Target>
He also provides a good suggestion on making the task easier to deploy and maintain if you have multiple projects to push this into.
If you vote this answer be sure to vote them both as well.

If you are using git and have a correct .gitignore in your project, you can
git clean -xdf --dry-run
to remove absolutely every file on the .gitignore list, i.e. it will clean obj, and bin folders (the x triggers this behavior)
Note: The parameter --dry-run will only simulate the operation ("Would remove ...") and show you what git would delete. Try it with dry-run, then remove the parameter and it will really delete the files+folders.
Optionally, after that clean command, you can use dotnet restore mySolution.sln to get all the NUGET packages restored. And if you have a developer console open anyway, you can quickly run msbuild -m mySolution.sln afterwards (without having Visual Studio open) to see if it was successful.

For Visual Studio 2015 the MSBuild variables have changed a bit:
<Target Name="SpicNSpan" AfterTargets="Clean"> <!-- common vars https://msdn.microsoft.com/en-us/library/c02as0cs.aspx?f=255&MSPPError=-2147217396 -->
<RemoveDir Directories="$(TargetDir)" /> <!-- bin -->
<RemoveDir Directories="$(SolutionDir).vs" /> <!-- .vs -->
<RemoveDir Directories="$(ProjectDir)$(BaseIntermediateOutputPath)" /> <!-- obj -->
</Target>
Notice that this snippet also wipes out the .vs folder from the root directory of your solution. You may want to comment out the associated line if you feel that removing the .vs folder is an overkill. I have it enabled because I noticed that in some third party projects it causes issues when files ala application.config exist inside the .vs folder.
Addendum:
If you are into optimizing the maintainability of your solutions you might want to take things one step further and place the above snippet into a separate file like so:
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Target Name="SpicNSpan" AfterTargets="Clean"> <!-- common vars https://msdn.microsoft.com/en-us/library/c02as0cs.aspx?f=255&MSPPError=-2147217396 -->
<RemoveDir Directories="$(TargetDir)" /> <!-- bin -->
<RemoveDir Directories="$(SolutionDir).vs" /> <!-- .vs -->
<RemoveDir Directories="$(ProjectDir)$(BaseIntermediateOutputPath)" /> <!-- obj -->
</Target>
</Project>
And then include this file at the very end of each and every one of your *.csproj files like so:
[...]
<Import Project="..\..\Tools\ExtraCleanup.targets"/>
</Project>
This way you can enrich or fine-tune your extra-cleanup-logic centrally, in one place without going through the pains of manually editing each and every *.csproj file by hand every time you want to make an improvement.

To delete bin and obj before build add to project file:
<Target Name="BeforeBuild">
<!-- Remove obj folder -->
<RemoveDir Directories="$(BaseIntermediateOutputPath)" />
<!-- Remove bin folder -->
<RemoveDir Directories="$(BaseOutputPath)" />
</Target>
Here is article: How to remove bin and/or obj folder before the build or deploy

This site: https://sachabarbs.wordpress.com/2014/10/24/powershell-to-clean-visual-studio-binobj-folders/ uses William Kempf's powershell commands to remove any bin and obj folders from the current directory and sub directories. It should be possible to run it from the root of the drive.
Here is William's version
gci -inc bin,obj -rec | rm -rec -force
In William's own words:
That wipes out all of the “bin” and “obj” directories in the current
directory and every subdirectory. Super useful to run in your
workspace directory to get to a “clean” state, especially when someone
messes up and there’s something that a Clean or Rebuild inside the IDE
doesn’t catch.
For those of you reading that may not know, PowerShell supports
command aliases, here it is rewritten again not using the aliases
Get-ChildItem -inc bin,obj -rec | Remove-Item -rec -force
NOTE : You should have this stored in a PowerShell file and place that
file at the root of your solution (where the .sln file resides), and
then run it when you want a proper clean (not the micky mouse one that
VisualStudio does, and reports success too).

Check out Ron Jacobs fantastic open source CleanProject It even takes care of the zipping if you like.
Here is the CodePlex link

Visual Studio Extension
Right Click Solution - Select "Delete bin and obj folders"

You can easily find and remove bin and obj folders in Far Manager.
Navigate to you solution and press Alt+F7
In search setting dialog:
Type "bin,obj" in field "A file mask or several file masks"
Check option "Search for folders"
Press Enter
After the search is done, switch view to "Panel".
Select all files (with Ctrl+A) and delete folders (press "Shift+Del")
Hope it helps someone.

Based on Joe answer, I've converted the VB code into C# :
/// <summary>
/// Based on code of VSProjCleaner tool (C) 2005 Francesco Balena, Code Archirects
/// </summary>
static class VisualStudioCleaner
{
public static void Process(string rootDir)
{
// Read all the folder names in the specified directory tree
string[] dirNames = Directory.GetDirectories(rootDir, "*.*", SearchOption.AllDirectories);
List<string> errorsList = new List<string>();
// delete any .suo and csproj.user file
foreach (string dir in dirNames) {
var files = new List<string>();
files.AddRange(Directory.GetFiles(dir, "*.suo"));
files.AddRange(Directory.GetFiles(dir, "*.user"));
foreach (string fileName in files) {
try {
Console.Write("Deleting {0} ...", fileName);
File.Delete(fileName);
Console.WriteLine("DONE");
} catch (Exception ex) {
Console.WriteLine();
Console.WriteLine(" ERROR: {0}", ex.Message);
errorsList.Add(fileName + ": " + ex.Message);
}
}
}
// Delete all the BIN and OBJ subdirectories
foreach (string dir in dirNames) {
string dirName = Path.GetFileName(dir).ToLower();
if (dirName == "bin" || dirName == "obj") {
try {
Console.Write("Deleting {0} ...", dir);
Directory.Delete(dir, true);
Console.WriteLine("DONE");
} catch (Exception ex) {
Console.WriteLine();
Console.WriteLine(" ERROR: {0}", ex.Message);
errorsList.Add(dir + ": " + ex.Message);
}
}
}
Console.WriteLine(new string('-', 60));
if (errorsList.Count == 0) {
Console.WriteLine("All directories and files were removed successfully");
} else {
Console.WriteLine("{0} directories or directories couldn't be removed", errorsList.Count);
Console.WriteLine(new string('-', 60));
foreach (string msg in errorsList) {
Console.WriteLine(msg);
}
}
}
}

In windows just open the explorer
navigate to your SLN folder
click into search field and type kind:=folder;obj --> for obj folders
use CTRL+A and delete 'em - same for bin
Done
No need for any tool or extra software ;)

Clean will remove all intermediate and final files created by the build process, such as .obj files and .exe or .dll files.
It does not, however, remove the directories where those files get built.
I don't see a compelling reason why you need the directories to be removed.
Can you explain further?
If you look inside these directories before and after a "Clean", you should see your compiled output get cleaned up.

I use VisualStudioClean which is easy to understand and predictable. Knowing how it works and what files it is going to delete relieves me.
Previously I tried VSClean (note VisualStudioClean is not VSClean), VSClean is more advanced, it has many configurations that sometimes makes me wondering what files it is going to delete? One mis-configuration will result in lose of my source codes. Testing how the configuration will work need backing up all my projects which take a lot of times, so in the end I choose VisualStudioClean instead.
Conclusion : VisualStudioClean if you want basic cleaning, VSClean for more complex scenario.

I can't add a comment yet (no minimal reputation reached)
so I leave this reply to underline that:
the "BeforeBuild" action with <RemoveDir Directories="$(BaseIntermediateOutputPath)" /> is great but, for me, is conflicting with an Entity Framework model included into the same project.
The error I receive is:
Error reading resource '{mymodel}.csdl' -- 'Could not find a part of the path '{myprojectpath}\obj\Release\edmxResourcesToEmbed\{mymodel}.csdl
I suppose, the "edmxResourcesToembed" is created before the "BeforeBuild" target action is executed.

This is how I do with a batch file to delete all BIN and OBJ folders recursively.
Create an empty file and name it DeleteBinObjFolders.bat
Copy-paste code the below code into the DeleteBinObjFolders.bat
Move the DeleteBinObjFolders.bat file in the same folder with your solution (*.sln) file.
#echo off
#echo Deleting all BIN and OBJ folders...
for /d /r . %%d in (bin,obj) do #if exist "%%d" rd /s/q "%%d"
#echo BIN and OBJ folders successfully deleted :) Close the window.
pause > nul

Update: Visual Studio 2019 (Clean [bin] and [obj] before release). However I am not sure if [obj] needs to be deleted. Be aware there is nuget package configuration placed too. You can remove the second line if you think so.
<Target Name="PreBuild" BeforeTargets="PreBuildEvent" Condition="'$(Configuration)' == 'Release'">
<!--remove bin-->
<Exec Command="rd /s /q "$(ProjectDir)$(BaseOutputPath)" && ^" />
<!--remove obj-->
<Exec Command="rd /s /q "$(BaseIntermediateOutputPath)Release"" />
</Target>

I store my finished VS projects by saving only source code.
I delete BIN, DEBUG, RELEASE, OBJ, ARM and .vs folders from all projects.
This reduces the size of the project considerably. The project
must be rebuilt when pulled out of storage.

Just an addendum to all the fine answers above in case someone doesn't realize how easy it is in VB/C# to automate the entire process down to the zip archive.
So you just grab a simple Forms app from the templates (if you don't already have a housekeeping app) and add a button to it and then ClickOnce install it to your desktop without worrying about special settings or much of anything. This is all the code you need to attach to the button:
Imports System.IO.Compression
Private Sub btnArchive_Click(sender As Object, e As EventArgs) Handles btnArchive.Click
Dim src As String = "C:\Project"
Dim dest As String = Path.Combine("D:\Archive", "Stub" & Now.ToString("yyyyMMddHHmmss") & ".zip")
If IsProjectOpen() Then 'You don't want Visual Studio holding a lock on anything while you're deleting folders
MsgBox("Close projects first, (expletive deleted)", vbOKOnly)
Exit Sub
End If
If MsgBox("Are you sure you want to delete bin and obj folders?", vbOKCancel) = DialogResult.Cancel Then Exit Sub
If ClearBinAndObj(src) Then ZipFile.CreateFromDirectory(src, dest)
End Sub
Public Function ClearBinAndObj(targetDir As String) As Boolean
Dim dirstodelete As New List(Of String)
For Each d As String In My.Computer.FileSystem.GetDirectories(targetDir, FileIO.SearchOption.SearchAllSubDirectories, "bin")
dirstodelete.Add(d)
Next
For Each d As String In My.Computer.FileSystem.GetDirectories(targetDir, FileIO.SearchOption.SearchAllSubDirectories, "obj")
dirstodelete.Add(d)
Next
For Each d In dirstodelete
Try
Directory.Delete(d, True)
Catch ex As Exception
If MsgBox("Error: " & ex.Message & " - OK to continue?", vbOKCancel) = MsgBoxResult.Cancel Then Return False
End Try
Next
Return True
End Function
Public Function IsProjectOpen()
For Each clsProcess As Process In Process.GetProcesses()
If clsProcess.ProcessName.Equals("devenv") Then Return True
Next
Return False
End Function
One thing to remember is that file system deletes can go wrong easily. One of my favorites was when I realized that I couldn't delete a folder because it contained items created by Visual Studio while running with elevated privileges (so that I could debug a service).
I needed to manually give permission or, I suppose, run the app with elevated privileges also. Either way, I think there is some value in using an interactive GUI-based approach over a script, specially since this is likely something that is done at the end of a long day and you don't want to find out later that your backup doesn't actually exist...

this answer is great I just want to comment on the last part of the answer
NOTE : You should have this stored in a PowerShell file and place that
file at the root of your solution (where the .sln file resides), and
then run it when you want a proper clean (not the micky mouse one that
VisualStudio does, and reports success too).
Alternatively, you can add the following to your profile.ps1
function CleanSolution {
Get-ChildItem -inc bin,obj -rec | Remove-Item -rec -force
}
Set-Alias cs CleanSolution
Then you can use either CleanSolution or cs to run. That way you can use it for any project and without the ./ prefix of the filename

Complete one-liner you can invoke from within Visual Studio
In your solution root folder create a file called "CleanBin.bat" and add the following one-liner:
Powershell.exe -ExecutionPolicy Bypass -NoExit -Command "Get-ChildItem -inc bin,obj -rec | Remove-Item -rec -force"
Run the .bat file. Enjoy.
Original creds to the answer here: https://stackoverflow.com/a/43267730/1402498
The original answer shows the powershell command, but I had a lot of trouble making it work smoothly on my system. I finally arrived at the one-liner above, which should work nicely for most folks.
Caveat:
Microsoft seems to be great at making Windows security cause stranger and stranger behavior. On my machine, when I run the script, all obj and bin folders are deleted but then reappear 2 seconds later! Running the script a second time causes permanent deletion. If anyone knows what would cause this behavior, please let me know a fix and I'll update the answer.

for visual studio 2022
you can use:
https://marketplace.visualstudio.com/items?itemName=MadsKristensen.CleanSolution

If you need to delete bin and obj folders from ALL of your projects...
Launch git Bash and enter the following command:
find . -iname "bin" -o -iname "obj" | xargs rm -rf

For C# projects, I recommend appending $(Configuration) to obj folder, so-as to avoid deleting nuget files which are stored on obj base directory.
<Target Name="CleanAndDelete" AfterTargets="Clean">
<!-- Remove obj folder -->
<RemoveDir Directories="$(BaseIntermediateOutputPath)$(Configuration)" />
<!-- Remove bin folder -->
<RemoveDir Directories="$(BaseOutputPath)" />
</Target>
If you delete the nuget files, it can be problematic to recreate them. Moreover, I've never seen a case where "Restore NuGet Packages" fixes this issue after these files have been deleted.

Related

code reuse for file existence test in a Visual Studio vcxproj file

I have a vcxproj file that contains explicit Windows shell commands in the NMakeBuildCommandLine section:
<NMakeBuildCommandLine Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
move file1 file2
</NMakeBuildCommandLine>
I'm using MSBuild to execute the vcxproj, either directly or via a sln file. The problem is that when file1 does not exist, the output is very unhelpful and doesn't even list the file's name:
The system cannot find the file specified.
My naive solution is to replace move file1 file2 with:
if exist file1 (move file1 file2) else (echo file1 does not exist && exit 1)
(Note that I need to write && instead of &&.)
This works, but it's error-prone because I need to type file1 three times per line and make sure they all match. file1 is only one of many files that need to be moved. Furthermore, the series of commands is virtually identical across the various build configurations.
How can I avoid repeating myself both within a command line and across build configurations? I thought that the UserMacros property group might help me, but I couldn't figure out how to write such a macro via the IDE. (Right-clicking on the project in Visual Studio doesn't show a field for entering user macros.) Nor could I find any discussion of the syntax of this section on the Internet, so I didn't know how to write macros with a text editor (which I would actually prefer).
There may be yet a better way within a vcxproj file to identify files that need to exist, so I'm open to any alternatives.
MsBuild has 'variables' like most other programming languages called properties. You declare one in a PropertyGroup element in the project file xml and then reuse it using the $(PropertyName) syntax. Example for your case:
<PropertyGroup>
<Src>/path/to/my/src</Src>
<Dst>/path/to/my/dst</Dst>
</PropertyGroup>
<NMakeBuildCommandLine>
if exist $(Src) (move $(Src) $(Dst)) else (echo $(Src) does not exist && exit 1)
</NMakeBuildCommandLine>
If you want to use the IDE, which might get tedious if you have lots of values, you can indeed use so-called UserMacros but you have to declare those in a proprty sheet. Go to View->Property Manager, right-click on your project and select 'Add new Property Sheet'. Doubleclick on it, go to 'User Macros' and add key/value pairs there. If you save everything and look in the generated files you'll see the vcxproj now Imports the propertysheet, and the propertysheet itself has a PropertyGroup just like shown above - but editable thgough the IDE.
As an alternative which might be better (less duplication, easier to automate) in the long run you can use MsBuild code for checking file existence and moving files which has the benefit you only have to write the move command once as you can have MsBuild loop over items. Those are declared in an ItemGroup. Explaining everything here is a bit out of scope but an example should make things clear:
<Target Name="BatchMove">
<ItemGroup>
<SrcFiles Include="file1">
<Dest>file2</Dest>
</SrcFiles>
<SrcFiles Include="file3">
<Dest>file4</Dest>
</SrcFiles>
</ItemGroup>
<Warning Text="Source file %(SrcFiles.Identity) does not exist" Condition="!Exists(%(SrcFiles.Identity))" />
<Move SourceFiles="%(SrcFiles.Identity)" DestinationFiles="%(SrcFiles.Dest)" Condition="Exists(%(SrcFiles.Identity))" />
</Target>
This declares 2 source files file1/file3 and their respective destination files file2/file4. If the source does not exists (using standard MsBuild Exists check) a message is shown, else it is moved to the destination. Those % characters will make the line they occur in loop over each element of the SrcFiles collection. To add more files, just add to the ItemGroup. Last step is to get this target invoked from the nmake command line which is done simply by calling msbuild on the file itself and telling it to run the target:
<NMakeBuildCommandLine>
msbuild $(MSBuildThisFile) /t:BatchMove
</NMakeBuildCommandLine>

Ruby can not delete file after cp on windows

I am using rake to copy files I receive from one folder to two sub-folders.
After the copy I try to delete these files from their original folder.
I can't seem to delete some of the files (usually only 1 or 2 out of 5 or so).
When using mv (and not CLEAN) I receive an error message of access denied.
I believe that Windows (my OS) still holds a reference to the file/s and therefore won't
allow me to delete them.
I can delete the files out of code no problem. There should not be a permissions issue.
If my theory is correct that there is still a reference open to the file, then how could i close those references?
Could it be something else?
The code:
DOCK = '/path'
NEW_FILES = DOCK + '/NewFiles'
dock_stock = FileList.new(DOCK + '/*.xml')
file target_path do |t|
unless dock_stock.empty?
mkdir t.name
dock_stock.each do |f|
target_new_files_folder = f.pathmap(NEW_FILES + '/%f')
mv f, target_new_files_folder
end
end
end
Also it should be noted this task is a dependency to a multitask(really a dependency of a dependency of a dependency). task :clean => target_path being one of them.
So maybe the issue is multi thread related or the :clean task.
It seems there was a McAfee Agent that was referencing the files not allowing me to delete them.
For the most part, if I tried to delete them later on in time they would delete.
When I write for the most part I mean once in a blue moon it could hold the files for days until released manually.
The workaround would be to record the problematic files and exclude them from the file list and try to erase them at a later point.
Wish I had a better solution.
The windows del command has f option, which forces the deletion. Combine with /q(uite) and run it from Ruby with for instanceexec:
exec 'del /f /q filename'

How can I force files in my project so that they always copy to output directory

I am using a visual studio c# library project to contain static resources that are needed as deployment artifacts. (in my case SQL files that are run with a combination of RoundhousE and Octopus deploy). By convention all files in the project must have their properties set so that the "Build action" is "Content" and "Copy to output directory" is "Copy always".
If someone on the team adds a file but forgets to set these properties we see deployment errors. This is usually picked up in an internal environment, but I was hoping to find a way to enforce this in the CI build.
So is there a way to either fail the build or better still override these properties during the build with an MS Build task? Am I tackling this the wrong way? Any suggestions welcomed.
You are going to have to parse the project files and check for Content without CopyToOutputDirectory set to Always, I doubt there is another way.
That can be done using whatever scripting language you want, or you could even write a small C# tool that uses the classes from the Microsoft.Build.Evaluation namespace. Here is a possible PowerShell implementation - the hardest part is getting the regexes right. First one checks for Content without any metadata, second one for Content where CopyToOutputDirectory does not start with "A" (which I assume should be "Always", no idea how to match that whole word).
FindBadContentNodes.ps1 :
param([String]$inputDir)
Function FindBadContent()
{
$lines = Get-Content $input
$text = [string]::Join( "`n", $lines )
if( $text -match "<Content Include.*/>" -Or
$text -match "<Content Include.*`n\s*<CopyToOutputDirectory>[^A]\w*<.*" )
{
"Found file with bad content node"
exit 1
}
}
Get-ChildItem -Recurse -Include *.csproj -Path $inputDir | FindBadContent
Call this from MsBuild:
<Target Name="FindBadContentNodes">
<Exec Command="Powershell FindBadContentNodes.ps1 -inputDir path\to\sourceDir"/>
</Target>
Note you mention or better still override these properties during the build. I'd stay away from such a solution: you're just burying the problem and relying on the CI to produce correct builds, so local builds using just VS would not be the same. Imo making the build fail is better, especially since most CI systems have a way of notifying the developper that is responsible anyway so the fix should be applied quickly.
Another possibility would be to have the CI apply the fix and then commit the changes so at least everyone has the correct version.
IIRC there is a way in Visual Studio to set a file extension to do certain things on default, much like .config files will always set to content and copy to output directory.
So one could do the same with .sql files (and other files that they would want to be set up this way). A quick search brought me to this: http://blog.andreloker.de/post/2010/07/02/Visual-Studio-default-build-action-for-non-default-file-types.aspx
The relevant parts:
The default build action of a file type can be configured in the
registry. However, instead of hacking the registry manually, we use a
much better approach: pkgdef files (a good article about pkgdef
files). In essence, pkdef are configuration files similar to .reg
files that define registry keys and values that are automatically
merged into the correct location in the real registry. If the pkgfile
is removed, the changes are automatically undone. Thus, you can safely
modify the registry without the danger of breaking anything – or at
least, it’s easy to undo the damage.
Finally, here’s an example of how to change the default build action
of a file type:
1: [$RootKey$\Projects{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}\FileExtensions.spark]
2: "DefaultBuildAction"="Content" The Guid in the key refers to project type. In this case, “{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}” means “C# projects”. A rather comprehensive list of project type guids can be found here. Although it does not cover Visual Studio 2010 explicitly, the Guids apply to the current version as well. By the way, we can use C# as the project type here, because C# based MVC projects are in fact C# projects (and web application projects). For Visual Basic, you’d use “{F184B08F-C81C-45F6-A57F-5ABD9991F28F}” instead.
$RootKey$ is in abstraction of the real registry key that Visual
Studio stores the configuration under:
HKEY_CURRENT_USER\Software\Microsoft\VisualStudio\10.0_Config (Note:
Do not try to manually edit anything under this key as it can be
overwritten at any time by Visual Studio).
The rest should be self explanatory: this option sets the default
build action of .spark files to “Content”, so those files are included
in the publishing process.
All you need to do now is to put this piece of text into a file with
the extension pkgdef, put it somewhere under
%PROGRAMFILES(x86)%\Microsoft Visual Studio
10.0\Common7\IDE\Extensions (on 64-bit systems) or %PROGRAMFILES(x86)%\Microsoft Visual Studio
10.0\Common7\IDE\Extensions (on 32-bit systems) and Visual Studio will load and apply the settings automatically the next time it starts. To
undo the changes, simply remove the files.
Finally, I’ve attached a bunch of pkgdef files that are use in
production that define the “Content” default Build Action for C# and
VB projects for .spark, .brail, .brailjs and .less files respectively.
Download them, save them somewhere in the Extensions folder and you’re
good to go.
The author also says that he built a utility to help do all of this for you:
http://tools.andreloker.de/dbag
Expanding on #stijn answer, instead of using regex it is far easier to use native xml parsing.
Here is my proposed file, it also supports the ability to customize which files are evaluated by using a regex on the filename only.
param([String]$Path, [string]$IncludeMatch, [switch]$AllowPreserve)
Function Test-BadContentExists
{
param (
[parameter(Mandatory=$true,ValueFromPipeline=$true,ValueFromPipelineByPropertyName=$true)]
[Alias("FullName")]
[string[]]$Path,
[string]$IncludeMatch,
[switch]$AllowPreserve
)
[xml]$proj = Get-Content -Path $Path
$ContentNodes = ($proj | Select-Xml "//Content|//n:Content" -Namespace #{n='http://schemas.microsoft.com/developer/msbuild/2003'}).Node
if (![string]::IsNullOrEmpty($IncludeMatch)) {
$ContentNodes = $ContentNodes | Where-Object -Property Include -Match $IncludeMatch
}
#remove the always nodes
$ContentNodes = $ContentNodes | Where-Object -Property CopyToOutputDirectory -ne 'Always'
#optionally remove the preserve nodes
if ($AllowPreserve) {
$ContentNodes = $ContentNodes | Where-Object -Property CopyToOutputDirectory -ne 'PreserveNewest'
}
if($ContentNodes)
{
write-output "Found file with bad content node:"
write-output ($ContentNodes | Select-Object Include,CopyToOutputDirectory | sort Include | Out-String)
exit 1
}
}
[hashtable]$Options = $PSBoundParameters
[void]$Options.Remove("Path")
Get-ChildItem -Recurse -Include *.csproj -Path $Path | Test-BadContentExists #Options
and calling it, with parameter:
<Target Name="FindBadContentNodes">
<Exec Command="Powershell FindBadContentNodes.ps1 -inputDir path\to\sourceDir -IncludeMatch '^Upgrade.*\.(sql|xml)$'"/>
</Target>
I ended up using a pre-build event instead and put this ps1 file in my solution directory so i could use it with multiple projects.
echo "Build Dir: %cd%"
echo "Sol Dir: $(SolutionDir)"
echo "Proj Dir: '$(ProjectDir)"
echo.
Powershell -NoProfile -Command "& '$(SolutionDir)\FindBadContentNodes.ps1' -Path '$(ProjectDir)' -IncludeMatch '^Upgrade.*\.(sql|xml)$'"
example build output:
1> "Build Dir: C:\Source\RPS\MRM BI\MRMBI-Setup\MRMBI-Schema\bin\Debug"
1> "Sol Dir: C:\Source\RPS\MRM BI\MRMBI-Setup\"
1> "Proj Dir: 'C:\Source\RPS\MRM BI\MRMBI-Setup\MRMBI-Schema\"
1>
1> Found file with bad content node:
1>
1> Include CopyToOutputDirectory
1> ------- ----------------------
1> Upgrades\V17.09\myfile1.sql
1> Upgrades\V20.05\myfile2.sql PreserveNewest
1>

User VisualStudio PostBuild with place-marker

After successfully build, I want to copy the content of the the folder to the destination.
I've learned that this will work fine:
copy "$(TargetPath)" "$(TargetDir)\..\..\..\TB-Annotation Editor\bin\Debug\Plugins\$(TargetFileName)"
But I am interested to copy all *.exe, all *.dll and all *.txt files into the destination and this could cost a lot of lines for each plugin. Now I wanted to ask if there is any possibility to use place-marker instead of fixed filenames.
this does not work and raise event "Error Code 1"
copy "$(TargetDir)*.*" "$(SolutionDir)bin\Debug\plugins\"
Regards
** Solved except .dll *
I'm very sorry, seems to be not an error because of the "*" but of the folder which is called same twice:
copy "$(TargetDir)*.*" "$(SolutionDir)MyProject\bin\Debug\plugins\"
Goes correct to:
"copy
"C:\Daten Laptop\PAG\Net\MyProject\Solution\Plugins\DSP - Alphablend\bin\Debug\DSP - Alphablend.exe"
"C:\Daten Laptop\PAG\Net\MyProject\Solution\MyProject Main\MyProject Main\bin\Debug\plugins\DSP - Alphablend.exe""
But when using ".dll" instead of ".*" (DLL does not exist, because at the moment it is selected as *.exe) it does throw error code 1 again.
To my mind the best way of doing this is setting file properties and project properties. This requires no additional lines at all. If you set "output folder" property for project, "copy local" flags for referenced libraries and change "Build action" and "Copy to output directory" properties for your txt files (they should be included to solution) you get what you want.

How to automatically add a huge set of .vcproj files to the solution?

I have a huge set of .vcproj files (~200) stored in different locations. I have a list of these files with full paths.
How can i automatically add them to the solution file(.sln) ?
UPD: I'm looking for existing tool/method.
Here's how I'd do it:
Create and save a blank solution to insert the vcproj files into (File->New Project->Other Project Types->Visual Studio Solutions->Blank Solution)
Create a VS macro which adds a project to a solution, saves the solution, and exits. Try the following:
Public Sub AddProjectAndExit(Optional ByVal vcprojPath As String = "")
If Not String.IsNullOrEmpty(vcProjPath) Then
DTE.ExecuteCommand("File.AddExistingProject", vcprojPath)
DTE.ExecuteCommand("File.SaveAll")
DTE.ExecuteCommand("File.Exit")
End If
End Sub
Create a batch script which executes this macro from the Visual Studio command prompt, iterating over each of your .vcproj files. The command for a single execution would be:
devenv.exe BlankSolution.sln /Command "Macros.MyMacros.Module1.AddProjectAndExit MyProject1.vcproj"
Hope that helps!
The .vcproj & .sln files are ascii format, so you could write a macro/script/program to run through your list of projects and insert the proper info into the .sln file. The only additional info you'll need to get about the projects is the project GUID, which can be found in the .vcproj file (assuming your build configurations are the same for each project).
Modify and existing vcwizard.
function CreateCustomProject(strProjectName, strProjectPath)
{
try
{
//This will add the default project to the new solution
prj = oTarget.AddFromTemplate(strProjTemplate, strProjectPath, strProjectNameWithExt);
//Create a loop here to loop through the project names
//you want to add to the new solution.
var prjItem = oTarget.AddFromFile("C:\\YourProjectPath\\YourProject.vcproj", false);
}
return prj;
}
catch(e)
{
throw e;
}
}

Resources