0

I have a monorepo with multiple solutions, we can see it simplified like this:

- monorepo
    |- scripts
    |   |- script1.ps
    |- src
        |- projA
        |   |- projA.csproj
        |- projB

In csproj file, I define a post build target to execute a command, from a script located in scripts directory at the root of the monorepo:

   <Target Name="PostBuild" AfterTargets="PostBuildEvent">
     <Exec Command="pwsh -NoProfile -ExecutionPolicy RemoteSigned -Command &quot;
      $root = $(git rev-parse --show-toplevel); 
      $scriptPath = [System.IO.Path]::Combine($root, 'scripts', 'script1.ps1');
      &amp; $scriptPath '$(ProjectDir)$(OutDir)' &quot;" />
   </Target>

It fails complaining about $root is not recognized as a command or executable program but I do not know how to debug this command:

 error MSB3073: The command "pwsh -NoProfile -ExecutionPolicy RemoteSigned -Command "
 error MSB3073:     $root = ; 
 error MSB3073:     $scriptPath = [System.IO.Path]::Combine($root, 'scripts', 'writemanifest.ps1');
 error MSB3073:     & $scriptPath <path> exited with code 255.

I understand variables are not assigned properly, or it does not execute the right command but I have no clue how to fix it. Any help would be appreciated.

7
  • Can you provide more detail about how it "fails miserably"? Is the XML csproj file not well-formed because of the line breaks in the Command attribute? Is the PostBuild target not being invoked by MSBuild? Is the cmd shell created by the Exec task giving an error on the passed Command? Is there an error from PowerShell (pwsh)? Is there an error from git when invoked from PowerShell? Commented Feb 6 at 11:28
  • Could you run manually this command in Command Prompt to see if it works well? You can also add <Message>task in your target to track these variable? Commented Feb 7 at 4:42
  • @JonathanDodds thanks for your comment, I updated the question Commented Feb 7 at 10:37
  • @DouXu-MSFT thanks for your comment, I am sorry I don't know what you are talking about I am new to all this (visual studio, dotnet, c sharp etc I come from Linux background and Python) Commented Feb 7 at 10:38
  • I found a solution after studying msbuild etc and I posted it below... Commented Feb 7 at 14:26

1 Answer 1

0

Instead of complicating the command to execute in the Target Exec, a possible solution is to use features of MSBuild:

<PropertyGroup>
    <!-- Temp var to store Git root dir -->
    <GitRoot>Unknown</GitRoot>
</PropertyGroup>

<Target Name="FindGitRoot" BeforeTargets="PostBuild">
    <!-- Run Git command and capture output -->
    <Exec Command="git rev-parse --show-toplevel" ConsoleToMSBuild="true">
        <Output TaskParameter="ConsoleOutput" PropertyName="GitRoot"/>
    </Exec>
</Target>

<Target Name="PostBuild" AfterTargets="PostBuildEvent" DependsOnTargets="FindGitRoot">
    <!-- <Message Text="Git Root is: $(GitRoot)" Importance="high" /> -->

    <!-- Execute script, located in directory from GitRoot var -->
    <Exec Command='pwsh -NoProfile -ExecutionPolicy Bypass -File 
&quot;$(GitRoot)/scripts/thescript.ps1&quot; 
&quot;$(ProjectDir)$(OutDir)manifest.txt&quot;' />
</Target>
Sign up to request clarification or add additional context in comments.

2 Comments

If you have a solution file (or another known file) in the root, you can use it and the GetDirectoryNameOfFileAbove property function to find the scripts folder. e.g. <PropertyGroup><ScriptsFldr>$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), 'repo.sln'))/scripts</ScriptsFldr></PropertyGroup>. Finding folders and files relative to a known sentinel file is a common MSBuild technique.
Good to know @JonathanDodds

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.