I'm looking for a way to add an extra build step which will create a backup copy of my entire solution. I want it to do this only if a file in the solution, or the entire solution itself, is not present in the destination folder or flashdrive directory. What would be the easiest way to achieve this? Preferably I would only want this to happen if a file is deemed "newer", and avoid the copy and replace if the file has not changed since the last backup.
You can do this with a batch file using
xcopy /D
which will copy only those files whose source time is newer than the destination time. Or robocopy.
This could recursively copy the entire directory, particular folders, or particular file types. If you're willing to launch your builds from the batch file itself (rather than within visual studio) the batch file has everything you need. Otherwise you might find Solution-wide pre-build event? useful for setting this up to work through Visual Studio. If you follow that process you should be able to take advantage of the Visual Studio Macros for Build Commands like $(SolutionPath).
If you need only those files actually contained in your projects then parsing the solution and project files may be necessary. The .NET framework provides some libraries to help parse solution or project files (SolutionParser). See
Parsing Visual Studio Solution files
That would be a bit of work, but you build a list of only those files contained in your projects and use with xcopy or robocopy.
Related
In the Resources folder of my project, I have many different DLLs from other assemblies in my solution. These DLLs are used as embedded resources so I can have a single EXE without having to have local copies of all the DLLs. What I want to be able to do is have them updated every time I build my entire solution. So for example, if I have AssemblyOne/bin/x86/Debug/Foo.dll, I want the DLL to always copy over to LocalAssembly/Resources/Foo.dll whenever I build the project.
Is there an easy way to do this? I was looking at the post-build-event macros, but none of them would be able to directly reference my "LocalAssembly", which is not the Solution Directory. Also, I'm not sure how I would go about writing a new custom post-build command in a way that the newly copied DLLs would not be an absolute reference to my local machine. Thanks! Please comment for more information and I will edit the question.
You need not access only your solution folder in post build events. The post build scripts run with whatever permissions the compiler had when it ran. Since in Visual Studio things frequently run with Administrator permissions, chances are great you have access to your entire file system. As a result, if you are wanting to copy resources around, you merely need to presume that you are starting the xcopy call in the build destination directory. From there, you can navigate around with normal paths. So if, for example, you needed go up three levels and then into the directory LocalAssemblies, your copy command would look like xcopy Foo.dll ../../../LocalAssemblies.
When starting out with a clean environment (nothing downloaded yet) and opening a solution for the first time through the Source Control Explorer in Visual Studio, all the necessary files for the solution are downloaded. Meaning i can compile the solution without any problems.
Then, in Visual Studio, when I do a right-mouse click on the solution in the Solution Explorer and do a "Get Latest", a whole bunch of additional files are downloaded that are part of my TFS tree. These files are not referenced by the solution. Does anybody have any idea why these files are downloaded?
I'm aware of another issue where opening an .sln file will download all the files within its root and subfolders, but that already happens when opening the .sln file through the Source Control explorer. In this particular case the sln file is located in its own subdirectory so this doesn't apply.
I'm would be interested to hear from anybody that has experienced the same thing and has any idea on why all these additional files are downloaded from the TFS tree although they are not referenced by the .sln file and its underlying projects.
I would assume that when you do a Get Latest Version within Solution Explorer, under the covers it is performing the operation on the folder that contains the solution and therefore it will pull down any files missing from your local workspace.
If you have items in the solution folder that you don't want to bring down to your local machine then you should use cloaking, explicit mappings and non-recursive mappings to limit what is mapped to your workspace.
2 = Cloaked, 5 = Non-recursive
Optimize your workspace
I'm tidying my projects. And I found the way to remove the object folder with adding:
%TEMP%
In my projects. But I want somehow to make this global setting or to auto delete my obj dirs after a build. Is there a way to do that?
I personally like having a specific Output folder in my project where I put all the compiled files.
I have the following command line in the Post-build events.
copy "$(TargetPath)" "$(SolutionDir)\Output\$(TargetFileName)"
This will copy the compiled file to the Output directory inside the Solution. You would need to add this to all the projects in your solution.
If you have any dependencies that also needs to be copied you could add something like this as well.
copy "$(ProjectDir)Dependencies\Language.xml" "$(SolutionDir)\Output\Extensions\Language.xml"
[EDIT]
You can try the following to have the file copied first, and then once that is done delete the object folder.
copy "$(TargetPath)" "$(SolutionDir)\Output\$(TargetFileName)"
rd /s /q "$(ProjectDir)\obj"
[EDIT2] Updated with screenshots to illustrate. :)
This is how my object folder normally would look like after compiling the project.
This is how it looks after compiling it with the above command. As you can see the folder is re-created after the event by Visual Studio, but the folder is empty.
You might want to double check that you are running Visual Studio with elevated permissions. To do so, simply right click on the Visual Studio and choose "Run as Administrator".
Are you using source control?
This comment sounds like you don't:
While archiving, those are unneeded megabytes.
("Archiving" sounds a bit like copying the whole project folder regularly to something like backup_yyyymmdd)
If you're not using source control, you should definitively consider starting to use it.
Apart from the general advantages (like, having a change history with dates and comments...), it has an out-of-the-box solution for your problem with the obj folders:
Every good source control software out there supports ignoring certain files or folders which you can define (ignoring means: they can never be committed to the source repository, you don't even see them in the list of changed files, not even when they were changed).
For example, in Mercurial (which I use) the ignore settings are saved in a file named .hgignore in the main folder (Git has the same, it's just called .gitignore).
My default .hgignore file for all Visual Studio projects looks like this:
syntax: glob
bin
obj
*.suo
*.user
The first line belongs to Mercurial's ignore syntax, the rest are the settings what to ignore.
You can see that the bin and obj folders are ignored...and they are ignored no matter in which subfolder they are!
So I don't have to care about where the obj folders actually are, and I don't have to delete them manually every time I build my solution. They are simply non-existent in my source control history.
Plus, I have a variation of Fuji's answer about putting everything in one single output folder:
I like to do this as well, but I prefer changing the output folders in Visual Studio's project settings instead of using post-build events.
The default output folders are:
bin\Debug\
bin\Release\
I change them to:
..\build\Debug\
..\build\Release\
This compiles everything into subfolders of a build folder which is at the same level like the .sln file (which means: all projects in the solution directly compile into the same folder).
It also reduces compile time because Visual Studio won't have to copy all the dependencies after compiling (because everything already is in the same folder).
(I do it mainly because of the compile time, because I ignore the bin and obj folders anyway in Mercurial as described above, so I don't care where they actually are)
I have a quick question regarding debug and release in VS 2008.
I have an app i've been working on - its not yet complete but the bulk of the functionality is there. So basically i'm trying to give a copy of it now to the person helping with documentation - just so they can have a play and get the feel for what i've made.
Now the question is how to provide it to them. I was told to just copy the .exe out of the debug/bin folder and put that onto USB. But when testing, if I run this .exe anywhere else (outside of this folder) it crashes. I've now worked out why this is:
var path = ConfigurationManager.AppSettings["PathToUse"];
var files = Directory.GetFiles(path);
throws a null reference, so that App.config file is not being used. If I copy that file in with the .exe it works again.
So actually my question is regarding the best way to manage this situation. What is the best way to provide a working copy to people, and, is there a reference on preparing apps for release - so everything is packaged together and installed in a clean structured folder heirarchy?
If you want to be safe grab everything in the debug/bin folder. If you use the drop down in VS to change to release and then compile the project, there will be fewer files in the release/bin folder because many debug related files are not included.
If there are third party DLLs you are referencing, like if you downloaded log4net or something like that, then you can simply put them in the same folder as the exe. This is called side-by-side deployment, and in my opinion is the simplest and easiest to test.
You can search for XCOPY deployment to learn more about what you are trying to do.
You can take another step of compressing the bin folder into an archive like a zip file to make it easy for the user to extract them, or you could use a tool like WIX or NSIS to create an installer to extract and copy the files.
I have a solution with many projects. There is actually a Core project and a few plugins. I changed OutputPath for all plugins so all binaries end up in the Core bin\debug folder. (this is necessary as the Core do not have a reference on plugins, hence it does not "include" plugins binaries when it is compiled.)
So basically my folder structure is as follow:
Solution
MySolution.sln
Plugin1\
Plugin2\
Core\bin\debug
Each plugin OutputPath is "..\Core\bin\debug". When I open the solution Visual Studio creates a folder "Core\bin\debug" in Solution's folder parent as if the relative path starts from .sln file. However when I build the solution the binaries are output to the correct path ("Solution\Core\bin\debug").
Core\bin\debug
It looks like a Visual Studio bug to me, but maybe I overlooked some option somewhere. Any ideas how to resolve this problem ?
PS: I know this not a critical issue as everything build and works fine, however I dislike the idea of meaningless folder hanging around
Rather than changing the output location of the plug-ins, what you could do is create a post-build script (Properties \ Build Events tab) for them that will copy the them to the Core folder. That would prevent the confusion with output folders.
This command line should do the trick for you:
copy "$(TargetPath)" "$(SolutionDir)Core\$(OutDir)"
If you need to copy .pdb and .config files as well, you can add more lines:
copy "$(TargetPath).pdb" "$(SolutionDir)Core\$(OutDir)"
copy "$(TargetPath).config" "$(SolutionDir)Core\$(OutDir)"
If you really want to do it with a single line, this should also work, though it's not as clean:
copy "$(TargetPath)*" "$(SolutionDir)Core\$(OutDir)"
If you're not using the same output path in both the main project and the add-ons, you'll need to replace $(OutDir) with a hard-coded value. If you have them set to target the typical "\bin\Debug" folder (or have just left the defaults in place), then you can get away with using the $(OutDir) value.
Instead of using "..\Core\bin\debug", use "$(SolutionDir)\Core\bin\debug".