share
Stack OverflowHow to run Visual Studio post-build events for debug build only
[+675] [12] JC.
[2008-09-29 18:41:33]
[ visual-studio build-process ]
[ https://stackoverflow.com/questions/150053/how-to-run-visual-studio-post-build-events-for-debug-build-only ]

How can I limit my post-build events to running only for one type of build?

I'm using the events to copy DLL files to a local IIS virtual directory, but I don't want this happening on the build server in release mode.

[+841] [2008-09-29 18:48:19] Joseph Daigle [ACCEPTED]

Pre- and Post-Build Events run as a batch script. You can do a conditional statement on $(ConfigurationName).

For instance

if $(ConfigurationName) == Debug xcopy something somewhere

(8) strange, maybe its just me but I tried adding the if condition, and now I get this error - error exited with code 255 - Michael L
(7) you can also use gotos / labels for a fuller solution (see my Jul 24 answwer) - CestLaGalere
(12) and you can use brackets with the if command (see my answer for an example) - gbjbaanb
@RobinM I am looking for similar solution but not on configuration name , is it possible to read some file or command line argument that can be passed and decides whether it should copy from one location or the other - ansar
(2) You should use "xcopy /Y", so that the file will be overwritten in the target directory. - Matthias
(1) Just tested, but I had to read all posts to build a valid command :(. I added the final command below. - Eric Bole-Feysot
(1) Cool trick: I found a hidden variable $(ActiveDebugProfile) - which gives you the name of the debug profile you're running i.e. IIS Express or any custom profile. - TetraDev
1
[+578] [2010-08-23 13:06:16] gbjbaanb

FYI, you do not need to use goto. The shell IF [1] command can be used with round brackets:

if $(ConfigurationName) == Debug (
  copy "$(TargetDir)myapp.dll" "c:\delivery\bin" /y
  copy "$(TargetDir)myapp.dll.config" "c:\delivery\bin" /y
) ELSE (
  echo "why, Microsoft, why".
)
[1] https://ss64.com/nt/if.html

(71) May I also add, to be careful of the opening parenthesis which needs to immediately follow the if statement, as if it's on the next line an error code will be produced - wonea
(48) Use "$(ConfigurationName)" (notice the quotes) if you get error code 255 - jgauffin
(1) Any ideas on why my echo after the if else block is not called? - Felipe Sabino
(25) note, if you use "" around $(ConfigurationName), you also need quotes around the word Debug too - shell command IF statements are very .. literal ... when it comes to string comparisons. - gbjbaanb
(1) This will also fail if you forget the space between the word Debug and the open parenthesis. That one just bit me. - JessieArr
(9) Note, To get rid of the 255, I had to use "" around $(ConfigurationName) AND remove spaces around the condition , for example if "$(ConfigurationName)"=="Release" <--No spaces around == - fhilton
You will also need to have an even number of hairs in your head otherwise you will get error 255, which cannot get any higher because Microsoft was too optimistic and stored error flags in 8 bits. - Sergio Basurco
@chuckleplant Error codes aren't necessarily bit flags (usually they're an enum of error codes), and they can in fact go over 255 (exit code is an Int32 in C#). This 255 value seems to be a "failure on the script itself" deal, not an exit condition of one of the commands in it. Its error code is most likely a legacy from DOS. - Nyerguds
@Nyerguds Thanks for the comment. It was actually a joke, at the time of writing I was pretty frustrated with the amount things I had tried and none seem to work. Kudos to Microsoft for the things they've done right. - Sergio Basurco
You just made my day! - myTerminal
(18) In my case with Visual Studio 2017 $(ConfigurationName) is empty (Post-build event command line). if "$(Configuration)" == "Debug" worked for me. BTW, if you want to do something in all other configs, use if NOT "$(Configuration)" == "Debug". - Ralf
to the editor: its ROUND brackets that are used here, its windows shell command syntax. - gbjbaanb
#gbjbaanb , round brackets, eh? Though I've never heard that term applied to parentheses, I knew instantly what you meant. - David A. Gray
@DavidA.Gray In this case I was explaining to the guy who edited the answer, replacing them with curly brackets, what they should be ;-) - gbjbaanb
2
[+147] [2008-09-29 18:47:13] Franci Penov

Add your post build event like normal. Then save your project, open it in Notepad [1] (or your favorite editor), and add condition to the PostBuildEvent property group. Here's an example:

<PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">
    <PostBuildEvent>start gpedit</PostBuildEvent>
</PropertyGroup>
[1] https://en.wikipedia.org/wiki/Notepad_%28software%29

(6) This works but it forces you do to all of your design work for the events in the project file source. Other conditional build event declarations are hidden from the the IDE also. - Joseph Daigle
(3) I would have to say this is the better answer for me, the preferred method just didn't work. - Michael L
(11) You don't need to open it in Notepad, you can stay in Visual Studio. You can rightclick the project-file, click "Unload project", then rightclick again and click "Edit". You can now edit the {{csproj}} file with syntax coloring. Rightclick again, but now click "Reload project" to reload. - Abel
(2) This approach did not expand macros in the PostBuildEvent command itself when I tried it. cd "$(ProjectDir)" expanded to cd "". - Darryl
This is a good answer. It does not rely on the post build actually running but just short circuiting and will be more portable across build environments as a result. - S.C.
(12) In VS 2017 you can also do this with <Target Name="PostBuild" AfterTargets="PostBuildEvent" Condition="$(ConfigurationName) == Debug"> <Exec Command="your command"/></Target>. Macro variables and everything work as normal. - S.C.
While this is clean and more in line with how the rest of the csproj file looks, be very careful. If you update the csproj in Visual Studio, especially the post build, you may find it has added a second, non-conditional postbuild entry. - Rhumborl
3
[+111] [2009-07-24 09:56:39] CestLaGalere

Alternatively (since the events are put into a batch file and then called), use the following (in the Build event box, not in a batch file):

if $(ConfigurationName) == Debug goto :debug

:release
signtool.exe ....
xcopy ...

goto :exit

:debug
' Debug items in here

:exit

This way you can have events for any configuration, and still manage it with the macros rather than having to pass them into a batch file, remember that %1 is $(OutputPath), etc.


(6) If you get a chance to look at some of your code in reflector, the compiler transforms a lot of switch/case statements into goto's. - StingyJack
(10) Most all compilers do translate code into simpler instructions, such as goto. And reverse engineering can't put together simpler instructions into the "nice" more complex instructions you would rather see. I don't see how Microsoft is enforcing us to use goto, or how this is relevant to this post. - TamusJRoyce
(1) @StingyJack: if you look at the compiled code, you'll see all of it is turned into JMP instructions :) I don't care what the compiler does under the covers, as long as I get to write nicely readable code. (not that using goto isn't occasionally very easy to read) - gbjbaanb
If I put my post-build commands inside a batch I get this error message when press build: Error 1 The command "C:\MyProject\postbuild.bat" exited with code 99. MyProject - Sebastian
Okay I fixed it by deleting all empty lines and put it directly inside the post-build textbox and it works?! So ignore my last comment :-) - Sebastian
(4) if you want, you can remove the if and use goto :$(ConfigurationName) - Calimero100582
(1) @gbjbaanb This isn't C# though. This is DOS batch script. And goto is and has always been completely normal in DOS batch scripting. - Nyerguds
@Nyerguds obviously... I was referring to the script, with gotos, having to be used when writing C# programs. It was light-hearted. - gbjbaanb
The only solution that actually worked for me! Thanks so much! - Dmitry Avtonomov
Once upon a time, my batch scripts were full of GOTO statements. However, once I became accustomed to multiline IF blocks, I have all but eliminated them. After all, it's 2018, and GOTO remains as harmful as ever. - David A. Gray
@DavidA.Gray GOTO was never harmful when it wasn't abused. It was simply maligned by novice developers who didn't know any better and its "harm" has become simply an urban legend. - Suncat2000
4
[+57] [2020-01-08 16:59:00] Daniel Earwicker

As of Visual Studio 2019, the modern .csproj format supports adding a condition directly on the Target element:

<Target Name="PostBuild" AfterTargets="PostBuildEvent" Condition="'$(Configuration)' == 'Debug'">
    <Exec Command="nswag run nswag.json" />
</Target>

The UI doesn't provide a way to set this up, but it does appear to safely leave the Configuration attribute in place if you make changes via the UI.


(10) This really deserves to be higher, also they really should update the UI to allow you to mark the Build Configuration or at least add the Condition from csproj properties. - DeadlyChambers
5
[+21] [2016-02-22 13:21:27] Eric Bole-Feysot

Visual Studio 2015: The correct syntax is (keep it on one line):

if "$(ConfigurationName)"=="My Debug CFG" ( xcopy "$(TargetDir)test1.tmp" "$(TargetDir)test.xml" /y) else ( xcopy "$(TargetDir)test2.tmp" "$(TargetDir)test.xml" /y)

No error 255 here.


(5) keep it on one line - Eric Bole-Feysot
(1) Your conditional technique worked the best for me. However, this worked even better without conditionals at all and it is much more concise. copy "$(ProjectDir)\..\$(ConfigurationName)\MyFileName" "$(TargetDir)" - shawn1874
(1) Your script is correct, but my script allows to copy different files for different configurations. - Eric Bole-Feysot
6
[+7] [2022-08-22 12:28:07] IAbstract

As of VS 2022, I have found 2 solutions. In my particular case, I want to pack to a different directory depending on Configuration.

Option 1

<Target Name="PostBuild" AfterTargets="PostBuildEvent">
    <Exec Command="if $(Configuration) == Debug (dotnet pack --no-build -o ~/../../../../../nuget-repo/debug -p:PackageVersion=$(VersionInfo)) else (dotnet pack --no-build -o ~/../../../../../nuget-repo -p:PackageVersion=$(VersionInfo))" />
</Target>

Option 2

<Target Name="PostBuild" AfterTargets="PostBuildEvent">
    <Exec Condition="'$(Configuration)' == 'Debug'" Command="dotnet pack --no-build -o ~/../../../../../nuget-repo/debug -p:PackageVersion=$(VersionInfo)" />
    <Exec Condition="'$(Configuration)' == 'Release'" Command="dotnet pack --no-build -o ~/../../../../../nuget-repo -p:PackageVersion=$(VersionInfo)" />
</Target>

I prefer option 2.


7
[+5] [2008-09-29 18:44:05] Lou Franco

You can pass the configuration name to the post-build script and check it in there to see if it should run.

Pass the configuration name with $(ConfigurationName).

Checking it is based on how you are implementing the post-build step -- it will be a command-line argument.


8
[+2] [2022-02-04 14:37:22] plcnut

I found that I was able to put multiple Conditions in the project file just like this:

  <Target Name="PostBuild" AfterTargets="PostBuildEvent" Condition=" '$(Configuration)' != 'Debug' AND '$(Configuration)' != 'Release' ">
      <Exec Command="powershell.exe -ExecutionPolicy Unrestricted -NoProfile -NonInteractive -File $(ProjectDir)postBuild.ps1 -ProjectPath $(ProjectPath) -Build $(Configuration)" />
  </Target>

Funnily enough, not only did this answer my question on Condition, but also solved exactly what I was looking for: running Powershell as part of the VS Build. So I am sending you 100000000000 upvotes and YOU WIN. - Frank
9
[-1] [2017-06-29 14:59:13] Jaan Marks

This works for me in Visual Studio 2015.

I copy all DLL files from a folder located in a library folder on the same level as my solution folder into the targetdirectory of the project being built.

Using a relative path from my project directory and going up the folder structure two steps with..\..\lib

MySolutionFolder
....MyProject
Lib

if $(ConfigurationName) == Debug (
xcopy /Y "$(ProjectDir)..\..\lib\*.dll" "$(TargetDir)"
) ELSE (echo "Not Debug mode, no file copy from lib")

10
[-3] [2008-09-29 18:48:43] Harald Scheirich

Like any project setting, the buildevents can be configured per Configuration. Just select the configuration you want to change in the dropdown of the Property Pages dialog and edit the post build step.


(10) Build Events are not specific to any configuration when created in the IDE. - Joseph Daigle
(1) Does not work in VS2015 either. Not configurable per configuration. - willem
(2) This only applies to C++ projects in Visual Studio, not C# - bytecode77
11
[-3] [2012-12-14 07:46:20] mawl

In Visual Studio 2012 you have to use (I think in Visual Studio 2010, too)

if $(Configuration) == Debug xcopy

$(ConfigurationName) was listed as a macro, but it wasn't assigned.

Enter image description here

Compare: Macros for Build Commands and Properties [1]

[1] https://learn.microsoft.com/en-us/previous-versions/visualstudio/visual-studio-2012/c02as0cs(v=vs.110)

(7) You want to use ConfigurationName. This image is... really hard to understand with all the blur. - Stealth Rabbi
12