Update Xml File (vsixmanifest) - xpath

I'm creating a Visual Studio 2013 Package (vsix) (shameless plug: pMixins ). As part of my quest to use TeamCity as a continuous integration server, I have configured Team City to build the .vsix Package (Visual Studio Package (vsix) - Team City without Visual Studio installed).
Now I want to configure Team City to set the Version in the VSIX Schema:
<?xml version="1.0" encoding="utf-8"?>
<PackageManifest
Version="2.0.0"
xmlns="http://schemas.microsoft.com/developer/vsx-schema/2011"
xmlns:d="http://schemas.microsoft.com/developer/vsx-schema-design/2011">
<Metadata>
<Identity Version="1.0" Language="en-US" Publisher="Company" />
Following the advice in Using msbuild I want to update a config file with values from teamcity and How do I update an XML attribute from an MSBuild script? I have updated Microsoft.VsSDK.targets to use XmlPoke with the following Target:
<Target
Name="UpdateVSIXVersion"
BeforeTargets="PrepareForBuild"
Condition="$(VSIXVersion) != '' And $(VSIXVersion) != '*Undefined*'">
<Message Text= "Updating VSIX Version" />
<XmlPoke
XmlInputPath="source.extension.vsixmanifest"
Query="/PackageManifest/Metadata/Identity/#Version"
Value="$(VSIXVersion)">
</XmlPoke>
</Target>
I updated Team City with a system Parameter to set VSIXVersion:
But, when I check TeamCity, it made 0 replacements:
How do I get Team City to correctly update the .vsixmanifest xml?

After much searching I finally found the XmlPoke expects a namespace when the Xml file contains a namespace, even for the default namespace (Modifying .config File in an MSBuild Project).
However, I couldn't find any documentation for the XmlPoke.Namespaces parameter and the above referenced code didn't work. After much trial an error, I finally got it to work with this:
<Target
Name="UpdateVSIXVersion"
BeforeTargets="PrepareForBuild"
Condition="$(VSIXVersion) != '' And $(VSIXVersion) != '*Undefined*'">
<Message Text= "Updating VSIX Version" />
<XmlPoke
XmlInputPath="source.extension.vsixmanifest"
Query="/n:PackageManifest/n:Metadata/n:Identity/#Version"
Value="$(VSIXVersion)"
Namespaces="<Namespace Prefix='n' Uri='http://schemas.microsoft.com/developer/vsx-schema/2011' Name='DoNotKnowWhatThisIsFor-ButItIsRequired' />">
</XmlPoke>
Notes:
This requires MSBuild 12 to be configured on Team City
The Namespaces needs to be escaped.
The Name parameter is required, otherwise MSBuild will error out
The original XPath query had to be updated with the artificial namespace prefix.
MSBuild file is on Github if anyone needs it: https://github.com/ppittle/pMixins/blob/master/tools/vssdk_tools/v12.0/VSSDK/Microsoft.VsSDK.targets

Related

Visual Studio 2017 not loading AjaxMin MSBuild Task from specified path

