How to get MSBuild Exec to run a java program? - msbuild

I am trying to run a command line action in my Team Build (MSBuild).
When I run it on the command line of the build machine it works fine. But when run in the build script I get a "exited with code 3".
This is command that I am running:
C:\Program Files\Wavelink\Avalanche\PackageBuilder>.\jresdk\bin\java -classpath
"WLUtil.jar;WLPackageBuilder.jar" com.wavelink.buildpkg.AvalanchePackageBuilder
/build PackageName
This command only works when run from the above directory (I have tried running it from c:\ with the full path at it fails).
When I try to run it using ms build this is my statement:
<PropertyGroup>
<!--Working directory of the Package Builder Call-->
<PkgBldWorkingDir>"C:\Program Files\Wavelink\Avalanche\PackageBuilder"</PkgBldWorkingDir>
<!--Command line to run to make Package builder "go"-->
<PkgBldRun>.\jresdk\bin\java" -classpath "WLUtil.jar;WLPackageBuilder.jar" com.wavelink.buildpkg.AvalanchePackageBuilder</PkgBldRun>
</PropertyGroup>
<!--Run package builder command line to update the Ava File.-->
<Exec ContinueOnError="true" WorkingDirectory="$(PackageBuilderWorkingDir)"
Command="$(PkgBldRun) /build PackageName"/>
As I said above this "exits with code 3". This is the full output:
Task "Exec"
Command:
.\jresdk\bin\java -classpath "WLUtil.jar;WLPackageBuilder.jar" com.wavelink.buildpkg.AvalanchePackageBuilder /build PackageName
The system cannot find the path specified.
MSBUILD : warning MSB3073: The command ".\jresdk\bin\java -classpath "WLUtil.jar;WLPackageBuilder.jar" com.wavelink.buildpkg.AvalanchePackageBuilder /build PackageName" exited with code 3.
The previous error was converted to a warning because the task was called with ContinueOnError=true.
Build continuing because "ContinueOnError" on the task "Exec" is set to "true".
Done executing task "Exec" -- FAILED.
It says it can't find the file (who knows what file).
Any ideas on how to make this run a command line action in MS Build?

So... here is the answer.
First my code had a error in it. I defined my working directory as PkgBldWorkingDir but used it as PackageBuilderWorkingDir. That was my first error.
The second one was putting quotes in my working dir property (PkgBldWorkingDir). The " messes that up. Don't pass them in when setting up a working directory. It can handle spaces in a path with out the quotes.

Related

Run MSBuild from Command Line task in Azure Devops

