ChatGPT解决这个技术问题 Extra ChatGPT

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.


J
Jakub Konecki

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

strange, maybe its just me but I tried adding the if condition, and now I get this error - error exited with code 255
I've found that the entire command needs to be on one line or you'll get "exited with code 255"
you can also use gotos / labels for a fuller solution (see my Jul 24 answwer)
and you can use brackets with the if command (see my answer for an example)
You should use "xcopy /Y", so that the file will be overwritten in the target directory.
P
Peter Mortensen

FYI, you do not need to use goto. The shell IF 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".
)

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
Use "$(ConfigurationName)" (notice the quotes) if you get error code 255
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.
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 ==
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".
P
Peter Mortensen

Add your post build event like normal. Then save your project, open it in Notepad (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>

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.
I would have to say this is the better answer for me, the preferred method just didn't work.
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.
This approach did not expand macros in the PostBuildEvent command itself when I tried it. cd "$(ProjectDir)" expanded to cd "".
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.
P
Peter Mortensen

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.


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.
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.
@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)
if you want, you can remove the if and use goto :$(ConfigurationName)
@gbjbaanb This isn't C# though. This is DOS batch script. And goto is and has always been completely normal in DOS batch scripting.
D
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.


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.
P
Peter Mortensen

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.


keep it on one line
Working nice. Tks
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)"
Your script is correct, but my script allows to copy different files for different configurations.
P
Peter Mortensen

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.


p
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.
P
Peter Mortensen

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")

P
Peter Mortensen

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.


Build Events are not specific to any configuration when created in the IDE.
Does not work in VS2015 either. Not configurable per configuration.
This only applies to C++ projects in Visual Studio, not C#
P
Peter Mortensen

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.

https://i.stack.imgur.com/CWF67.png

Compare: Macros for Build Commands and Properties


You want to use ConfigurationName. This image is... really hard to understand with all the blur.