VisualStudio: 多个生成后命令?

VisualStudio2008允许我声明一个命令并将其附加到项目的生成后事件。像许多开发人员一样,我经常使用它将文件 xcopy 到应用程序输出目录。

我正在从事一个项目,我需要 xcopy 文件从两个不同的地方到两个不同的目的地,所有在一个单一的项目。换句话说,我需要从同一个构建后事件调用两个不同的 xcopy 命令。看起来构建后的事件只接受一个命令,如果需要调用多个命令,则必须将这些命令放在 * 中。Bat 文件,并在构建后事件中调用它。

是否正确,或者有更简单的方法从构建后事件调用两个命令?先谢谢你的帮助。

85328 次浏览

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.

Important: When executing a batch file, you must use the "call" statement on order the following lines to be executed. If you don´t use "call", the execution goes into the .bat and doesn´t return to the following lines. Same as on DOS prompt.

e.g.:

call MyBatch1.bat
call MyBatch2.bat

There is another option: you can separate the commands with &&. E.g.

copy $(TargetPath) d:\folder1 && copy $(TargetPath) d:\folder2

This is not exactly the same as separating with newlines: with &&, if the previous command failed, next commant will not run.

Separating by newlines is easier to read, so you should prefer it. However I know at least one case when && is useful. It is the scenario, when you use property sheets to have different post-build steps on different machines. VS 2008 doesn't allow setting PostBuildStep in property sheets directly, but you can add a user macro with your command and call it from the main project settings. A macro is single line, so you can use && to have multiple commands there.

Just prefix "call " to your batch script. So that statements below the Batch script is also executed after returning the call from batch script.

call Script1.cmd
call Script2.bat

Adding to womp's answer:

If you have multiple property sheets with something to do on the same build event you can do the following to chain the commands:

%(Command)
echo foo

where %(Command) expands to the previous value of the command.

Personally I do this for all build events, even if I currently do not have inherited commands, because this ensures there will be no problems if I add property sheets later on.

The approach suggested by womp works in Visual Studio 2015/2017 (Windows), but doesn't work in Visual Studio for Mac (Preview), which seems to execute only the first of the commands. The only approach that I found working in both Mac and Windows versions of Visual Studio was chaining 2 MSBuild commands:

<Target Name="AfterResolveReferences">
<Exec Command="path\MyFirstCommand.exe -parameters" />
</Target>
<Target Name="MySecondCommand" AfterTargets="AfterResolveReferences" >
<Exec Command="path\MySecondCommand.exe -parameters" />
</Target>

The example above uses "AfterResolveReferences" event but should obviously work for PostBuild event too.

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.

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>

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

You can run multiple commands/batch files in Visual Studio 2022.

Just take care of do not add

exit %errorlevel%

to your batch file because that will cause cmd to exit and further post build events will not be executed by visual studio.

If you wish to return exit codes use

exit /b

https://learn.microsoft.com/en-us/windows-server/administration/windows-commands/exit