I'm trying to create post build events to copy the final .js and .debug.js files for my script# projects into the proper directories. I can't use the regular output folder, since I have more than one project that references another project, and that always results in a build error (Unable to copy referenced script because it is being used by another process).
The problem is that the C# compiler appears to run the post build events BEFORE it writes the actual .js files, so they don't exist when the post build event happens.
Is there any other solution to make this work?
You can set up a DeploymentPath property in your csproj and the generated scripts will be copied there.
All of the logic is in here: https://github.com/nikhilk/scriptsharp/blob/cc/src/Core/Build/Tasks/ScriptCompilerTask.cs ... so another option is to customize the build task to exactly your requirements.
The latest work if you check out the github repo, also has the script# part of the build process done during the build step of an msbuild project, so that should free up the post-build step for you to do what you'd like with the generated scripts. See https://github.com/nikhilk/scriptsharp/blob/cc/src/Core/Build/ScriptSharp.targets. Again, its just msbuild stuff, so you could potentially customize the .targets file to your liking as well if it doesn't fit your needs.
I got around this by adding the "copy" command as a pre build step on the projects that were using the script# project output, then adding a dependency so that the script# project would be built first.
Related
I have a WebApi2 application and it references other projects within the solution. One of these includes some files that I want copied on build. These files have their Copy to Output Directory property set to true.
The files are correctly located in the bin folder of their assembly.
However:
After the build I need them to be copied to the App_Data folder of the web application
Included in the files that get published to IIS
Is it possible?
From my experience you are going to have to get your hands dirty with MSBuild. Its been ages since I've used it but you will need to use the Move Task
This is what Visual Studio uses in the background to build the projects. It may seem daunting but is actually pretty simple once you get used to it. There are tons of tutorials online.
Alternatively, and the most straightforward way, is that you include the files in the APP_DATA folder from within the solution.
EDIT: As mentioned by robor78 you will need to call the Move Task in the Post-Build event
Add build events
In Visual Studio -> Solution Explorer -> right click the project -> properties -> go to build events.
Use something like xcopy
Also if click on "Edit Post-Build" you will see a list of useful folders and file names which you can use e.g. $(OutDir)
You can use Xcopy from the Post build event. It is pretty straight forward but will not run if code not changed. So if you update configs etc. you must force the build I beleive.
See here for how to use xcopy.
http://commandwindows.com/xcopy.htm
There are wild cards and all kinds of useful features, but your situation is pretty simple. Just copy from $(ProjectDir)/bin or something like that to a path.
We're using Code First in EF6.1 - our model is over 300+ tables now and startup time is ridiculous. We've tried pregenerating views already but it didn't help much, it's the model compilation in the Code First pipeline that takes most of the time.
We're going to try using the Database / Model First approach for initializing the context by using an entity connection string with metadata links to CSDL, SSDL and MDL files, instead of a direct SQL connection. This would be our ideal process:
After the project containing the Code First model is compiled, a post-build task runs that generates an EDMX file from our DbContext, splits it into component CSDL, SSDL and MDL files, and embeds these files in the assembly as resources
When we create a context via our own factory, we wrap the original SQL connection string in an EntityConnectionStringBuilder, with the Metadata property pointing to the embedded resources, and use the builders connection string to initialize the DbContext
Initial testing shows an ~80% improvement in startup time - the tricky part here is doing the post-build resource embedding in step 1!
Can anyone provide any clues as to how step 1 could be done in MSBuild? Is there an alternative strategy that would work as well? Basically we want a zero-maintenance solution so that developers don't have to manually do anything other than build their code, with no special deployment considerations either.
EDIT:
We ended up using a new, separate class library project that references the project containing the Code First model. This project contains a T4 template that writes the EDMX from the DbContext into memory, then saves the component parts into project files that are already marked as embedded resources, so we get source control as well.
The build order guarantees that the resources will always be up to date, and the entity connection string references this resources assembly at runtime. The MSBuild integration was done by using the T4 MSBuild integration targets so that the template always runs during a build of the project.
You should certainly be able to do this with MSBuild. You will have to pick up a little bit of build script, but shouldn't be too bad.
How are you doing it now? Do you have a console application that you run to generate the edmx? It sounds like you have already done the hard part -- integrating with MSBuild should be easy. I will assume that you do, and go from there.
btw: One thing to know up front is that you .csproj files are MSBuild scripts, so any custom MSBuild scripting can go into those csproj files.
In order of increasing complexity, you could:
Add an "After build" event to your project that executes your console app. This option does not require any MSBuild script -- you just set up an after build event in the project options. It will always run, though. (I don't think you can make a post-build event dependent on configuration), so it could slow down your compile times.
You could use the Exec task in MSBuild to execute your console application. This will require a little editing of your csproj file, but you can make it conditional if you need to. Here's a link to the Exec task: http://msdn.microsoft.com/en-us/library/x8zx72cd.aspx If you put it in a target named "AfterBuild", it will automatically execute after your build has completed.
You could write your own build task -- this is a c# class that will be loaded and executed during build. This is the most sophisticated way to do it, but it also gives you the most control: http://blogs.msdn.com/b/msbuild/archive/2006/01/21/515834.aspx
One of the nice things about the last option (custom build tasks), is that you can write error messages back into the build process. That should help with getting helpful information if the task fails, and if you use a build server, those messages should be picked up by the server in the same manner as any other build message.
The solution consists of two projects: main.csproj and helper.csproj.
What Id'like to do is using dll which helper project will be complied into, as an embedded resource for main.dll.
For that purposes it's seems resonable to add custom compile attribute for project main: /resource: <path to dll>.
The problem is I can't find how to add this compile parameter through the Project Property.
PS Maybe someone can suggest other solution to avoid making changes in compile process.
You should be able to add the helper assembly as a resource in the main.csproj. That will make MsBuild generate the correct parameters for csc.
(MsBuild is the build engine used by .NET in general up to and including 4.x and is also used by VisualStudio.)
What you can do to set this up is:
Right click the Main project in the Visual Studio solution explorer and select Add existing item. Add the assembly to be embedded as a linked item from the bin folder of the helper project. (click the little arrow on the Add button in the selection dialog to access the option to add as a link).
In the properties for the item in the Main project, set Action to Embedded resource.
Tricky bit would be to include the correct build so that you include the debug build or the release build depending on what configuration you are building.
If you need that, you can either:
edit main.csproj file to include the ${Configuration} variable in the path for the helper dll.
Add a pre-build step to the main.csproj file to copy in the assembly to a fixed place and include the file from there (the include as link bit is no longer needed then)
To make sure you always build the helper assembly when you build the main assembly I would recommend you add a project reference to the main project.
I am writing a utility for my company that will batch build a number of solutions in a one-click fashion. There are about 8 solutions in all, and each one has an average of 20 projects. The utility needs to be able to capture the build log and the total number of errors for each solution, just as is done when you build at the command line. I know I this is the command to accomplish that
msbuild mysolution.sln /t:build /verbosity:minimal /maxcpucount:xx
However, I would like to make use of the Microsoft.Build.Evaluation API's if possible. I know the Project object can load a single project, but is there anyway to build an entire solution? I intend to build this utility to make use of the all cpus/cores on the system and build multiple solutions simultaneously. I've looked at the MSDN page for Microsoft.Build.Evaluation, though the documentation is (still) abysmal.
Thanks for any help you can offer!
Jason
You do not need a Visual Studio solution file (sln) to build multiple projects. As you may know, Visual Studio project files are just MSBuild XML files and they can fall other project files. Therefore, build a project file that builds the other projects as required. This can be done in one of two ways.
First, solution files are just MSBuild XML so anything that can generate XML can generate a solution. See the MSBuild XML Schema for more information.
Second, construct a Microsoft.Build.Evaluation.Project programmatically using the constructor that takes an Microsoft.Build.Construction.ProjectRootElement instance then call Project.Build(). The ProjectRootElement has methods for adding common element types such as CreateTaskElement(), CreatePropertyElement() and CreateTargetElement().
See also:
Replace .sln with MSBuild and wrap contained projects into targets
Generating an MSBUILD project file from a visual studio solution file and project files.
In C++ projects there is the possibility to set a custom build step for files. Is there a similar functionality in C# projects? I couldn't really find anything.
One idea would be to create a second project (makefile or c++) and move the files there.
MsBuild should work for you although it might take some time to figure out how it works. It appears that you can setup a step that runs prior to building each .cs file by separating each .cs file into its own build group.
In MSBuild script for compiling each .cs file into an EXE, Dino Chiesa comments:
By using the %(CSFile.identity)
scalar, we run this task once for each
file. The converse would be
#(CSFile.identity). That would run
the compile once, for all files,
compiling them all together into a
single assembly.
Also, these links might help:
Custom build step for C# files
Master Complex Builds with MSBuild
No custom build step for individual files with C# projects. You could probably hack something together with MSBuild...
Look at the BeforeBuild and AfterBuild targets in your csproj file.
I think you are on the right track with your comment about multiple projects. Combine this with the fact that you can include multiple projects within a single Solution and you may have your answer. I use this functionality to build several components at a time and it works quite well.