The reason it's failing is that there's another custom build step in the same project that's calling a batch file, like this:
Command Line: buildsomething.bat something.h
Description: Building something
Outputs: something.h
As of Visual Studio 2010, all the custom build commands are concatenated into a single batch file, which is then executed. When a batch file runs another batch file, Windows doesn't return control to the first batch file. It's like a goto, not a function call. So to fix the problem, you need to use call
like this:
Command Line: call buildsomething.bat something.h
call
makes the flow of control return to Visual Studio's batch file, and hence lets your other Custom Build steps run.
(I'm answering my own question so that future searchers can find the answer.)