How to use .NET 6 Preview Generic Math in Visual Studio 2022? - visual-studio-2022

There are several articles explaining the new .NET 6 Preview features of Generic Math, often based on this Microsoft article:
https://devblogs.microsoft.com/dotnet/preview-features-in-net-6-generic-math/
In the preview versions, and the first release of Visual Studio 2022 this works fine. But in Visual Studio 2022 version 17.0.3 and 17.0.4 (the current release) I simply cannot get this to compile.
I actually went back to VS2022 version 17.0.0 to make sure I had correctly followed the article steps. The code compiles just fine. Upgrade to VS2022 version 17.0.3 and the same project fails to build with the error:
Error CS0246 The type or namespace name 'INumber<>' could not be found (are you missing a using directive or an assembly reference?)
Anyone got any ideas? I assume I have to make a further change to the csproj file, but what change?
In the NuGet Package Manager I found the option to upgrade System.Runtime.Experimental to version 6.0.0, which changed the entry in my csproj file from:
<ItemGroup>
<PackageReference Include="System.Runtime.Experimental" Version="6.0.0-preview.7.21377.19" />
</ItemGroup>
to:
<ItemGroup>
<PackageReference Include="System.Runtime.Experimental" Version="6.0.0" />
</ItemGroup>
rebooting doesn't help. Cleaning the solution doesn't help. I am not seeing anything to help me in the release notes for Visual Studio 2022 either.
The complete csproj file, for reference, already containing the extra bits you need, is:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net6.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<EnablePreviewFeatures>True</EnablePreviewFeatures>
<LangVersion>preview</LangVersion>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="System.Runtime.Experimental" Version="6.0.0" />
</ItemGroup>
</Project>

Step 1
As explained in the blog article you've linked at the top of the question: add
<EnablePreviewFeatures>true</EnablePreviewFeatures>
into a <PropertyGroup> element in your project file.
Step 2
Now the above is confirmed: have you tried the preview version of VS2022 (currently V17.1 Preview 1.1)?
Just tried it: No.
Step 3
See Hans Passant's comment on to the question: need to wait on this (or do you own builds of what is being built to be .NET 7...)
Update for VS 2002 17.2.0 Preview 3.0
With V6.0.2 of System.Runtime.Experimental this now works.

I got the same error with VS2022 17.0.4. Now, VS2022 17.1.0 Preview 1.1 seems to work fine.

Related

Upgrading large solution to .NET 6

There is some good documentation here how to manually upgrade to .NET 6: https://learn.microsoft.com/en-us/aspnet/core/migration/50-to-60
But I have a large solution with many projects that references many of NuGet-packages that need to be upgraded. Is there any automatic way to do upgrade the project files?
I used to do it with the "replace-in-files option" and NuGet-Manager in Visual Studio. Worked out for me in a 181 projects solution.
Open any *.csproj-file
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net5.0</TargetFramework>
</PropertyGroup>
</Project>
Press Shift+Ctrl+H
Open NuGet-Manager for Solution (not project itself). Select all packages and update them all (if possible, else leave out the once you know are not compatible)
You can set properties for all projects in the solution using a Directory.Build.props file, see: https://learn.microsoft.com/en-us/visualstudio/msbuild/customize-your-build?view=vs-2022#directorybuildprops-and-directorybuildtargets
In your case you'd use something like this:
<Project>
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
</PropertyGroup>
</Project>
Place the file in the root of your solution, above all project folders.
You could try this PowerShell script that that upgrade all csproj-files from .NET 5 to .NET 6, including NuGet-packages:
https://gist.github.com/pekspro/24fca2eb1cad8c30333a910b163a3f6a
On the same location there is a script that downgrades to .NET 5. But do not trust this, make sure you have a backup if something goes wrong.

Visual Studio 2017 and the new .csproj InternalsVisibleTo

