Visual Studio 2017 extension - VSToolsPath not working - visual-studio

I'm updating an old Visual Studio extension for VS 2017. It compiles fine from Visual Studio and msbuild in debug and release on my local computer.
This is the msbuild command line I am using:
msbuild VxCop.sln /p:ToolsHome=C:\ProgramData\chocolatey\bin /p:Configuration=Release /p:Platform="Any CPU"
However, on the build machine (TFS Build 2010) calling msbuild.exe with the same command line it fails with this error
In order to fix this I am trying to specify VSToolsPath. I've tried various things such as altering the VSToolsPath entry in the .csproj (which seems to not be taken into account since doing this had no effect) and also passing it on the command line:
msbuild VxCop.sln /p:ToolsHome=C:\ProgramData\chocolatey\bin /p:Configuration=Release /p:Platform="Any CPU" /p:VSToolsPath=Packages\Microsoft.VSSDK.BuildTools.15.1.192\tools\
This causes a very strange error:
CopyFilesToOutputDirectory:
Copying file from "obj\Release\SymCop.dll" to "bin\Release\SymCop.dll".
SymCop -> H:\src\tools\VisualStudioExtensions\Main\VxCop\source\SymCop\bin\Release\SymCop.dll
Copying file from "obj\Release\SymCop.pdb" to "bin\Release\SymCop.pdb".
Done Building Project "H:\src\tools\VisualStudioExtensions\Main\VxCop\source\SymCop\SymCop.csproj" (default targets).
Done Building Project "H:\src\tools\VisualStudioExtensions\Main\VxCop\VxCop.sln" (Build target(s)) -- FAILED.
Done Building Project "H:\src\tools\VisualStudioExtensions\Main\VxCop\build.proj" (default targets) -- FAILED.
Build FAILED.
0 Warning(s)
0 Error(s)
The actual extension project isn't appearing in the log at all, and there's no, y'know, errors. But the build returns as failed, the return code is non-zero, and the vsix project seems to not be built (its output is missing)
Hopefully someone has some suggestions
Thanks
Edit:
For those reading this in the future, the problem seemed to be that there was an <Import> further down in the same file which didn't care about my update to $(VSToolsPath).
Changing that import fixed it:
<Import Project="$(SolutionDir)\packages\Microsoft.VSSDK.BuildTools.15.1.192\tools\VSSDK\Microsoft.VsSDK.targets"
/>

Visual Studio 2017 extension - VSToolsPath not working
I got the same result as you based on your scripts. After installed the NuGet package Microsoft.VSSDK.BuildTools to the project, the Microsoft.VSSDK.BuildTools.props will be imported in to project file, open the project file, you can find below Import:
<Import Project="..\packages\Microsoft.VSSDK.BuildTools.15.1.192\build\Microsoft.VSSDK.BuildTools.props" Condition="Exists('..\packages\Microsoft.VSSDK.BuildTools.15.1.192\build\Microsoft.VSSDK.BuildTools.props')" />
Then open this props file, you can notice below scripts snippet:
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup Label="VSSDK_NuGet_Configuration">
<ThisPackageDirectory>$(MSBuildThisFileDirectory)..\</ThisPackageDirectory>
<VSToolsPath>$(ThisPackageDirectory)\tools</VSToolsPath>
<VsSDKInstall>$(VSToolsPath)\VSSDK</VsSDKInstall>
<VsSDKIncludes>$(VsSDKInstall)\inc</VsSDKIncludes>
<VsSDKToolsPath>$(VsSDKInstall)\bin</VsSDKToolsPath>
</PropertyGroup>
</Project>
In this case, NuGet package override the value VSToolsPath with $(ThisPackageDirectory)\tools. So MSBuild will skip set the value setting in the next step in the project file:
<PropertyGroup>
<MinimumVisualStudioVersion>15.0</MinimumVisualStudioVersion>
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
<NuGetPackageImportStamp>
</NuGetPackageImportStamp>
</PropertyGroup>
Because NuGet have already set the value $(VSToolsPath), the value of Condition="'$(VSToolsPath)' == ''" would be False. In addition, you can add a target to check if the value is set, like:
<Target Name="CheckVSToolsPath" BeforeTargets="Build">
<Message Text="$(VSToolsPath)"></Message>
</Target>
You will find this value is set to:
C:\Users\Admin\Documents\Visual Studio 2017\Projects\VSIXProject2\packages\Microsoft.VSSDK.BuildTools.15.1.192\build\..\\tools
Summary above, the value of VSToolsPath was imported correctly, we do not need to passing it on the command line.
After in-depth investigation, I found the reason for the previous error "MSB4226: The imported project "(...)\VSSDK\Microsoft.VsSDK.targets" was not found." is that the MSBuild property of "VisualStudioVersion" not be set on the build server.
See below link for detail info Building a VSIX extension with the Visual Studio 2017 Build Tools:
something that a machine with the full Visual Studio 2017 does and that a machine with the Build Tools 2017 does if you open a developer command prompt. Since I was not using it, I passed it as a parameter to the MSBuild script. It can be defined too inside the .csproj file, something that previous Visual Studio versions did automatically but recent versions don’t.
So to resolve the error "MSBuild4226", you should pass the visual studio version on command line:
msbuild VxCop.sln /p:ToolsHome=C:\ProgramData\chocolatey\bin /p:Configuration=Release /p:Platform="Any CPU" /p:VisualStudioVersion=15.0
After using this command line, the error MSBuild 4226 was resolved.
Hope this helps.

