-1

When building with Visual Studio we copy a bunch of dlls through the post build event step.

Currently the build step looks like such:

xcopy <source/file> <target/file>
if errorlevel 1 goto VCEnd
xcopy <...> <...>
if errorlevel 1 goto VCEnd
...

The problem with that is that if xcopy doesn't find a file because it has a wrong name or it doesn't exist the build will still pass. The reason is that although xcopy prints File not found - <some_file> it does not set the errorlevel.

My task is to make sure the build actually fails to make the developer aware of this issue more quickly.

My idea is to create a new subroutine that checks if the build log contains "File not found" and call this subroutine after every step:

xcopy <source/file1> <target/file1>
call :check_xcopy_success
xcopy <source/file2> <target/file2>
call :check_xcopy_success
...

goto :end

:check_xcopy_success
type $(Configuration)\$(AssemblyName).log | findstr /i /c:"File not found" > nul
if %errorlevel%==0 ( echo "Postbuild: error 1234: Unable to copy lib" && goto VCEnd )
exit /b

:end

SO

However that doesn't do anything. At first I thought that the file couldn't be opened for reading because VS is still writing to it but I am able to get the file contents through a for loop:

:check_xcopy_success
setlocal enabledelayedexpansion
set content=
for /f "delims=" %%i in ('type $(Configuration)\$(AssemblyName).log') do set content=!content! %%i
echo !content!
endlocal
exit /b

SO

This will show the content of the file in a single line, which would be fine for me to use with findstr but using it in that way doesn't do anything either:

(echo !content! | findstr /i /c:"File not found" > nul)
echo %errorlevel%

will output 0 no matter the search string or the content of the file so conditionally outputting an error that signals VS that the build failed this way doesn't work either.

Where am I going wrong? Do you have any other idea of what I could do?

Spray'n'Pray
  • 190
  • 1
  • 15
  • 1
    First of all, it is not ```xcopy ```, it is ```xcopy "sourceDir\file1" "targetDir\" /Options```. Next `xcopy.exe` does return exit codes, (`0` - _Files were copied without error_, `1` - _No files were found to copy_, `2` - _The user pressed CTRL+C to terminate xcopy_, `4` - _Initialization error occurred. There is not enough memory or disk space, or you entered an invalid drive name or invalid syntax on the command line_, `5` - _Disk write error occurred._)! Finally, `xcopy.exe` has been deprecated for fifteen years now, use its successor `Robocopy.exe` instead. – Compo Jul 12 '23 at 14:55
  • First of all, thank you for this very incredibly useless comment. I am totally sorry for typing the wrong syntax off my screen. Next, if you'd have given it a try yourself you'd have found that the exit code 1 does not work when the file (not the path to the file) does not exist. Finally, I am not able to use Robocopy because we rename files in the process of copying them, which is not supported by Robocopy. So please, instead of being a smarty pants and assuming peole are dumb, don't read the documentation and haven't tried various things, try to answer the question at hand. Have a great day! – Spray'n'Pray Jul 12 '23 at 15:14
  • 1
    Instead of complining about things I commented, which you did not mention in your submission, perhaps you'll consider offering that information from the outset in future. Also, you're using a script, not working in an interactive console, so there's no reason not to include an ```if exist "sourceDir\file1" (xcopy "sourceDir\file1" "targetDir\" /Options) else echo "Postbuild: error 1234: file1 does not exist"& goto VCEnd```, is there? – Compo Jul 12 '23 at 15:23
  • Instead of trying to justify a hastily typed answer perhaps you could've pointed out that you're still missing some information from my (I'd say) rather exhaustive question to be able to give a good answer. Regarding your suggestion: Typing all dll names and paths twice is probably the last approach any sane person would take. Also - nice rage-downvote :) You and yours-alike are the reason many people perceive SO as a toxic community. – Spray'n'Pray Jul 12 '23 at 15:32
  • 1
    I can categorically state without hesitation that I have not used the downvote button. You may be inclined to act in an aggressive manner towards others, but I am not that way inclined. What we have so far, is an admission from you that you typed the wrong syntax off your screen and that information which turned out to be important, (at least to me), was missing from your submission. I didn't tell you to type every file name or path, I offered only a simple method of determining if a file existed before trying to use a command which you indicated did not identify that scenario via exit code. – Compo Jul 12 '23 at 16:07
  • 1
    I will also add that in your very first code box example, you did, in your first five lines, imply that you were actually typing each filename and path individually, so please, once again, do not complain about suggestions I have made, which were loosely based on the information you submitted. There is nothing to stop you from using the same syntax within a looping mechansim, although such a thing would only be done, if your renaming also followed a logical pattern. – Compo Jul 12 '23 at 16:11
  • Yes, the path to every lib is typed individually _once_ - but only because it has to be done. The _second_ time typing the path manually for _every_ lib would have been _your_ suggestion. As for your statement that I made an "admission" - please don't be ridiculous, I won't even go there – Spray'n'Pray Jul 12 '23 at 18:53
  • 1
    Perhaps my understanding of English has diminished over the years, but in my book, "I am totally sorry for typing the wrong syntax off my screen" is an **admission**. Also, typing it multiple times is hogwash. As a very basic example with three named files, ```for %%g in ("sourceDir\file1" "sourceDir\file2" "sourceDir\file3") do if exist "%%~g" (xcopy "%%~g" "targetDir\" /Options) else echo "Postbuild: error 1234: %%~g does not exist"& goto VCEnd```, I only wrote each filename once! Oh, and don't apologise for incorrectly singling me out as your 'rage-downvoter'. – Compo Jul 12 '23 at 20:31
  • For me to make an admission I must first be guilty of something, which I am not, or have done something wrong, which I haven't. Ever heard of the word sarcasm? Why would I apologize for accidentally mistyping something that is only there for context, _already working_ and not a fundamental part of the question I posted? Your for loop works only if all files go into the same folder and _again_ doesn't allow for renaming specific files. – Spray'n'Pray Jul 13 '23 at 05:53
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/254471/discussion-between-spraynpray-and-compo). – Spray'n'Pray Jul 13 '23 at 05:54
  • 1
    You have told us nothing about the renaning scheme or their intended locations, in fact you didn't even provide the real filenames. Your script snippets, aren't a [mcve], and you've not told us enough to put those snippets into context of something usable. Just take a minute to think why you've had no other interested commentors, and a 'rage-downvoter'. Is it that you've given us to little useful information? or is it how you're presenting yourself? Sarcasm is negative, and directly mocks or targets another individual, (in this case me) and you complain about our toxicity. – Compo Jul 13 '23 at 10:00

1 Answers1

-1

I found a way simpler solution to my problem than my initial approach. Instead of gathering all file contents first and checking them once I check every line while iterating through it:

:check_xcopy_success
for /f "delims=" %%i in ('type $(Configuration)\$(AssemblyName).log') do (
  ( echo %%i | findstr /i /c:"File not found" > nul ) && ( echo Postbuild: error 1234: Unable to copy lib, see output for more specific information && goto :end )
)
exit /b

I am not entirely sure why this works and my initial approach did not but maybe it help someone in the future.

Spray'n'Pray
  • 190
  • 1
  • 15