0

I am looking for a way to run my defined Target only once per build process and not for every project that gets build.

I have defined the following in Directory.Build.props

<Target Name="MyTarget" AfterTargets="AfterBuild" >

    <Message Text="Hello World!!!" Importance="High" />

</Target>

Should only run once no matter how many projects the msbuild process is building, currently it happens for each project.

It shouldn't matter if I hit (Re-)Build Soltution or (Re-)Build [ProjectName] or hit F5 in Visual Studio, as long any build happens I want to exectue MyTarget only once.

Rand Random
  • 6,067
  • 9
  • 36
  • 77
  • I think you want the target be executed once and then when you build it second time, it will not be executed, right? – Perry Qian-MSFT Feb 11 '21 at 07:24
  • @PerryQian-MSFT - for example I have a Solution containing 3 Project, I am hitting `Build Solution` which builds all 3 projects, it should only execute once, if I hit `Build Project B`, but the internal build process decides because of references it needs to Build Project A prior to Project B i still would like to only run it once, so basically what ever msbuild decides to do when I hit any Build action my desire would be to only run stuff once when it is done with everything – Rand Random Feb 11 '21 at 07:41
  • But it should run again once if a new build process starts – Rand Random Feb 11 '21 at 07:43
  • @PerryQian-MSFT - just in case you are interessted or need to know why I need this, here you would find an in-depth explanation - https://github.com/NuGet/Home/issues/10560 – Rand Random Feb 11 '21 at 07:49
  • does my answer help you handle the issue? – Perry Qian-MSFT Feb 17 '21 at 07:24
  • @PerryQian-MSFT - sadly no, because it will already trigger on the second build of a project and not at the very end, eg. imagine a solution with 50 projects and you hit rebuild solution, I would want my stuff to run once at the very end when everything was build, but your answer seems to run already after the second project was build, yes it does the it runs only once, but the desired time is off – Rand Random Feb 17 '21 at 08:20
  • @PerryQian-MSFT - after another google search hunt, this seems a duplicate of what I want - https://stackoverflow.com/questions/17709873/how-can-i-invoke-my-msbuild-target-when-msbuild-exe-starts-and-when-it-ends // https://stackoverflow.com/questions/2295454/solution-wide-pre-build-event/5720489#5720489 – Rand Random Feb 17 '21 at 13:12
  • You means that when the first executes the target, the second should not execute it, right? One point I found is that the rebuild solution is parallel build. And they are executing build at the same time. – Perry Qian-MSFT Feb 22 '21 at 08:40
  • If my guess is right, you could try to disable the parallel build. enter `Tools`-->`Projects and Solutions`-->`Build and Run`-->set `Maximum number of parallel project builds` to `1`. – Perry Qian-MSFT Feb 22 '21 at 08:42

1 Answers1

1

Just answer this situation:

If my guess is right, pure msbuild function is not enough and you have to use a external file to help it work.

create a file called test.txt on the solution folder and write 0 in the txt file.

Then, modify your Directory.Build.props like this:

<Project>
<PropertyGroup>
  <Record></Record>
</PropertyGroup>
<ItemGroup>
    <File Include="..\test.txt"></File>
</ItemGroup>
    <Target Name="GetConditionValue" BeforeTargets="PrepareForBuild">
  
    <ReadLinesFromFile File="@(File)">
        <Output TaskParameter="Lines" PropertyName="Record"/>
      </ReadLinesFromFile>
    </Target>
    
    
<Target Name="MyTarget" AfterTargets="Build" Condition="'$(Record)'=='0'">

 <WriteLinesToFile File="@(File)" Lines="2" Overwrite="true"></WriteLinesToFile>

  <Message Text="Hello World!!!" Importance="High" />
  </Target>

</Project>

When you start a new build process, you should clear the test.txt file to 0 to make a new start.

Perry Qian-MSFT
  • 13,922
  • 1
  • 6
  • 20
  • `When you start a new build process, you should clear the test.txt file to 0 to make a new start.` - does this imply I have to manually change the text file? so before hitting `Build Soltuion` in Visual Studio I would need to change it to 0 - every time? – Rand Random Feb 11 '21 at 08:22
  • yes. If you want to make it easier, automatic, you could use a batch file to clear that. – Perry Qian-MSFT Feb 11 '21 at 08:24
  • Just a random thought, is there maybe a macro that knows how many projects are going to build? if so maybe I could write a line for each build and than check if the lines count matches the macro, do my stuff and reset the file?!? – Rand Random Feb 11 '21 at 08:28
  • ...I did not know that if there is any msbuild properties to realize that. The premise of my approach is that I need a flexible, realistic, controllable identifier. If this MSBuild Macro really exists, I have to modify it which I did not know how much impact does he have on the build, also, second build will reset it to default values, actually for all msbuild properties. And the changed value should be restored on some actual file which is not controlled by msbuild, and then read it from that file. The whole process will not be controlled by msbuild.So, a txt file will be better. – Perry Qian-MSFT Feb 11 '21 at 08:54
  • And I did not know such type macro. And if so, you should also modify that value by my function which I am not sure how much impact does it have to the build. Also, if you do not use an additional file, how to store the value which is not controlled by every build is a question, that do not use a file could make it more difficult, that macro will be reset every build time and when you use msbuild to read that value, it already be set to the default. So using a extra file will not cause such puzzle. Make a bat file to clear that. The whole function could cause less although it is not perfect. – Perry Qian-MSFT Feb 11 '21 at 09:04