4

I'd like to create an AfterBuild Task that generates code in a Visual Studio project. The problem is that since it is an AfterBuild Task, the generated code won't get compiled.

I need it to be an AfterBuild Task because I load the output assembly of the build and inspect it using reflection in order to generate the code.

Is there a way that I can compile the generated code after the AfterBuild Task?

Thanks.

nbilal
  • 1,069
  • 2
  • 10
  • 21

2 Answers2

1

It is possible to compile C# code at runtime using the CSharpCodeProvider Class, look at this article, it is well explained. Although by the sound of it looks like you want to change (e.g. to weave) your library by injecting the code you are compiling in your AfterBuild task event.

If that is the case the only way to achieve what you want to do is to use an AOP (Aspect Oriented Programming) framework like PostSharp or Mono.Cecil. What they do is generating IL (Intermediate Language) and injecting at run-time or at compile time into your program.

In this answer are discussed a few AOP solutions for .NET.

EDIT:

To compile c# project (*.csproj) programmatically there are specific classes in the .NET framwork. Look at the Microsoft.Build.Evaluation namespace.

However this snippet should work for you. Try it in your Task and you should be able to fire another compilation process from your code.

      const string projectPath = @"your csproj path";
      var collection = new Microsoft.Build.Evaluation.ProjectCollection {DefaultToolsVersion = "4.0"};


      collection.RegisterLogger(new ConsoleLogger());
      collection.LoadProject(projectPath);

      var project = new Microsoft.Build.Evaluation.Project(collection);

      if (!project.Build())
      {
         //Error
      }

hope it helps.

Community
  • 1
  • 1
codingadventures
  • 2,924
  • 2
  • 19
  • 36
  • That sounds a bit overkill for what I am trying to achieve.. I simply want the build to pick up the class I generated.. My task is already part of the compile process, it would be great if I could re-trigger the build somehow right after generating the code. – nbilal Mar 29 '15 at 19:39
  • Thanks Giovanni. Wouldn't that cause a circular build? – nbilal Mar 29 '15 at 20:38
  • if it is the same exact project, yes it would. you might introduce a check in your afterbuild task to run only once – codingadventures Mar 29 '15 at 20:45
1

CSC does the trick. Inside my vcproj, I included:

  <Target Name="AfterBuild">
        <MyGenerateCodeTask />
        <CSC
              Sources="@(Compile)"
              References="@(Reference)"
              AdditionalLibPaths="$(OutputPath)"
              OutputAssembly="$(TargetName)$(TargetExt)"
              EmitDebugInformation="true" >
        </CSC>
  </Target>

To make sure CSC finds all the required references, add the following:

<Reference Include="$(OutputPath)*.dll"/>
nbilal
  • 1,069
  • 2
  • 10
  • 21
  • I am trying to injecting some code to my project after build and I came across this question. I was wondering if there would be a way to contact you since it seems that you were trying to do the same thing. Do you have any blog or something where I can reach you? – Dryadwoods Apr 03 '17 at 09:07
  • @Dryadwoods I ended up using a BeforeBuild Task and generate the code before the build. The benefit is that the code get automatically built as part of the build. Take a look at my github repo (https://github.com/Microsoft/SimpleStubs/blob/master/Documentation/DeveloperDocumentation.md) where I described this process. The code is also available. – nbilal Apr 06 '17 at 00:14
  • Thanks, I will have a look :) – Dryadwoods Apr 06 '17 at 05:31