Where do I put InternalsVisibleTo from AssemblyInfo in the new Visual Studio 2017 .csproj project file?
Just in case anyone would like to put InternalsVisibleTo within a .csproj file instead of AssemblyInfo.cs (a possible scenario is to have a naming convention between a project under test and a test project), you can do it like this:
<ItemGroup>
<AssemblyAttribute Include="System.Runtime.CompilerServices.InternalsVisibleTo">
<_Parameter1>$(MSBuildProjectName).Test</_Parameter1>
</AssemblyAttribute>
</ItemGroup>
Having this the following code will be generated
[assembly: System.Runtime.CompilerServices.InternalsVisibleTo("MyProject.Test")]
inside auto-generated AssemblyInfo.cs (e.g. for Debug configuration and .NET Standard 2.0 target)
/obj/Debug/netstandard2.0/MyProject.AssemblyInfo.cs
Additional Info
In case you're on .NET Core 3.1 and this approach isn't working, you may have to explicitly generate assembly info by adding the following to your .csproj file:
<PropertyGroup>
<!-- Explicitly generate Assembly Info -->
<GenerateAssemblyInfo>true</GenerateAssemblyInfo>
</PropertyGroup>
As of .NET 5 (and newer .NET versions) this actually works once added to your csproj:
<ItemGroup>
<InternalsVisibleTo Include="YourProject.Tests.Unit" />
</ItemGroup>
Work and discussion around this feature can be seen on this PR on dotnet's GitHub repo.
To clarify Hans Passant's comment above, you simply have to add InternalsVisibleTo to any cs file in your project. For example, I created an AssemblyInfo.cs file in the root of the project and then added the following content (only):
using System.Runtime.CompilerServices;
[assembly: InternalsVisibleTo("DynamicProxyGenAssembly2, PublicKey=<ADD_KEY_HERE>")]

How to exclude some stylecop rule in visual studio 2013

I'm using visual studio 2013.
I install stylecop using NuGet Package follow these steps:
https://www.nuget.org/packages/StyleCop.MSBuild/
Previously when I using visual studio 2010, I usually put my custom rules set called Setting.StyleCop file to my solution or project.
How should I implement my custom rules set in VS 2013?
Settings.StyleCop still works as it did previously.
The StyleCop.MsBuild package performs a couple of actions:
1. Stores an instance of StyleCop.exe in the packages directory, this makes it portable between machines, build servers etc.. Namely \packages\StyleCop.MSBuild.4.7.49.1\tools this is pretty much the same you would get with installing it, but its not in program files.
2. Makes changes to the csproj, namely:
<Import Project="..\..\packages\StyleCop.MSBuild.4.7.49.1\build\StyleCop.MSBuild.Targets" Condition="Exists('..\..\packages\StyleCop.MSBuild.4.7.49.1\build\StyleCop.MSBuild.Targets')" />
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
<PropertyGroup>
<ErrorText>This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.</ErrorText>
</PropertyGroup>
<Error Condition="!Exists('..\..\packages\StyleCop.MSBuild.4.7.49.1\build\StyleCop.MSBuild.Targets')" Text="$([System.String]::Format('$(ErrorText)', '..\..\packages\StyleCop.MSBuild.4.7.49.1\build\StyleCop.MSBuild.Targets'))" />
</Target>
All this basically does is point at the targets file so that it runs stylecop and adds in some requires for the package to be there before building.
What you need to do to use StyleCop.Settings
Copy it into the root of your solution, or the project file, then it should get picked up as usual. The easiest way is just to copy it from \packages\StyleCop.MSBuild.4.7.49.1\tools

How can I reset Visual Studio's publishing configuration to default?

