I have a roslyn analyzer project based on Microsoft's default template. I can easily build the analyzer in Visual Studio or with msbuild.
The problem is that the solution includes a vsix project that relies on the microsoft.vssdk.buildtools which are not supported by dotnet build.
This results in an error message when trying to build the solution in the command line with dotnet build: microsoft.vssdk.buildtools\17.4.2119\tools\VSSDK\Microsoft.VsSDK.targets(826,5): error : VSIX deployment is not supported with 'dotnet build'
The vsix is nice to have when developing with Visual Studio, but I do publish my analyzer via NuGet package instead of as vsix so I don't need the vsix on the CLI.
Is there a way to specify in the csproj that I don't want it to be built when it is invoked from dotnet build? I'd like to avoid having a separate sln file or a specific dotnet configuration that excludes the project if possible.
Two possible approaches include using a solution filter and changing the project to not build under certain conditions.
Use a Solution Filter
dotnet build will accept a solution filter file (.slnf).
To create the solution filter:
Open the solution in Visual Studio
Go to the solution explorer window
Right-click on the VSIX project, choose 'Unload Project'
Right-click on the solution, choose 'Save As Solution Filter'
When building with dotnet the .slnf will need to be used. Using the .sln file or the VSIX project file with dotnet will be an error.
Detecting when Invoked from dotnet build
There isn't a defined property or function in MSBuild that identifies the executable that is running the MSBuild engine.
However there is a MSBuildRuntimeType property.
Prior to MSBuild 15, MSBuildRuntimeType will be undefined. In MSBuild 15 and later MSBuildRuntimeType will have a value of Full, Core, or Mono. From the documentation MSBuildRuntimeType will have a value of Core when dotnet build is used. (Further the error message "VSIX deployment is not supported with 'dotnet build'" is only displayed when '$(MSBuildRuntimeType)' == 'Core'.)
There isn't an 'exit build' task so the project can't detect and then end. We need to detect before the project really starts. But wrapping a project within a project is clunky especially if you want to be able to work with the project and change properties from the Visual Studio IDE.
Targets can be redefined and an Import can have a condition. A file can be imported when MSBuildRuntimeType is Core and the file can redefine the 'Build' target.
Add to the VSIX project file:
<Import Project="noop.targets" Condition="'$(MSBuildRuntimeType)' == 'Core'" />
The noop.targets may contain the following:
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Target Name="Build">
<Message Text="$(MSBuildProjectName) has been skipped." />
</Target>
</Project>
Hope this helps or at least provides some ideas.
Related
I am not able to build a UWP project with Github actions. I run dotnet build --configuration Release on the whole solution, but for UWP the error is:
error MSB4019: The imported project "C:\hostedtoolcache\windows\dncs\3.1.101\x64\sdk\3.1.101\Microsoft\WindowsXaml\v16.0\Microsoft.Windows.UI.Xaml.CSharp.targets" was not found. Confirm that the expression in the Import declaration "C:\hostedtoolcache\windows\dncs\3.1.101\x64\sdk\3.1.101\\Microsoft\WindowsXaml\v16.0\Microsoft.Windows.UI.Xaml.CSharp.targets" is correct, and that the file exists on disk.
Locally I use VS 2019 Pro, 16.4.5. I have this import in my csproj (generated by default VS template):
<Import Project="$(MSBuildExtensionsPath)\Microsoft\WindowsXaml\v$(VisualStudioVersion)\Microsoft.Windows.UI.Xaml.CSharp.targets" />
I tried installing the visualstudio2019-workload-universal with chocolatey, but same result.
Links to Build, yaml, csproj
Any idea how to fix the build issue?
We have a Visual Studio 2013 project who's .csproj looks like this
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
Recently we migrated the solution to Visual Studio 2017 but somehow tool version remained same.
I am using TeamCity to build my project & on teamcity server we only have MS build version 14. If I use it to build the app, I get following error: The imported project "C:\Program Files (x86)\MSBuild\Microsoft\VisualStudio\v11.0\WebApplications\Microsoft.WebApplication.targets" was not found. Confirm that the path in the <Import> declaration is correct, and that the file exists on disk.
What is the easiest way to update the tool-version is .csproj? If I update it manually, would it cause any issues? are there any other settings/config I need to change once I make this change?
ToolsVersion is not the main cause of this issue I think, so you can feel free to manually change it. And for project from VS2013, its ToolsVersion should be 12.0 instead of 4.0.
VS2013=>12.0, VS2017=>15.0, VS2015=>14.0: So you now have one project migrated from VS2012 to VS2017, and now you use msbuild of VS2015 to build it. For this scenario, here're some suggestions which may help:
1.Change the ToolsVersion to 12.0(or 14.0). This actually makes a bit effect.
2.Make sure you've installed web application workload for your msbuild 14.0 in server. If your msbuild 14.0 comes from VS2015, please check if you can create new web application project in it, then you'll know if you've installed web workload in VS! (The missing targets come from the web app workload, similar issue see here.)
If you can find the missing file in C:\Program Files (x86)\MSBuild\Microsoft\VisualStudio\v14.0\WebApplications, trying passing /p:VisualStudioVersion=14.0 to msbuild command when you configure it in teamcity.
3.The most recommended way is to install the msbuild from higher VS version. MSbuild has independent package for VS2017 and VS2019.(Build Tools for VS2017 or VS2019)
You can find their download link here,see Tools for VS category. You can install this package(Enable web-related workload!) in your server(you don't need to install whole VS IDE), and then you can call msbuild.exe from C:\Program Files (x86)\Microsoft Visual Studio\2019\BuildTools\MSBuild\Current\Bin or C:\Program Files (x86)\Microsoft Visual Studio\2017\BuildTools\MSBuild\15.0\Bin in teamcity to build current project.
Note: MSBuild from higher VS version can always build projects from earlier VS versions, but msbuild from earlier sometimes can't recognize projects from higher vs versions. So it's recommended to use msbuild 15.0 to build projects from VS2017, instead of using msbuild 14.0.
Currently we are evaluating NuGet tool for our dot net project built on framework 4.6.2 using VS2017. Our goal is to refer our common libraries in our solution as reference (like Maven dependencies) pulling it from internal nexus repository.
We are familiar with maven concepts like snapshot and release. We would like to achieve the same using NuGet tool. Brief search on internet says this is not supported in Nuget. Any pointers to do it in elegant way for dotnet projects with NuGet?
Any assistance in this regards is appreciated. Thanks
Using the new SDK-based project system, NuGet and MSBuild are integrated. There currently isn't a project template for this in VS2017 but you can create a .NET Standard library and change the <TargetFramework> value in the .csproj file to:
<TargetFramework>net462</TargetFramework>
Then you need to define a version number for your library. This can be done through setting a Versionproperty OR setting a combination of VersionPrefix and VersionSuffix property that are combined during build. For CI-szenarios, you usually want to set only the VersionPrefix value in your .csproj file, inside of a <PropertyGroup> element:
<VersionPrefix>1.2.3</VersionPrefix>
This can also be set inside a Directory.Build.props file in the solution directory to have a single place to set the property for all projects in one place:
<Project>
<PropertyGroup>
<VersionPrefix>1.2.3</VersionPrefix>
</PropertyGroup>
</Project>
When building through CI or locally, you can set the VersionSuffix property through command line, the pack command of the dotnet cli offers a convenience option for this:
dotnet pack -c Release --version-suffix SNAPSHOT
Alternatively, the same result can be accomplished when using the VS version of MSBuild via the Developer Command Prompt:
msbuild /t:Pack /p:Configuration=Release /p:VersionSuffix=SNAPSHOT
Currently (VS 2017 15.2, .NET CLI 1.0.*), there is a bug when having multiple projects that reference each other - the dependency versions aren't generated with a the specified version suffix. There is a workaround: Perform an additional restore before packing using the same property:
dotnet msbuild "/t:Pack;Restore" /p:Configuration=Release /p:VersionSuffix=SNAPSHOT
On your CI system you would typically overwrite the Suffix with a build number to generate a version like 1.2.3-ci-20170102 or just generate SNAPSHOT / PREVIEW etc. packages.
Since msbuild allows for scripting, you can also extend the csproj file to set the version suffix automatically if some conditions are met - e.g. always generate a suffix for debug builds so you don't accidentally publish a debug build.
<VersionSuffix Condition=" '$(Configuration)' != 'Release' ">SNAPSHOT</VersionSuffix>
I have one project configured with AppVeyor for Nuget deployments. Recently I decide add support for .Net Core Framework. On continuous integration environment dotnet is used to compile, run unit tests and pack the project, but when I added a project.json and compile with Visual Studio 2015 dotnet is used instead MSBuild. So I have in the project folder the .csproj and project.json files.
QUESTION:
There is any way to configure Visual Studio to use always MSBuild with .csproj instead dotnet with project.json and leave the use of these for continuous integration only?
There is any way to configure Visual Studio to use always MSBuild with .csproj instead dotnet with project.json and leave the use of these for continuous integration only?
You can use the dotnet migrate command to migrate a project.json project to the csproj format. This command will also migrate any project-to-project references you have in your
project.json file automatically. for more information, please refer to: https://learn.microsoft.com/en-us/dotnet/articles/core/preview3/tools/dotnet-migrate
The following blogs provide an example about migrate project.json to csproj for your reference(please check the phase “Upgrading project.json projects”)
https://blogs.msdn.microsoft.com/dotnet/2016/11/16/announcing-net-core-tools-msbuild-alpha/
I have a solution with many projects, some of which use PostSharp. I've recently switched from using NuGet MSBuild integrated restore to NuGet Auto Restore. This causes all necessary packages to be restored for all packages before a build starts. This works great, except for now I come across an issue frequently where PostSharp will fail the build with the error:
The build restored NuGet packages. Build the project again to include these packages in the build. For more information, see http://www.postsharp.net/links/nuget-restore.
When I edit the project file I see the following entry:
<Import Project="..\..\packages\PostSharp.3.1.46\tools\PostSharp.targets" Condition="Exists('..\..\packages\PostSharp.3.1.46\tools\PostSharp.targets')" />
<Target Name="EnsurePostSharpImported" BeforeTargets="BeforeBuild" Condition="'$(PostSharp30Imported)' == ''">
<Error Condition="!Exists('..\..\packages\PostSharp.3.1.46\tools\PostSharp.targets')" Text="This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://www.postsharp.net/links/nuget-restore." />
<Error Condition="Exists('..\..\packages\PostSharp.3.1.46\tools\PostSharp.targets')" Text="The build restored NuGet packages. Build the project again to include these packages in the build. For more information, see http://www.postsharp.net/links/nuget-restore." />
</Target>
As you can see, there is an error condition for when the NuGet package exists on my machine and also doesn't exist on my machine. It appears that these conditions are evaluated because the variable $(PostSharp30Imported) is never set. I'm assuming this something that is dependent on the MSBuild integrated version of restore, but I don't have enough MSBuild experience to know for sure.
I am able to work around the issue by simply removing the second Error condition in the project file (since I am guaranteed to have the files by the time the project builds), but it seems like any upgrades or additions of PostSharp cause the project file to revert to the old way and prevents my solution from building.
Is this a bug in PostSharp, or is there some other way I should be working with PostSharp when using NuGet auto restore that does not cause this issue?
If you have completely migrated from the old MSBuild based package restore away then you should not see that error message if you are using a recent version of NuGet. Visual Studio checks for the existence of the .nuget/NuGet.targets file and does not use the new Visual Studio based package restore if this file exists.
The newer automatic package restore will occur when you build the project but before MSBuild is started. This means the various MSBuild properties that are defined in the PostSharp MSBuild targets file will be imported before MSBuild tries to compile your project. In this case the PostSharp30Imported should be defined so that custom target is never run. It would only be run if the PostSharp.targets file did not exist whilst MSBuild was compiling the project.
The error message is correct for the older MSBuild based package restore since the build would restore the targets file whilst MSBuild was running so they would not be available, and therefore not imported, for the first build.
Creating a new project, adding PostSharp, deleting all the packages, then recompiling the project I see no error message.