I resolved this problem in VS 2019 by https://learn.microsoft.com/en-us/nuget/consume-packages/package-references-in-project-files#generatepathproperty
<ItemGroup>
<PackageReference Include="Microsoft.VSSDK.BuildTools" Version="16.10.1055">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
</ItemGroup>
<Import Project="$(PkgMicrosoft_VSSDK_BuildTools)\tools\vssdk\Microsoft.VsSDK.targets" />

Related

Visual Studio New project wont run tests

Visual Studio 2019 is not detecting or discovering NUNit nor MSTest unit tests at all. I installed it fresh just a week ago. The MS guide here https://learn.microsoft.com/en-us/visualstudio/test/getting-started-with-unit-testing?view=vs-2019&tabs=mstest does not work.
A few threads hold possible solutions, but none that I've tried helped have helped. I'm new to C# so much of the steps have taken a long time to figure out, but while my application is progressing nicely I really want to work and learn in a TDD style.
Even if a create a new blank MSTest project, with no application code or libs in the solution at all, the example/template project does not work, so I'm missing something big someplace. (I have .NET Core SDKs installed - my intent is to target macOS and linux at a future point.)
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netcoreapp3.1</TargetFramework>
<IsPackable>false</IsPackable>
<LangVersion>latest</LangVersion>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="nunit" Version="3.13.0" />
<PackageReference Include="NUnit3TestAdapter" Version="3.17.0" />
</ItemGroup>
</Project>
Threads I have tried: Tests not running in Test Explorer Why will Visual Studio 2019 will not run my unit tests? Visual Studio 2019 Test Explorer puts all tests under "Not Run Tests"
If I create a project targeting .NET 4.7 all is good, it's when I want to target Core that I'm unstuck, if that helps.
Stuck again
I had to install a component called "NUnit 3", https://marketplace.visualstudio.com/items?itemName=NUnitDevelopers.NUnitTemplatesforVisualStudio worked for a moment... but when I added a testcase, it all broke again.
Did the nuget package updates, still not working.
I cloned. from git this project https://github.com/dotnet/samples/tree/master/core/getting-started/unit-testing-using-nunit
And it does not work either.
I then re-installed 2019, and emailed my project to a friend, who merely removed the nunit nuget modules, added them back and then it worked for him, but the project he sent me back did not work. Module versions unchanged
I opened the same project in the Microsoft developer VM/iso image and the project works just fine. so it's my environment that is incompatible with nunit somehow. Is there a way to see some traces?
Changed the installation drive from D: to C: I get this error now
Testhost process exited with error: A fatal error occurred, the required library hostfxr.dll could not be found.
If this is a self-contained application, that library should exist in [C:\Users\zapho\src\c#\tutorials\working\ConsoleApp1\ConsoleApp1\NUnit.Tests2\bin\Debug\netcoreapp3.1\].
If this is a framework-dependent application, install the runtime in the default location [C:\Program Files\dotnet] or use the DOTNET_ROOT environment variable to specify the runtime location.
. Please check the diagnostic logs for more information.
Testhost process exited with error: A fatal error occurred, the required library hostfxr.dll could not be found.
If this is a self-contained application, that library should exist in [C:\Users\zapho\src\c#\tutorials\working\ConsoleApp1\ConsoleApp1\NUnit.Tests2\bin\Debug\netcoreapp3.1\].
If this is a framework-dependent application, install the runtime in the default location [C:\Program Files\dotnet] or use the DOTNET_ROOT environment variable to specify the runtime location.
. Please check the diagnostic logs for more information.
You need to add the Microsoft.NET.Test.Sdk NuGet package to your solution to run tests in Visual Studio.
Modify your project file,
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netcoreapp3.1</TargetFramework>
<IsPackable>false</IsPackable>
<LangVersion>latest</LangVersion>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="nunit" Version="3.13.0" />
<PackageReference Include="NUnit3TestAdapter" Version="3.17.0" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.9.1" />
</ItemGroup>
</Project>
Fixed it by eventually setting environment variable
DOTNET_ROOT=D:\Program Files\dotnet\
as per an answer
https://stackoverflow.com/a/61453119/337598

Visual Studio 2017 MSBuild issue

I am trying to publish a Visual stuido Project from another Project, to do this I have created a bat file which runs my MSBuild file. If you run this outside of Visual Studio it works correctly but when i tried to add it to Visual Studio's prebuild scripts it does not publish. I am getting this warning -
C:\Program Files (x86)\MSBuild\14.0\bin\Microsoft.Common.CurrentVersion.targets(1820,5): warning MSB3247: Found confl
icts between different versions of the same dependent assembly. In Visual Studio, double-click this warning (or select
it and press Enter) to fix the conflicts; otherwise, add the following binding redirects to the "runtime" node in the a
pplication configuration file
My MSBuild file:
<Target Name="BeforeBuild">
<MSBuild
Projects="E:\Development\alyz\myAPI\View.API.sln"
Targets="View_API_Search"
Properties="DeployOnBuild=true;Configuration=Release;PublishProfile=InstallerPublish;WebPublishMethod=FileSystem;PublishURL=E:\Temp\installertemp\SearchAPI" />
</Target>
Visual Studio is saying that my project has built correctly but i can't work out why it's not publishing, any ideas?
Visual Studio is saying that my project has built correctly but i can't work out why it's not publishing, any ideas?
You can use another solution for this issue. Following is my publish target, you can check it:
<Target Name="BeforeBuild">
<Exec Command=""<YourMSBuild.exePath>\msbuild.exe" "<YourSolutionPath>\View.API.sln" /p:DeployOnBuild=true /p:PublishProfile=InstallerPublish.pubxml /p:Configuration=Release /p:PublishURL=E:\Temp\installertemp\SearchAPI"></Exec>
</Target>
With this target, the project/solution will be build and published when you build the project.
Hope this helps.

MSBuild 15 WebApplication.targets is missing

I am working with a web application that was written using VS2015, and is being maintained using VS2017. I am trying to write another application to build the full web stack locally using the MSBuild API and other tools. In VS2015 or VS2017 the ASP.NET Web Application project will build successfully, but when running MSBuild programmatically, I keep getting this error:
The imported project "C:\Program Files (x86)\MSBuild\Microsoft\VisualStudio\v15.0\WebApplications\Microsoft.WebApplication.targets" was not found. Confirm that the path in the declaration is correct, and that the file exists on disk.
I have the following build packages installed in my app:
Microsoft.Build
Microsoft.Build.Framework
Microsoft.Build.Tasks.Core
Microsoft.Build.Utilities.Core
The standard advice I've seen in forums for this error is to install Visual Studio on the build server, but I am doing this locally and I do have Visual Studio installed. I've also read that MSBuild 15 does not come with the WebApplication.targets file. There is also a toolsVersion parameter on the constructor for Microsoft.Build.Execution.BuildRequestData that I've tried setting manually to 14.0 but it still seems like my app is trying to use MSBuild 15. (I do have MSBuild 14 installed.)
Questions:
Can I make this build run in MSBuild 14 programmatically without updating any csproj files?
Where can I get WebApplication.targets for MSBuild 15?
Solution:
Thanks in large part to #Leo-MSFT I was able to get this working. Here's how:
Uninstalled the VS2017 ASP.NET and Web Application Development workload, then reinstalled with all of its optional components. This downloaded the missing .targets file.
In my builder application, added this property to my instance of BuildRequestData to make MSBuild look in the folders used by v15, rather than using the folders used by v14.
["MSBuildExtensionsPath32"] =
"C:\Program Files (x86)\Microsoft Visual Studio\2017\Professional\MSBuild"
Can I make this build run in MSBuild 14 programmatically without updating any csproj files?
MSBuildExtensionsPath32 is set internally by MSBuild. If you do not want update you .csproj file, you can try to override the value in your project file:
<PropertyGroup>
<MSBuildExtensionsPath32>C:\Program Files (x86)\Microsoft Visual Studio\2017\Enterprise\MSBuild</MSBuildExtensionsPath32>
</PropertyGroup>
<PropertyGroup>
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">10.0</VisualStudioVersion>
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
</PropertyGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<Import Project="$(VSToolsPath)\WebApplications\Microsoft.WebApplication.targets" Condition="'$(VSToolsPath)' != ''" />
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v10.0\WebApplications\Microsoft.WebApplication.targets" Condition="false" />
But I'm not sure if it will introduce other error(Not tested).
Where can I get WebApplication.targets for MSBuild 15?
The path of WebApplication.targets for MSBuild 15 is:
C:\Program Files (x86)\Microsoft Visual Studio\2017\Enterprise\MSBuild\Microsoft\VisualStudio\v15.0\WebApplications

How to set PlatformToolset property from MSbuild?

We are experiencing AppVeyor x64 build failures, and trying a suggestion to set PlatformToolset to DefaultPlatformToolset. The property value is undocumented, so we want to thoroughly test it.
We wired DefaultPlatformToolset into our AppVeyor configuration file:
test_script:
- cmd: >-
msbuild /t:Build /p:PlatformToolset=DefaultPlatformToolset cryptlib.vcxproj
msbuild /t:Build /p:PlatformToolset=DefaultPlatformToolset cryptest.vcxproj
msbuild /t:CopyCryptestToRoot /p:PlatformToolset=DefaultPlatformToolset cryptest.vcxproj
cryptest.exe v
cryptest.exe tv all
The value DefaultPlatformToolset is causing AppVeyor failures. Here's from the log where we believe everything is correct: Build 1.0.129:
msbuild /t:Build /p:PlatformToolset=DefaultPlatformToolset cryptlib.vcxproj
Microsoft (R) Build Engine version 14.0.25420.1
Copyright (C) Microsoft Corporation. All rights reserved.
Build started 8/2/2017 5:14:24 AM.
The target "_ConvertPdbFiles" listed in a BeforeTargets attribute at "C:\Program Files (x86)\MSBuild\14.0\Microsoft.Common.targets\ImportAfter\Xamarin.Common.targets (45,37)" does not exist in the project, and will be ignored.
The target "_CollectPdbFiles" listed in an AfterTargets attribute at "C:\Program Files (x86)\MSBuild\14.0\Microsoft.Common.targets\ImportAfter\Xamarin.Common.targets (45,70)" does not exist in the project, and will be ignored.
The target "_CollectMdbFiles" listed in a BeforeTargets attribute at "C:\Program Files (x86)\MSBuild\14.0\Microsoft.Common.targets\ImportAfter\Xamarin.Common.targets (52,38)" does not exist in the project, and will be ignored.
The target "_CopyMdbFiles" listed in an AfterTargets attribute at "C:\Program Files (x86)\MSBuild\14.0\Microsoft.Common.targets\ImportAfter\Xamarin.Common.targets (52,71)" does not exist in the project, and will be ignored.
Project "C:\projects\cryptopp\cryptlib.vcxproj" on node 1 (Build target(s)).
C:\Program Files (x86)\MSBuild\Microsoft.Cpp\v4.0\V140\Microsoft.Cpp.Platform.targets(57,5): error MSB8020: The build tools for DefaultPlatformToolset (Platform Toolset = 'DefaultPlatformToolset') cannot be found. To build using the DefaultPlatformToolset build tools, please install DefaultPlatformToolset build tools. Alternatively, you may upgrade to the current Visual Studio tools by selecting the Project menu or right-click the solution, and then selecting "Retarget solution". [C:\projects\cryptopp\cryptlib.vcxproj]
Done Building Project "C:\projects\cryptopp\cryptlib.vcxproj" (Build target(s)) -- FAILED.
Build FAILED.
How do we set PlatformToolset on the command line when using MSbuild to build the project?
None of these work. They produce similar errors as above.
> msbuild /t:Build /p:PlatformToolset=DefaultPlatformToolset cryptlib.vcxproj
> msbuild /t:Build /p:PlatformToolset=$(DefaultPlatformToolset) cryptlib.vcxproj
> msbuild /t:Build /p:PlatformToolset="$(DefaultPlatformToolset)" cryptlib.vcxproj
> msbuild /t:Build /p:PlatformToolset='$(DefaultPlatformToolset)' cryptlib.vcxproj
Here's another error when trying to do that silly MS XML quoting:
>msbuild /t:Build /p:PlatformToolset="$(DefaultPlatformToolset)" cryptlib.vcxproj
Microsoft (R) Build Engine version 4.6.1087.0
[Microsoft .NET Framework, version 4.0.30319.42000]
Copyright (C) Microsoft Corporation. All rights reserved.
MSBUILD : error MSB1011: Specify which project or solution file to use because t
his folder contains more than one project or solution file.
'#34' is not recognized as an internal or external command,
operable program or batch file.
'#34' is not recognized as an internal or external command,
operable program or batch file.
And then there's this one:
> msbuild /t:Build /p:PlatformToolset=""$(DefaultPlatformToolset)"" cryptlib.vcxproj
Microsoft (R) Build Engine version 4.6.1087.0
[Microsoft .NET Framework, version 4.0.30319.42000]
Copyright (C) Microsoft Corporation. All rights reserved.
Build started 8/2/2017 2:19:15 AM.
Project "c:\Users\Test\cryptlib.vcxproj" on node 1 (Build target(s)).
C:\Program Files (x86)\MSBuild\Microsoft.Cpp\v4.0\V110\Microsoft.Cpp.Platform.p
rops(15,24): error MSB4115: The "exists" function only accepts a scalar value,
but its argument "$(VCTargetsPath)\Platforms\$(Platform)\PlatformToolsets\$(Pla
tformToolset)\Microsoft.Cpp.$(Platform).$(PlatformToolset).props" evaluates to
"C:\Program Files (x86)\MSBuild\Microsoft.Cpp\v4.0\V110\\Platforms\x64\Platform
Toolsets\"$(DefaultPlatformToolset)"\Microsoft.Cpp.x64."$(DefaultPl
atformToolset)".props" which is not a scalar value.
Regarding the error message's suggestion ... or right-click the solution, and then selecting "Retarget solution", we can't. This is remote, command line only. We are trying to figure out how to run VCUpgrade from the command line at How to run VCUpgrade before Appveyor build?
DefaultPlatformToolset is an MSBuild property which gets set in one of the platform .props files imported by the main project. At one point in a C++ project file there should be the line
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
which for instance for VS2017 ends up importing <msbuild installation>\Microsoft.Cpp\v4.0\V140\Microsoft.Cpp.Default.props in turn, which sets the property using
<DefaultPlatformToolset>v140</DefaultPlatformToolset>
Since this is an msbuild property it is not known by Appveyor nor by cmd and as such you cannot reference it directly from within appveyor.yml. And even if it were known, you cannot refer to it using $(DefaultPlatformToolset) which is msbuild property expansion syntax whereas cmd's is of the form %ABC%. The errors you get are all because the PlatformToolset property gets set to e.g. the string 'DefaultPlatformToolset' whereas it needs to be set to the name of an actual available platform like v110 or v140 or v120_xp or ...
If you want to use DefaultPlatformToolset the easiest way is entering it in the project file. It can still be overriden from the commandline if needed. The alternative would be running msbuild and have it print it's value, then pass that using /p:PlatformToolset=. But that's not so nice for local development builds in Visual Studio.
For changing the project file, find the section(s) where the PlatformToolset is defined and change it to $(DefaultPlatformToolset) - this should come after the Microsoft.Cpp.Default.props import else the property might not yet be defined. To guard against the case where you're building for a platform which for some reason does not define DefaultPlatformToolset (something custom, or possibly old VS versions) set it to a sensible default first, before the Microsoft.Cpp.Default.props. Example:
<PropertyGroup Label="Globals">
<PlatformToolset>v100</PlatformToolset>
</PropertyGroup>
....
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
....
<PropertyGroup>
<PlatformToolset>$(DefaultPlatformToolset)</PlatformToolset>
</PropertyGroup>
Here's another way to do it:
<!-- Use DefaultPlatformToolset after Microsoft.Cpp.Default.props -->
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<!-- Set DefaultPlatformToolset to v100 (VS2010) if not defined -->
<PropertyGroup Label="EmptyDefaultPlatformToolset">
<DefaultPlatformToolset Condition=" '$(DefaultPlatformToolset)' == '' ">v100</DefaultPlatformToolset>
</PropertyGroup>
<PropertyGroup Label="PlatformToolset">
<PlatformToolset>$(DefaultPlatformToolset)</PlatformToolset>
</PropertyGroup>
It is also very important to ensure the Global property group elements are set before Microsoft.Cpp.Default.props is imported. If they are not set, then MSbuild assumes an Application is being built, and it ignores the ConfigurationType that comes later:
<PropertyGroup Label="Globals">
<ProjectGuid>{016d3861-ccd6-4a50-83b4-fe4e93bea333}</ProjectGuid>
<RootNamespace>mylib</RootNamespace>
<ConfigurationType>StaticLibrary</ConfigurationType>
</PropertyGroup>
...
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
...
<PropertyGroup>
<PlatformToolset>$(DefaultPlatformToolset)</PlatformToolset>
</PropertyGroup>

