Visual Studio: Multiple post-build commands?

Viewed 84194

Visual Studio 2008 lets me declare a command and attach it to the post-build event for a project. Like a lot of developers, I use it regularly to xcopy files to the application output directory.

I am working on a project where I need to xcopy files from two different places to two different destinations, all within a single project. In other words, I need to invoke two different xcopy commands from the same post-build event. It looks like the post-build event will only take a single command, and that if I need to invoke multiple commands, I will have to put the commands in a *.bat file and call that from the post-build event.

Is that correct, or is there a simpler way to invoke two commands from the post-build event? Thanks in advance for your help.

13 Answers

You can type in as many post build commands as you want. Just separate them by newlines.

Here's an example from one of my projects.

Post Build Event Commandline

Each command should be on a separate line. What I found though is that if there's an error executing one of those commands the whole post-build fails and so you'll need to try each post-build command one at a time to debug.

Separating the commands with & or && or ; does not work in VS2017. Can't belive such simple functionality is not available in VS2017. Visual studio tries to execute the entire text in the post build event window as one string. Only option for me now is to create a batch script which I do not particularly like.

In Visual Studio 2017, you can do this:

<PostBuildEvent>
    <Command>
        copy $(TargetPath) $(SolutionDIr)\bin1
        copy $(TargetPath) $(SolutionDIr)\bin2
    </Command>
</PostBuildEvent>

There isn't a good solution to this problem. The call idea does cause other scripts to run. I have noticed that error detection will not work. Put 'exit /b 1' into FailMe.cmd The use 'call FailMe.cmd' in the post build steps. Notice the build does not fail? I am using VS 2017 building a C# project. Now try it with 'FailMe.cmd' The build now reports an error.

So you might be better off just using a single script, if error reporting is important.

Just a note for idiots like me - there is this "drop down" button so you can edit commands as a multi-line text enter image description here

In Visual Studio 2022, the UI for specifying both pre and post build events has changed slightly, but you can still specify multiple commands to run by placing each on its own line:

enter image description here

The above sets the following in your project file:

  <Target Name="PostBuild" AfterTargets="PostBuildEvent">
    <Exec Command="echo Post 1&#xD;&#xA;echo Post 2" />
  </Target>

  <Target Name="PreBuild" BeforeTargets="PreBuildEvent">
    <Exec Command="echo Pre 1&#xD;&#xA;echo Pre 2" />
  </Target>

Which when built produces something resembling:

1>------ Build started: Project: MyProject, Configuration: Debug Any CPU ------
1>You are using a preview version of .NET. See: https://aka.ms/dotnet-core-preview
1>Pre 1
1>Pre 2
1>MyProject -> D:\repos\MyProject\bin\Debug\net6.0\MyProject.dll
1>Post 1
1>Post 2

Migrating a legacy .NET project to Visual Studio 2022. Found I was not able to run multiple commands for either Pre-Build or Post-Build. The behavior wasn't consistent when switching between Debug/Release even once I got the syntax correct. I anticipate there is possibly a bug here.

In Debug configuration, it would error out using XCOPY /Y /F no matter what I tried. Error code 2 and 4 being the most common while Release worked. I had trouble gauging what was a syntax error and what was just an error. XCOPY /Y /F worked just fine in CMD/PowerShell.

Executing multiple commands becomes possible (even with conditionals) only after "bubbling" the commands ( ... ).

i.e. going from this

copy $(TargetDir)x64\SQLite.Interop.dll $(TargetDir)SQLite.Interop_x64.dll
copy $(TargetDir)x86\SQLite.Interop.dll $(TargetDir)SQLite.Interop_x86.dll
if $(ConfigurationName) == Release (
    call "C:\Program Files (x86)\Microsoft SDKs\ClickOnce\SignTool\signtool.exe" sign /t http://timestamp.sectigo.com /fd sha256 $(TargetPath)
)
(copy $(TargetDir)x64\SQLite.Interop.dll $(TargetDir)SQLite.Interop_x64.dll)
(copy $(TargetDir)x86\SQLite.Interop.dll $(TargetDir)SQLite.Interop_x86.dll)
(if $(ConfigurationName) == Release (
    call "C:\Program Files (x86)\Microsoft SDKs\ClickOnce\SignTool\signtool.exe" sign /t http://timestamp.sectigo.com /fd sha256 $(TargetPath)
))

Additional tidbit, since ( ) are the special characters, if you need to escape them, use caret, i.e. ^)

Stackoverflow: Post-build event with multiple if/copy combinations only execute if first file does not exist

Related