How to suppress initial post-build event error in Visual Studio 2017 (C#)?
Asked Answered
M

2

8

I have a C# solution in Visual Studio 2017. I also have a batch script called foobar.bat that contains the following code:

echo foobar : error 1: This is a test error.           

My goal is to get only the test error message above to appear in Visual Studio's Error List when I build a particular project and for the build to stop when it appears. So I put [path to script]\foobar.bat in the project's post-build event command line and then build. Now I'm getting two error messages in the Visual Studio Error List:

  1. The command "[path to script]\foobar.bat" exited with code -1.
  2. This is a test error.

In this case, seeing that first error message that just prints out the contents of my post-build event isn't helpful. I want to suppress this initial error so that only my custom error messages show up in the Error List (or at least change it to say something more useful).

Here's what I've tried:

  • Adding 2>nul to the end of my batch script has no effect.
  • Adding 1>nul to the end of my batch script suppresses both errors, which isn't what I want.
  • Adding &set errorlevel=0 to the end of my batch script has no effect.
  • Adding the line exit 0 to the end of my batch script has no effect.
  • Adding the following to the end of my .csproj file (per this article) suppresses the first error, but makes it so the build no longer fails:
<Target
    Name="PostBuildEvent"
    Condition="'$(PostBuildEvent)'!=''"
    DependsOnTargets="$(PostBuildEventDependsOn)">
    <Exec WorkingDirectory="$(OutDir)" Command="$(PostBuildEvent)" IgnoreExitCode="true" />
</Target>

The last option almost gets me what I want. However, in spite of there being an error message, the Error List doesn't pop up and the build does not fail. It appears as though anything that would cause the initial error message to not appear will also cause the build to no longer fail. Is that the case? Or is there some way I can get the build to fail without showing that initial error message?

Misanthrope answered 25/4, 2019 at 16:14 Comment(5)
I don't know if that apply to your case but maybe you can redirect the error output like explained here (second answer to one of the question but since you don't mention it I put it here)Kandi
@Kandi Thanks for the suggestion. Unfortunately that doesn't work for me because then I don't get any error messages, including the ones I actually do want. The only message I'm trying to suppress is that initial one where VS spits out the entire contents of the post-build script and says it exited with code -1. (I can probably revise my question to make it more clear.)Misanthrope
Oh ok, actually it's clear. Is it an exec task you're using?Kandi
@Kandi It's a post-build event. Not sure if that's the same thing?Misanthrope
I've edited my question for clarity and simplicity.Misanthrope
K
6

What you can do is use an exec and an error task together.

You need to edit the .csproj file and add these tasks after your the Target PostBuildEvent from your last bullet point above.

This solution works by getting the ExitCode and Output of your exec task and using them to trigger the error task which will then stop the build and log the message.
The Exec task needs three parameters:

  • IgnoreStandardErrorWarningFormat and IgnoreExitCode prevent the error from being logged at this step
  • ConsoleToMsBuild parameter is required to get the output (spelled ConsoleToMSBuild in VS 2017).

So the tasks look like this:

  <Target Name="PostBuild" AfterTargets="PostBuildEvent">
    <Exec Command="$(PostBuildEvent)" IgnoreStandardErrorWarningFormat="true" IgnoreExitCode="true" ConsoleToMsBuild="true">
      <Output TaskParameter="ConsoleOutput" PropertyName="OutputMessage" />
      <Output TaskParameter="ExitCode" PropertyName="ExitCode" />
    </Exec>
    <Error Text="$(OutputMessage)" Condition="$(ExitCode) == 10" />
    <!-- <Error Text="(optional text) : $(OutputMessage)" Condition="$(ExitCode) == 11" />
    <Error Text="(optional text) : $(OutputMessage)" Condition="$(ExitCode) == 12" /> -->
  </Target>

And edit the file foobar.bat:

echo foobar : error 1: This is a test error.
exit /b 10 <-- /b parameter needed if used in a .bat file

The important part is the exit that will set the code we want to use afterwards.

You can have more than one Error task do to more conditional logging or just use the output as is.

Kandi answered 27/4, 2019 at 16:27 Comment(9)
I will look into this. Thank you!Misanthrope
What goes in the Command parameter? (Where you currently have "[path_to_file]\test.bat") Should that match the contents of my post-build event?Misanthrope
Oh yes sorry that's not clear. When you add Build Events with Visual Studio, it writes a "basic" Target in your .csproj but you don't have access to more parameters, for that you need to edit it manually. So you can still use VS to write the event like you did then edit the file (if you change the Build Events you will see the modification in the .csproj).Kandi
Additionally, the Target you added in your edit override the event, you can remove it and just use the initial PostBuildEvent like in this answer.Kandi
Ah, I see. So the above is in addition to the target I added in my last bullet point above.Misanthrope
Once I add the above Target to my .csproj, it no longer shows the initial error message I was seeing before, but it still does show two error messages. The first one says foobar : error 1: This is a test error. and the second one (the one I want) is the same as before. However, I'll accept this answer anyway because now I can change the message from $(OutputMessage) to something more descriptive/useful than I was getting before. Thanks!Misanthrope
That's strange, I only have one. I tested it with VS2019 but according to the doc it should be the same for VS2017. Did you put IgnoreStandardErrorWarningFormat="true"? Otherwise I think you could get rid of it by not following the error format (so you just put echo : this is a test without error 1 :)Kandi
Yeah, I have it set to ignore the standard error format. This is a workable solution though. If you happen to know how to get an error task to stop the build without posting a message to the error list (so I can rely exclusively on my custom messages) that would be perfect, but either way, I appreciate the help!Misanthrope
No I don't ^^ That should work though, maybe a difference with the MsBuild version. Glad it helped!Kandi
S
0

Re: Adding &set errorlevel=0 to the end of my batch script has no effect.

To ignore the exitcode from a single command use || not & or &&. e.g.

Robocopy || set errorlevel=0

This says only if RoboCopy exits with errorlevel != 0, set errorlevel=0

What does “&&” do in this batch file?]1 explains this and more

Historical Notes The single ampersand e.g.

(prog1 arg1 arg2) & (cmd2 arg1 arg2 arg3)

runs both commands. It was not very useful in DOS. In Unix, it runs both commands at the same time (2 processes), waiting until both finished. Since DOS did not support multiple-processes the '&' was just syntactic sugar for running sequentially.

The single pipe prog1 | prog2 suffered the same limitations in DOS. In Unix after prog1 writes a modest amount on stdout, it is available to prog2 on its stdin.

In DOS this was shorthand for

prog1 > tmpFile
prog2 < tmpFile

In many cases this worked well enough. In the simple case of write1Meg | head, (or more) DOS had to run to completion before, head could exit after reading the 1st 10 lines.

What does & do? Unix also supports & at the end of the command-line prog1 & This starts prog1 and returns control to the console quickly.

&& and || only make sense when you know that an exit code of 0 is treated like 'true' and non-zero as 'false'. Also short-circuit evaluation is done, so the second command after checking the exit code of the first.

prog1 && prog2

After prog1 exits, prog2 runs only if exitcode == 0

prog1 || prog2

After prog1 exits prog2 runs only if exitcode != 0

Scarcely answered 23/3, 2020 at 15:46 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.