I'm attempting update an existing application so that it will load in Visual Studio 2017 (Enterprise - V15.2 (26430.12)) from Visual Studio 2015 (Enterprise) and having issues with the AjaxMin build task.
In Visual Studio 2015, the AjaxMin build task is found in C:\Program Files (x86)\MSBuild\Microsoft\MicrosoftAjax. Visual Studio 2017 looks for it in C:\Program Files (x86)\Microsoft Visual Studio\2017\Enterprise\MSBuild\Microsoft. Given that all developers on the team may not have VS2017 Enterprise and we've had issues in the past with developers installing the wrong version, I'd like to have it use the AjaxMin NuGet package referenced in the solution.
There are 3 projects in the solution that use the AjaxMin task. I've updated all of them to have the following import:
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="12.0">
...
<Import Project="$(MSBuildProjectDirectory)\..\..\..\packages\AjaxMin.5.14.5506.26202\tools\net40\AjaxMin.targets" />
<Target Name="BeforeBuild">
<ItemGroup>
<JS Include="..." Exclude="..." />
</ItemGroup>
<ItemGroup>
<CSS Include="..." Exclude="..." />
</ItemGroup>
<AjaxMin Switches="..." JsSourceFiles="#(JS)" JsCombinedFileName="..." CssSourceFiles="#(CSS)" CssCombinedFileName="..." />
</Target>
...
</Project>
However, when the build happens, I receive an error saying it can't find the AjaxMin task in the default build extensions directory:
The "AjaxMin" task could not be loaded from the assembly C:\Program
Files (x86)\Microsoft Visual
Studio\2017\Enterprise\MSBuild\Microsoft\MicrosoftAjax\AjaxMinTask.dll.
Could not load file or assembly 'file:///C:\Program Files
(x86)\Microsoft Visual
Studio\2017\Enterprise\MSBuild\Microsoft\MicrosoftAjax\AjaxMinTask.dll'
or one of its dependencies. The system cannot find the file specified.
Confirm that the declaration is correct, that the assembly
and all its dependencies are available, and that the task contains a
public class that implements Microsoft.Build.Framework.ITask.
I've used the MSBuild Message Task to output the path and verified that it is correct by navigating to it from the command prompt. I also tried using the UsingTask with no luck there.
Why is Visual Studio not looking for the AjaxMin DLL in the location I specified?
Update:
I moved the import tag for AjaxMin to the top (right under the project tag) and it works now. I don't understand why.
I resolved this issue by installing the .Net 3.5 framework
The issue turned out being another import for another third party build task. It appears that build task alters the build process such that the AjaxMin build task won't work after it. Having the AjaxMin build task after the Microsoft.CSharp.Targets import but before the other third party build task did the trick.
I moved the import tag for AjaxMin to the top (right under the project tag) and it works now. I don't understand why.
If I understand your question correctly, that is because you have two reference sources for the AjaxMinTask.dll, one is the default assembly source:C:\Program Files (x86)\Microsoft Visual Studio\2017\Enterprise\MSBuild\Microsoft\MicrosoftAjax, another is the import reference, you will notice that the AjaxMinTask.dll is used in the AjaxMin.targets:
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<UsingTask AssemblyFile="AjaxMinTask.dll" TaskName="AjaxMin" />
<UsingTask AssemblyFile="AjaxMinTask.dll" TaskName="AjaxMinBundleTask" />
<UsingTask AssemblyFile="AjaxMinTask.dll" TaskName="AjaxMinManifestTask" />
<UsingTask AssemblyFile="AjaxMinTask.dll" TaskName="AjaxMinManifestCleanTask" />
...
</Project>
So when set the import reference behind your task, MSBuild will use the default assembly source (under the VS2017 installation directory), when you set the import reference before you task, the AjaxMin.targets will rewrite the path of reference source.

How to build wix toolset project?

I've installed Wix Toolset 3.11.0.1528 and extension for VS 2015 0.9.17.13693
After pressing build I get:
The WiX Toolset v4 build tools must be installed to build this project. To download WiX Toolset v4 visit ...
I don't get it. I have version 3.11 installed and it wants v4. I don't want to build anything from source.
What should I do to make it use available WiX version?
Bit of a necro post but if anyone finds it helpful, well then, good.
Edit the XML as pointed out above by replacing the namespace from v4 to the v3 one.
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi"/>
Then edit the proj file of your setup and remove the reference to the WIX target path.
<WixTargetsPath Condition=" '$(WixTargetsPath)' == '' ">$(MSBuildExtensionsPath)\WiX Toolset\v4\wix.targets</WixTargetsPath>
Finally, replace the import and target tags with the 3.11 version of the code.
<Import Project="$(WixTargetsPath)" Condition=" '$(WixTargetsPath)' != '' " />
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\WiX\v3.x\Wix.targets" Condition=" '$(WixTargetsPath)' == '' AND Exists('$(MSBuildExtensionsPath32)\Microsoft\WiX\v3.x\Wix.targets') " />
<Target Name="EnsureWixToolsetInstalled" Condition=" '$(WixTargetsImported)' != 'true' ">
<Error Text="The WiX Toolset v3.11 (or newer) build tools must be installed to build this project. To download the WiX Toolset, see http://wixtoolset.org/releases/" />
</Target>
Ah. Ok. At VS project manager (or whatever they call it), when you add New project, you have two almost identical choices:
Setup project - A project for creating an MSI file
Setup project - A project fro creating a WiX based XML MSI file
So the first one uses <Wix xmlns="http://schemas.microsoft.com/wix/2006/wi" ...
And the second one: <Wix xmlns="http://wixtoolset.org/schemas/v4/wxs" ...
The second one fails. And just changing this url doesn't help.
Choose the first variant and just use it.

UWP .appx file naming