I am just a hobbyist programmer so I am sorry if I am asking a question I should know the answer to. I searched for an answer, but never found it, so I thought I would join and post a question here.
I have some VB 2010 Express code I have written that I wished to deploy from my web page. I used Visual Studio's ClickOnce publishing system and was pleased with the results.
After a couple of versions published I went into the publisher's configuration manager to explore the options.
That was my, uhhh, mistake. I changed many things that I thought would make things nicer for the deployment but screwed up something because now all versions, even previously working versions no longer deploy correctly. If you click for a download and installation, the install starts but the installer complains that there is an error it wants to report to Microsoft.
Is there some way to reset the publish configuration back to it's starting values?
I am running VB on XP with Visual Studio 2010 Express.
I was able to reset the Publish settings for my actual project by comparing the content of the project files for two sample projects, one with publishing and the other one without and identifying which entries were added. I used the FC DOS command to output the differences to a text file (the file extensions were .csproj since mine was a C# project):
fc publish_project.csproj non_publish_project.csproj > diff.txt
I examined diff.txt and found what changed. Deleting the following entries from the real project file will reset the Publish option (do a backup first!):
<IsWebBootstrapper>true</IsWebBootstrapper>
<PublishUrl>ftp://ftpserver.com/</PublishUrl>
<Install>false</Install>
<InstallFrom>Web</InstallFrom>
<UpdateEnabled>true</UpdateEnabled>
<UpdateMode>Foreground</UpdateMode>
<UpdateInterval>7</UpdateInterval>
<UpdateIntervalUnits>Days</UpdateIntervalUnits>
<UpdatePeriodically>false</UpdatePeriodically>
<UpdateRequired>false</UpdateRequired>
<MapFileExtensions>true</MapFileExtensions>
<InstallUrl>http://www.myproduct.net/project1/downloads/</InstallUrl>
<CreateWebPageOnPublish>true</CreateWebPageOnPublish>
<WebPage>publish.htm</WebPage>
<ApplicationRevision>0</ApplicationRevision>
<ApplicationVersion>1.0.0.%2a</ApplicationVersion>
<UseApplicationTrust>false</UseApplicationTrust>
<PublishWizardCompleted>true</PublishWizardCompleted>
<BootstrapperEnabled>true</BootstrapperEnabled>
...
<PropertyGroup>
<TargetZone>LocalIntranet</TargetZone>
</PropertyGroup>
<PropertyGroup>
<GenerateManifests>true</GenerateManifests>
</PropertyGroup>
...
<ItemGroup>
<BootstrapperPackage Include="Microsoft.Net.Client.3.5">
<Visible>False</Visible>
<ProductName>.NET Framework 3.5 SP1 Client Profile</ProductName>
<Install>false</Install>
</BootstrapperPackage>
<BootstrapperPackage Include="Microsoft.Net.Framework.3.5.SP1">
<Visible>False</Visible>
<ProductName>.NET Framework 3.5 SP1</ProductName>
<Install>true</Install>
</BootstrapperPackage>
<BootstrapperPackage Include="Microsoft.Windows.Installer.3.1">
<Visible>False</Visible>
<ProductName>Windows Installer 3.1</ProductName>
<Install>true</Install>
</BootstrapperPackage>
</ItemGroup>
Copying the file ProjectName.vbproj from a very previous version took care of my problem.
I would presume that the other suggestion, creating a new project and copying it's file, should have the same result. Especially if you do not have previous versions.
When you publish, it creates a profile with all the configuration settings.
So, you just have to delete that profile.
Click on "Delete" and it should be reseted.

Overriding MSBuildExtensionsPath in the MSBuild task is flaky

This is already cross-posted at MS Connect:
https://connect.microsoft.com/VisualStudio/feedback/details/560451
I am attempting to override the property $(MSBuildExtensionsPath) when building a solution containing a C# web application project via msbuild. I am doing this because a web application csproj file imports the file "$(MSBuildExtensionsPath)\Microsoft\VisualStudio\v9.0\WebApplications\Microsoft.WebApplication.targets". This file is installed by Visual Studio to the standard $(MSBuildExtensionsPath) location (C:\Program Files\MSBuild). I would like to eliminate the dependency on this file being installed on the machine (I would like to keep my build servers as "clean" as possible). In order to do this, I would like to include the Microsoft.WebApplication.targets in source control with my project, and then override $(MSBuildExtensionsPath) so that the csproj will import this included version of Microsoft.WebApplication.targets. This approach allows me to remove the dependency without requiring me to manually modify the web application csproj file.
This scheme works fine when I build my solution file from the command line, supplying the custom value of $(MSBuildExtensionsPath) at the command line to msbuild via the /p flag. However, if I attempt to build the solution using the MSBuild task in a custom msbuild project file (overriding MSBuildExtensionsPath using the "Properties" attribute), it fails because the web app csproj file is attempting to import the Microsoft.WebApplication.targets from the "standard" Microsoft.WebApplication.targets location (C:\Program Files\MSBuild). Notably, if I run msbuild using the "Exec" task in my custom project file, it works. Even more notably, the FIRST time I run the build using the "MSBuild" task AFTER I have run the build using the "EXEC" task (or directly from the command line), the build works.
Has anyone seen behavior like this before? Am I crazy? Is anyone aware of the root cause of this problem, a possible workaround, or whether this is a legitimate bug in MSBuild?
Steps to Reproduce:
1) Create a new empty solution in MSVS 2008 (Fake.sln)
2) Add a new C# web application to the solution (WebApplication1.csproj)
3) Close MSVS
4) Copy the contents of "C:\Program Files\MSBuild\" to a directory called "MSBuildExtensions" in the directory containing your solution.
5) rename the directory "C:\Program Files\MSBuild\Microsoft\VisualStudio\v9.0\WebApplications" so that WebApplication1.csproj will not be able to import Microsoft.WebApplication.targets from that location.
6) Create a custom MSBuild project file called "TestBuild.proj" in the same directory as the solution. It should have the following content:
<?xml version="1.0" encoding="utf-8"?>
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003" DefaultTargets="BuildMSBuild">
<PropertyGroup>
<MSBuildExtensionsPath>$(MSBuildProjectDirectory)\MSBuildExtensions\</MSBuildExtensionsPath>
<BuildThis>Fake.sln</BuildThis>
</PropertyGroup>
<Target Name="BuildMSBuild">
<MSBuild Projects="$(BuildThis)" Properties="MSBuildExtensionsPath=$(MSBuildExtensionsPath);" Targets="Clean" />
<MSBuild Projects="$(BuildThis)" Properties="MSBuildExtensionsPath=$(MSBuildExtensionsPath);"/>
</Target>
</Project>
7) execute "msbuild TestBuild.proj" from a MSVS command prompt (note: the build may succeed the first time, but will fail if you run more than once)
Did you try setting the environment variable MSBuildExtensionPath in the CMD prompt and then running your build?
For example:
C:\> SET MSBuildExtensionsPath=C:\My\MSBuild\Extensons
Then on this project file:
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Target Name="Build">
<Message Text='MSBuildExtensionsPath="$(MSBuildExtensionsPath)"' />
</Target>
</Project>
you will get the following output:
c:\Users\chuckeng\Desktop\ConsoleApplication1>"C:\Windows\Microsoft.NET\Framework\v3.5\MSBuild.exe" my.proj
Microsoft (R) Build Engine Version 3.5.30729.4926
[Microsoft .NET Framework, Version 2.0.50727.4927]
Copyright (C) Microsoft Corporation 2007. All rights reserved.
Build started 6/25/2010 1:04:05 PM.
Project "c:\my.proj" on node 0 (default targets).
MSBuildExtensionsPath="C:\My\MSBuild\Extensons"
Done Building Project "c:\my.proj" (default targets).
Build succeeded.
0 Warning(s)
0 Error(s)
Time Elapsed 00:00:00.03
This works from v4.0 as well. Although, support is generally better in v4.0 for things like this. And, v4.0 is 100% backward compatible (bugs not withstanding). So, you can build your v3.5 and prior projects with v4.0. Just select ToolsVersion 3.5.
msbuild my.proj /tv:3.5
Hope this helps...
Chuck England
Visual Studio
Program Manager - MSBuild
This is a bug in MSBuild 3.5 but it is fixed in MSBuild 4.
If you can, switch to MSBuild 4 (you still can compile your 3.5 projects), otherwise you'll have to override the property in the project file.
It works fine if you override MSBuildExtensionsPath directly in the web app .csproj file.
<PropertyGroup>
<MSBuildExtensionsPath>C:\Users\madgnome\Desktop\msbuild</MSBuildExtensionsPath>
<!-- It works too with relative path -->
<!--<MSBuildExtensionsPath>..\msbuild</MSBuildExtensionsPath>-->
</PropertyGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<Import Project="$(MSBuildExtensionsPath)\Microsoft\VisualStudio\v10.0\WebApplications\Microsoft.WebApplication.targets" />
Don't know if this might help anyone in the future, but I was able to use the following at the top of my file and it works as I would expect in both 32 and 64 bit build environments.
<PropertyGroup>
<MSBuildExtensionsPath Condition=" '$(MSBuildExtensionsPath64)' != '' ">$(MSBuildExtensionsPath64)</MSBuildExtensionsPath>
</PropertyGroup>
<Import Project="$(MSBuildExtensionsPath)\ExtensionPack\4.0\MSBuild.ExtensionPack.tasks"/>