I'm trying to execute msbuild on Azure Devops. Because of that I cannot use the MSBuild task provided.
When I use a Command Line task the command is not recognised. On my local machine I load vcvarsall.bat before I use msbuild. But I've not been unable to work out how to obtain that path in Azure Devops. Doesn't appear to be a Develop Command Prompt task for Azue Devops either.
Any ideas on how I can use msbuild from a Command Line task or Batch Script task? Using their Hosted VS agent.
The best way to do this in a supported way is to use vswhere. The following bit of script will install vswhere (using chocolatey) and then query the installer registry where msbuild can be found. Replace -latest with a more specific version if you need that:
choco install vswhere
for /f "tokens=*" %%i in ('vswhere -latest -requires Microsoft.Component.MSBuild -find MSBuild\**\Bin\MSBuild.exe -nologo') do set msbuildpath="%%i"
echo "##vso[task.setvariable variable=msbuildpath]%msbuildpath%"
This will save the path to msbuild to the environment variable %msbuildpath% as well as the pipeline variable (for this stage) $(msbuildpath).
You can then either use a second run commandline task and pass in $(msbuildpath) or you can simply call MsBuild from the same piece of script mentioned above by calling:
%msbuildpath%
This will make sure your script will remain working, even if Microsoft upgrades their images and moves some things around (which does happen).
You can also get vswhere using wget or invoke-webrequest -outfile from the following location:
https://github.com/Microsoft/vswhere/releases/latest/download/vswhere.exe
Other samples for vswhere syntax can be found on the project wiki, including the syntax for PowerShell.
If you use Hosted Agent 2017 you can run the msbuild.exe from the Command Line task in this way:
Command Line version 1:
Command Line version 2:
Results:
If you are interested in seeing how the built-in Microsoft task resolves the path, all the Azure Devops tasks are provided open-source. These are the path functions you probably care to review.
Here is the solution I came up with using only built-in pipeline tasks which makes the MSBuild bin directory available on the path environment variable.
Create a PowerShell task to generate an MSBuild project to capture and output to a file the variables you are interested in (ex. MSBuildBinPath)
PowerShell script
"<Project DefaultTargets=`"DetectMsBuild`">
<ItemGroup>
<OutFile Include=`"`$(MsBuildDetectionFile)`" />
<OutFile Condition=`"'`$(OutFile)' == ''`" Include=`"msbuildInfo.json`" />
</ItemGroup>
<Target Name=`"DetectMsBuild`">
<PropertyGroup>
<MsBuildPaths>
[{
`"Name`": `"BinPath`",
`"Value`": `"`$(MSBuildBinPath.Replace('\', '\\'))`"
}]
</MsBuildPaths>
</PropertyGroup>
<WriteLinesToFile
File=`"#(Outfile)`"
Lines=`"`$(MsBuildPaths)`"
Overwrite=`"true`"
Encoding=`"UTF-8`" />
</Target>
</Project>" | Out-File -FilePath "msbuilddetect.proj" -Encoding utf8
Set the working directory and any variables accordingly.
PowerShell task settings screenshot:
Create an MSBuild task to run the project file generated by the previous task. Ensure the MSBuild version is set to the version you want to use.
MSBuild task settings screenshot:
Last, create another PowerShell task that will parse the outputted JSON file of the extracted variables and sets environment variables accordingly.
PowerShell script
Write-Host "Current path: $($env.Path)`n`n"
$msBuildVariables = Get-Content -Path msbuildInfo.json | ConvertFrom-Json
$Path = "$($msBuildVariables[0].Value);$($env:Path)"
Write-Host "##vso[task.setvariable variable=Path;]$Path"
PowerShell task settings screenshot:
Here is a screenshot of the task order in the build pipeline.

How to use msbuild command line to create a bundle but exclude test projects

I have a C# solution with VS 2017, containing an app project and a test project. I can use the "create app package" wizard to create one single bundle for x86 and x64. However, I would like to automate this process, which means I need to use msbuild in command line to do the same work.
With the reference from here and here, I got:
msbuild .\MyProject.sln /p:AppxBundle=Always /p:AppxBundlePlatforms="x86|x64" /p:Configuration=Debug
But I will get errors for my test projects, like:
MakeAppx : error : Error info: error 80080204: The package with file name "Tests.XXXX.Shared.Uwp_1.0.0.0_x86_Debug.appx" and package full name "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxxx_1.0.0.0_x86__xxxxxxxxxxx" is not valid in the bundle because it has a different package family name than other packages in the bundle. The expected package name is xxxx-Test.xxxxTestApp....
My guess is that I should not use "Always" for AppxBundle, but I cannot find any document online mentioning how to set this value as "If Needed". I also tried to add "Never" in project properties for the test project, but the command line argument seems to overwrite that.
So my question is: How to exclude a test project from the solution when creating a bundle using msbuild in the command line?
How to exclude a test project from the solution when creating a bundle using msbuild in the command line?
To resolve this issue, you can build the project file directly when you create a bundle using MSBuild in the command line:
msbuild .\YourProjectFile.csproj /p:AppxBundle=Always /p:AppxBundlePlatforms="x86|x64" /p:Configuration=Debug
Alternatively, you can open test project file and add the following properties at the end of the first <PropertyGroup> element to exclude the test project to be included:
<PropertyGroup>
<AppxBundle>Never</AppxBundle>
</PropertyGroup>
Check this thread and the document for some more details.
Hope this helps.

msbuild error MSB4044: The "CheckPathAttributes" task was not given a value for the required parameter "Path"

I'm trying to build a deploy package from a Publish Profile using msbuild. I use the command from https://stackoverflow.com/a/15079260/492336:
msbuild.exe MyProject.csproj /p:DeployOnBuild=true;PublishProfile=MyProfile
But I am getting this error:
C:\Program Files (x86)\MSBuild\Microsoft\VisualStudio\v14.0\Web\Microsoft.Web.Publishing.targets(3683,5): error MSB4044: The "CheckPathAttributes" task was not given a value for the required parameter "Path". [c:\Workspace\MyProject\MyProject.csproj]
How should I go about fixing it?
The reason seems to be related to this line inside my *.pubxml file:
<DesktopBuildPackageLocation>$(SolutionDir)/WebSite1.zip</DesktopBuildPackageLocation>
It works from VisualStudio because $(SolutionDir) is defined there, but it obviously is not defined when I execute msbuild from the command line (maybe it would be defined if I used the solution instead of the csproj file).
Edit: Changing it to $(ProjectDir)/WebSite1.zip works as well.

MSBUILD : error MSB1001: Unknown switch Switch: /Y

I'm using team city to make an automatic deploy and MSBuild won't work...
In the build step the the command line parameters look like this:
ProjectName.deploy.cmd /y /M:https://[WebDeployUrl:8172]/MsDeploy.axd /u:username /p:password –allowUntrusted /A:basic
this works fine from my machine, but the build server fails with the following response:
[MSBuild output] MSBUILD : error MSB1001: Unknown switch.
[MSBuild output] Switch: /Y
Anyone has an idea about this?
This is a very old question, and the asker likely sorted out their issue long ago, but here goes anyways:
MSBuild tasks in TeamCity require a commandline that pertain to MSBuild.exe specifically, IIRC.
That is, TeamCity is executing MSBuild.exe with the parameters you've given it like so:
msbuild.exe ProjectName.deploy.cmd /y /M:https://[WebDeployURL]:8172]/MsDeploy.axd /u:username /p:password -allowUntrusted /A:basic
Of course, MSbuild has no idea what those switches are, nor would it be able to process 'ProjectName.deploy.cmd' as an MSBuild file.

How can I execute programs in my %PATH% with MSBuild?

Note: I'm using Mercurial as an example here, because that's what I'm trying to get to work with MSBuild right now.
But the problem is not limited to Mercurial, it happens with every external program that is somewhere in my %PATH% variable (I tried the same with PowerShell, for example).
So I didn't put the Mercurial tag on this question on purpose, because this is not about Mercurial!
What I actually want to do:
I want my build script to get the current revision number from my Mercurial repository and store it in a file.
The simplest way to do this from the command line is:
hg id -i >rev.txt
Mercurial is installed on my machine and the installation folder is in my %PATH% variable.
So I can run this line from anywhere on my machine (directly from the command line, or from a batch file), and it just works.
The problem occurs when I try to run this line from my build script.
I change the BeforeBuild (or AfterBuild) section of my .csproj file as follows:
<Target Name="AfterBuild">
<Exec Command="hg id -i >rev.txt"/>
</Target>
When I compile my solution with Visual Studio, it works and the rev.txt file is created in the folder where my .csproj is.
But when I compile the exact same solution from the command line with MSBuild, the build fails with the following error message:
The command "hg id -i >rev.txt" exited with code 9009.
I googled "msbuild code 9009" and found some solutions, but all of them propose to provide the full path to the executable.
When I do this, the build succeeds with MSBuild as well.
But this is not an acceptable solution for me, because I can't be sure that everyone using my project (including the build server) has installed Mercurial in the exact same folder.
That's exactly what %PATH% is for...
The same happens when I put the <Exec Command="... line directly into the build script.
If I specify the path to the executable, it works.
If I don't specify the path, it doesn't.
Is there any trick to make MSBuild execute programs in my %PATH% variable without specifying the complete folder?
EDIT:
#leppie:
Output redirection:
You mean the fact that I save the output of my command in a text file inside the command , instead of just running hg id -i as a command and using an output parameter or something like that to get the output?
Doesn't make any difference...the error is the same when I omit >rev.txt.
Command line args:
No, it throws the same error, even if I shorten the command to just hg (without any parameters).
Don't forget: if I run the exact same Exec command in the exact same .csproj file from Visual Studio, or if I just provide the path to the .exe file in the command, everything works.
So IMO output redirection and command line args can't be the problem.
Have you tried this extension pack for mercurial/msbuild?
http://msbuildhg.codeplex.com/documentation
Seems to have a task for returning revision id, which is what your trying to achieve no?
<HgVersion LocalPath="$(MSBuildProjectDirectory)" Timeout="5000">
<Output TaskParameter="Revision" PropertyName="AssemblyRevision" />
</HgVersion>
Okay, I found the solution.
I have to admit, it was a classic case of PEBKAC :-)
I'll explain it anyway, maybe it will help someone who made the same mistake:
Basically everything I have tried (plus what James Woolfenden suggested in his answer) would have been worked...if only the batch file that I use to run the build script wouldn't have looked like this:
path="%windir%\Microsoft.net\Framework\v4.0.30319"
msbuild build.proj
Yes, exactly.
I'm editing the %PATH% variable for the duration of this batch file, and I'm overwriting it with the path to MSBuild instead of just appending it.
So when my build script tries to call Mercurial, it can't find it anymore because its location is not in the %PATH% variable anymore.
No idea why I didn't see this before.
The correct way would be to append the MSBuild path, leaving the other paths intact:
path=%path%;%windir%\Microsoft.net\Framework\v4.0.30319