I am building an UWP app and I want to have generated package to be named with the build number in order to distinguish the builds.
So far, I have this configuration in the csproj file:
<Target Name="BeforeBuild">
<Message Text="Updating AssemblyInfo to Version $(VersionNumber)"></Message>
<Message Text="Writing to AssemblyInfo files in $(SolutionRoot)"></Message>
<AssemblyInfo CodeLanguage="CS"
AssemblyCompany="Company"
AssemblyProduct="Product"
AssemblyCopyright="Copyright © Company 2011"
ComVisible="true"
AssemblyVersion="$(BUILD_NUMBER)"
AssemblyFileVersion="$(BUILD_NUMBER)" />
</Target>
All good, I can run the msbuild with the /p:BUILD_NUMBER=1.2.3.4 argument, but this is only reflecting in AssemblyInfo.cs file.
The .appx file will be named as MyApplication.Core_1.0.0.0_x86_Test.appx and not MyApplication.Core_1.2.3.4_x86_Test.appx
How can I use the BUILD_NUMBER information to be reflected in the .appx file name?
The version number in .appx file name is not set by AssemblyInfo. This version number is called Package version number which is set as a value in the Version attribute of the Package/Identity element in the app manifest like:
<Package xmlns="http://schemas.microsoft.com/appx/manifest/foundation/windows10" xmlns:mp="http://schemas.microsoft.com/appx/2014/phone/manifest" xmlns:uap="http://schemas.microsoft.com/appx/manifest/uap/windows10" IgnorableNamespaces="uap mp">
<Identity Name="e12578ad-9b81-44bb-8651-0b58e44e71b8" Publisher="CN=Jay Zuo" Version="1.2.3.0" />
...
</Package>
Once you changed the Version attribute and then run MSBuild, you will get the .appx file named like MyUWPApp_1.2.3.0_x86.appx.
Besides this, we usually change the package version number while creating an app package. This can be done with Microsoft Visual Studio wizard like following:
(source: s-msft.com)

How do I use msbuild in Visual Studio's post build event?

I'm trying to configure the YUICompressor.NET in my Visual Studio project.
As I've understood, I have to create a .proj file and add it to my solution. After that, I need to create a post-build event that will build this .proj file and I'll get my desired output (minified js/css files).
So, I have:
This .proj contains:
<?xml version="1.0" encoding="utf-8"?>
<Project xmlns="http://schemas.microsoft.com/developer/MsBuild/2003">
<UsingTask TaskName="CssCompressorTask" AssemblyFile="\..\packages\YUICompressor.NET.MSBuild.2.7.0.0\lib\NET20\Yahoo.Yui.Compressor.Build.MsBuild.dll" />
<UsingTask TaskName="JavaScriptCompressorTask" AssemblyFile="\..\packages\YUICompressor.NET.MSBuild.2.7.0.0\lib\NET20\Yahoo.Yui.Compressor.Build.MsBuild.dll" />
<Target Name="Minify">
<ItemGroup>
<!-- Single files, listed in order of dependency -->
<CssFiles Include="Content\*.css"/>
<JavaScriptFiles Include="Scripts\*.js"/>
</ItemGroup>
<CssCompressorTask
SourceFiles="#(CssFiles)"
OutputFile="Content\min.css"
/>
<JavaScriptCompressorTask
SourceFiles="#(JavaScriptFiles)"
OutputFile="Scripts\min.js"
/>
</Target>
</Project>
I'm trying to build it as the following:
I'm getting the following error:
The command "msbuild C:\Users\Me\Desktop\MvcApplicationExample\MvcApplicationExample\YuiCompressorMsBuild.proj" exited with code 9009.
This error suggests that "msbuild" is not a valid command. So, how should I build this type of project? (I've followed this tutorial: youtube)
Thanks for any help.
As you said maybe the visual studio cannot find the MSBuild command, try with the following command instead
"$(MSBuildBinPath)\msbuild.exe"
That uses the complete path to msbuild.
Update (For futures references)
As the comment by Steve Medley, you should not forget the encapsulating quotes.
vfabre is correct to use $(MSBuildBinPath)\msbuild.exe but missing one thing. you should encapsulate that in quotes as there will 99.99% of the time be a space in the file path to msbuild
Well, one thing that might be a problem is that you want it as a Post-build event but it's set for the Pre-build command line.

Build doesn't work from VisualStudio, but is ok from msbuild

From a brand new console application template in visual studio, I edited the .csproj to build another project like this:
...
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<Target Name="BeforeBuild">
<MSBuild Projects=".\other.mproj"/>
</Target>
...
Where other.mproj is:
<?xml version="1.0" encoding="utf-8"?>
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003" DefaultTargets="Build">
<Target Name="Build">
<Message Text="kikou" />
</Target>
</Project>
After a while I discovered that modifying the content of other.mproj (for instance, by introducing errors or changing text kikou to something else) would not be taken into account unless unloading/reloading the project in visual studio.
Building from the command line with 'msbuild myproj.csproj' immediatly detect changes in 'other.mproj'. So it all looks like visual studio is working from a cached version of other.mproj file.
Why is visual studio caching this other script (which is even not included to the project), and how can I solve this issue ?
Update: I also tried this UseHostCompilerIfAvailable, it doesn't work.
NB1: I didn't add other.mproj as a project reference in the .csproj because it is not a .NET project at all (it just creates resources files for the .csproj from other inputs before the build)
NB2: I'm using VS2010 (10.0.10219.1SP1Rel + MSBuild 4.0.30319.1)
Visual Studio caches all MSBuild files, this is done for performance reasons. You will not be able to have an MSBuild only way around this. It may be possible to achieve this via a VS add-in but I'm not 100% sure of that.

Resources