2

In my demo project's build event, (a class library project), to copy the build result .dll to a specific folder, (auto-created if it doesn't exist), I added following command line in Post-build event command line section:

xcopy /Y "$(TargetDir)$(TargetFileName)" "$(SolutionDir)DemoApp\bin\$(ConfigurationName)\Packages\"

It works perfectly.

Then I tried to replace that command line with a call to a new batch file called CopyPackage.bat located in $(SolutionDir). The content of the batch file is exactly the command line above:

call $(SolutionDir)CopyPackage.bat

Then I rebuild the project and get following error:

Severity Code Description Project File Line Suppression State Error The command "call C:\TestProjects\DemoApp\CopyPackage.bat" exited with code 4. DemoApp

Do I miss something?


The solution after getting some hints from you all:

In post-build event command line I put: (see the params)

$(SolutionDir)CopyPackage.bat "$(TargetDir)$(TargetFileName)" "$(SolutionDir)DemoApp\bin\$(ConfigurationName)\Packages\"

In batch file CopyPackage.bat :

set targetfile=%~1
set targetdir=%~2
echo %targetfile%
echo %targetdir%
xcopy /Y %targetfile% %targetdir%
MagB
  • 2,131
  • 5
  • 28
  • 54

3 Answers3

3

No need to use call you can simply invoke the batch script directly.

I do have to caution you, since the post-build targets have no way of knowing the inputs and outputs of the task, it will always have to execute the script, even if nothing has changed.

Instead, if you convert this to a msbuild target and you implement the input/output signalling correctly, you'll gain a lot of time by being able to leverage the incremental build features of MsBuild.

For example:

<Target Name="CopyOutputs"
    Inputs="@(BuiltAssemblies)"
    Outputs="@(BuiltAssemblies -> '$(OutputPath)%(Filename)%(Extension)')">

    <Copy
        SourceFiles="@(BuiltAssemblies)"
        DestinationFolder="$(OutputPath)"/>

</Target>

More information on incremental builds and input/output signalling can be found:

jessehouwing
  • 106,458
  • 22
  • 256
  • 341
  • +1 for the MsBuild suggestion, I'll try it out later, too. But MS insist on using 'call' to ensure that all subsequent commands are executed: https://learn.microsoft.com/en-us/visualstudio/ide/how-to-specify-build-events-csharp?view=vs-2019 – S. Kalabukha Nov 27 '20 at 11:59
2

call is an internal command of cmd.exe you should use

cmd.exe /c "$(SolutionDir)CopyPackage.bat"

instead.

Edit:

The content of the batch file is exactly the command line above

VS variables will not be properly resolved inside of the .bat file. You should pass them as parameters to batch file.

montonero
  • 1,363
  • 10
  • 16
  • 1
    or simply `"$(SolutionDir)CopyPackage.bat"` – jessehouwing Mar 13 '19 at 13:49
  • 1
    I think the real answer is on the last line of your answer. The script on the question probably fail because he use an `msbuild` variables in the `bat` file – baruchiro Mar 13 '19 at 21:19
  • 2
    @Baruch I believe that explicit calling of `cmd.exe` will remove any ambiguity. – montonero Mar 14 '19 at 08:12
  • Passing parameter to batch file is the correct way for my demo. For real world operation it is better to use the real build engine script to manage all replacement etc. – MagB Mar 14 '19 at 08:35
  • @MagB Of course there's more than one solution for a post-build file copying, mine was about your specific case. – montonero Mar 14 '19 at 08:39
1

Changing the path in your CopyPackage.bat to absolute path can help resolve this.

Properties like these: $(TargetDir),$(SolutionDir) are recognized by msbuild.exe tool since they are part of msbuild properties and are defined or imported into current environment.

When using xcopy /Y "$(TargetDir)$(TargetFileName)" "$(SolutionDir)DemoApp\bin\$(ConfigurationName)\Packages\" in post-build-event,the msbuild tool can recognize them.So for the first time, it succeeds.

However, for the second time. The msbuild engine can recognize properties in post-build-event, so it calls the .bat successfully. But since the .bat can't recognize the Msbuild property(These properties can only be recognized by MSbuild.exe, not .bat or cmd.exe), the build will fail for not finding the path.

LoLance
  • 25,666
  • 1
  • 39
  • 73
  • Replacing variables with hardcoded paths is a worst possible solution. – montonero Mar 14 '19 at 08:11
  • @montonero Yes, but what you want to know is "Do I miss something?", and I am just want to tell you, the issue results from .bat file can't recognize the msbuild properties. If you want an easy way to do this, keeping the original command in post-build-event could be better. – LoLance Mar 14 '19 at 08:27
  • Your solution is a (very) bad practice. No matter how easy it is. Simple transferring of the project's folder will break it. – montonero Mar 14 '19 at 08:32