TransformXml task could not be loaded from Microsoft.Web.Publishing.Tasks.dll

Has anyone seen this error and know how to fix it?
The "TransformXml" task could not be loaded from the assembly C:\Program Files (x86)\MSBuild\Microsoft\VisualStudio\v11.0\Web\Microsoft.Web.Publishing.Tasks.dll.
Could not load file or assembly 'file:///C:\Program Files (x86)\MSBuild\Microsoft\VisualStudio\v11.0\Web\Microsoft.Web.Publishing.Tasks.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 read elsewhere that the problem is when you don't have SQL Server installed. But I do have SQL Express 2012 x64 installed with SP1. I am also running VS 2013 Professional.
I have ran this exact same solution in VS 2012 express with no problems.
The answers provided by Dai Bok and emalamisura work fine as long as you use Visual Studio 2012.
For VS 2013 this fails as well. In order to make this work with all versions of Visual Studio you should:
Open the project file (.csproj) of the project failing to load
Search for <Import Project="$(MSBuildExtensionsPath)\Microsoft\VisualStudio\v10.0\Web\Microsoft.Web.Publishing.targets" />
Change it to <Import Project="$(MSBuildExtensionsPath)\Microsoft\VisualStudio\v$(VisualStudioVersion)\Web\Microsoft.Web.Publishing.targets" />
Reload the project
That will set the correct version of Visual Studio dynamically and properly.
To get mine to work, I just copied my v10.0 folder and renamed it to v11.0, and things seems to work well from then on. That's the quick fix for now.
As this is probably not the best solution, and although it works, I was going to try installing the Microsoft Windows SDK for Windows 7 and .NET Framework 4 Windows SDK for Windows 7 and .NET Framework 4, but it is taking to long to download.
To fix the issue,
Find the Visual studio Installer in your computer
Click or tap to start the installer, and then select Modify.
From the Individual Components screen, select Asp.net and web development tools and then select Modify/Install.
This solved the issue as it creates the dll's in the mentioned path.
I've been combating this problem on our build server for several days, so I figured I'd document the resolution I came to. First, my build server has the web publishing extensions installed. I can use the TransformXml task to my heart's content inside of a web application project.
To use it outside of a web application project, I tried to add the UsingTask element to my project and point it to the right place using ms build properties (as Benjamin demonstrated). However, they weren't there on my build server (those with easy access to the file system of their build server can probably skip this and just install the relevant package to Visual Studio). I even went so far as to hard code visual studio versions, but it always dropped that error on me.
I finally gave up, pulled the DLLs from my local PC:
C:\Program Files (x86)\MSBuild\Microsoft\VisualStudio\v12.0\Web\Microsoft.Web.Publishing.Tasks.dll
C:\Program Files (x86)\MSBuild\Microsoft\VisualStudio\v12.0\Web\Microsoft.Web.XmlTransform.dll
I uploaded them to source control and added that folder to my build's workspace (Edit Build Definition -> Source Settings -> Source Control Folder). From there, I don't even need to reference the folder -- here's what my UsingTask looks like:
<UsingTask TaskName="TransformXml" AssemblyFile="Microsoft.Web.Publishing.Tasks.dll" />
Now I can use the TransformXml task to my heart's content from any project.
For VS2019
<UsingTask TaskName="TransformXml" AssemblyFile="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(MSBuildToolsVersion
I replaced MSBuildToolsVersion with VisualStudioVersion.
Because there are only v12.0, v14.0 and v15.0 in my VisualStudio folder, I edit my project file and change the reference path from v10.0 to v14.0. Then the project builds successfully.
Before:
<UsingTask TaskName="TransformXml" AssemblyFile="$(MSBuildExtensionsPath)\Microsoft\VisualStudio\v10.0\Web\Microsoft.Web.Publishing.Tasks.dll" />
After:
<UsingTask TaskName="TransformXml" AssemblyFile="$(MSBuildExtensionsPath)\Microsoft\VisualStudio\v14.0\Web\Microsoft.Web.Publishing.Tasks.dll" />
Solutions provided seem to work for using VS as an IDE, but if you use DotnetCore via CLI or on a unix based system this does not work.
I found that the following seem to work
<PropertyGroup>
<XmlTransformDllPath Condition="'$(XmlTransformDllPath)' == '' AND '$(MSBuildRuntimeType)' == 'core'">$(MSBuildSDKsPath)/Microsoft.NET.Sdk.Publish/tools/net5.0/Microsoft.NET.Sdk.Publish.Tasks.dll</XmlTransformDllPath>
<XmlTransformDllPath Condition="'$(XmlTransformDllPath)' == '' AND '$(MSBuildRuntimeType)' != 'core'">$(MSBuildSDKsPath)/Microsoft.NET.Sdk.Publish/tools/net472/Microsoft.NET.Sdk.Publish.Tasks.dll</XmlTransformDllPath>
<XmlTransformDllPath Condition="!Exists($(XmlTransformDllPath))">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\Web\Microsoft.Web.Publishing.Tasks.dll</XmlTransformDllPath>
</PropertyGroup>
<UsingTask TaskName="TransformXml" AssemblyFile="$(XmlTransformDllPath)" />
This solution takes into account netcore, full .net
For some reason MSBuildSDKsPath and MSBuildExtensionsPath32 are different on windows when using CLI vs VS2019
CLI:
MSBuildSDKsPath = C:\Program Files\dotnet\sdk\5.0.103\Sdks
MSBuildExtensionsPath32 = C:\Program Files\dotnet\sdk\5.0.103
Vs2019
MSBuildSDKsPath = C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\MSBuild\Sdks
MSBuildExtensionsPath32 = C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\MSBuild
Which on my Mac returns /usr/local/share/dotnet/sdk/5.0.201
Only problem I see is with the tools/net5.0 part of the name which changes ever release
Also created https://github.com/dotnet/sdk/issues/16469 and answers this on The "TransformXml" task was not found (error MSB4036) on TeamCity build
The correct answer to this is to unload the project in question and then edit the csproj file, look for an entry where they are referencing the 10.0 path and change it to point to 11.0 instead.
You need two things to make it work:
1) Install Visual Studio Build Tools (You don't need the whole Visual Studio, only the VS Build Tools) with selected "Web development build tools" option on your build server
https://www.visualstudio.com/pl/thank-you-downloading-visual-studio/?sku=BuildTools&rel=15
2) Ensure that path to Microsoft.Web.Publishing.Tasks.dll is correct
<UsingTask TaskName="TransformXml" AssemblyFile="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(MSBuildToolsVersion)\Web\Microsoft.Web.Publishing.Tasks.dll" />
For me it started working just by adding reference to the NuGet package MSBuild.Microsoft.VisualStudio.Web.targets v14.0.0.3
Even no need to add UsingTask element to the project file as it mentioned by the package author
https://github.com/pdonald/nuget-webtargets
Just install the NuGet package. The package automatically sets the
$(VSToolsPath) property to use the targets file in the tools folder.
And then I was able to use TransformXml and other tasks, defined in the package, for instance to transform app.config
<Target Name="app_config_AfterCompile" AfterTargets="AfterCompile" Condition="Exists('app.$(Configuration).config')">
<!--Generate transformed app config in the intermediate directory-->
<TransformXml Source="app.config" Destination="$(IntermediateOutputPath)$(TargetFileName).config" Transform="app.$(Configuration).config" />
<!--Force build process to use the transformed configuration file from now on.-->
<ItemGroup>
<AppConfigWithTargetPath Remove="App.config" />
<AppConfigWithTargetPath Include="$(IntermediateOutputPath)$(TargetFileName).config">
<TargetPath>$(TargetFileName).config</TargetPath>
</AppConfigWithTargetPath>
</ItemGroup>
</Target>
Just in case someone is using an SDK-style csproj, you can achieve this without having to install Visual Studio on the build server.
First you should install the SlowCheetah nuget package to your project. Once you install it, you'll see the following in your SDK-style project.
<PackageReference Include="Microsoft.VisualStudio.SlowCheetah" Version="3.2.20">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
</PackageReference>
Then make sure you add the GeneratePathProperty="true" attribute (see below). This is very important for the next part because it'll help you grab the path of where the nuget package is restored on your machine. George Dangl explains it in his article here.
<PackageReference Include="Microsoft.VisualStudio.SlowCheetah" Version="3.2.20" GeneratePathProperty="true">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
</PackageReference>
Import the SlowCheetah targets into your project:
<Import Project="$(PkgMicrosoft_VisualStudio_SlowCheetah)\build\Microsoft.VisualStudio.SlowCheetah.targets" />
You can now use an target command (in this case after publish) to apply some custom transformations. If you need to, you can always hard-code the file names below instead of using the variables in the below example.
<Target Name="AfterPublishs" AfterTargets="Publish">
<TransformTask Source="Web.config" Transform="Web.$(Configuration).MyCustomTransformFile.config" Destination="$(PublishDir)\Web.config" />
</Target>
If you haven't used SlowCheetah before, I recommend checking it out. They have a Visual Studio extension that will make it easier for you to preview transform files.

Resources