Creating a custom Sdk in .Net Core - visual-studio

In .Net core projects, there is a .csproj file and inside it the first line specifies the SDK you are targeting in that project, similar to:
<Project Sdk="Microsoft.NET.Sdk.Web">
My question is whether it is possible to create a whole new SDK (maybe by extending the Microsoft.NET.Sdk.Web) and then using this new custom SDK in some other projects, in a way that the new project would have something like this in its .csproj file:
<Project Sdk="My.Own.Sdk">
How could something like this be done?

Yes, you can do it for fun, but there is unlikely to be an official support for publishing.
How to: Use MSBuild project SDKs
It shows the how msbuild loads the props and targets, and you can find the SDK.props and SDK.targets file in the .NET SDK installing folder (represented as dotnet, for example C:\Program Files\dotnet on Windows)
What you need to do to create your own sdk is to make a folder inside dotnet/sdk similarly to any other SDKs look like.
And make the SDK.props and SDK.targets files with path dotnet/sdk/<SDK_VERSION>/Sdks/<YOUR_SDK_NAME>/Sdk, as the entry that reference your props and targets to customize your build steps,
If there is any other file needed by convention, create your new one to mimic the existings.
But still, the officially supported way to customize the callers' build steps is to create a nuget package with a convention subfolder build and the props and targets files would be automatically into the project that referenced the package.

Yes, this is definitely possible, and yes, it can be even published. You can find inspiration at Microsoft.Build.Traversal, for example.
SDK is, basically, nuget package, that has two files, Sdk\Sdk.props and Sdk\Sdk.targets.
If you publish NuGet package with such files to NuGet.org, you may then reference it as
<Project Sdk="YourNugetName/1.0.0">
</Project>
Where the 1.0.0 is your version.
For testing, the Sdk may also contain (fully qualified) path to directory that contains the same content as the nuget package, and just running dotnet build consumes the defined SDK, and runs target Build on it.

Related

Why is TinyIoC not picked up in my Xamarin.Android project when added using nuget?

So I installed TinyIoC v1.3.0 using nuget in my Xamarin.Android project, its in the references, but I cannot type using TinyIoC; without a compile error. I would like to understand why this is?
PS. I know I can use the TinyIoC.cs file directly, but I thought it would be more convenient to update if I added using nuget.
I get this error:
I think the issue is related to the nuget package TinyIoC 1.3.0 itself.
The nuget package does not contain the lib folder with the related dll so that you can not use the format by using namespace.
Note: Important
The nuget package contains a folder called Content. This folder will copy its content into the main project with packages.config when you install the nuget pacakge. See this similar issue on so.
And it will make TinyloC.cs file directly in your main project and you can just modify it there.
I have created a net framework project with packages.config format.
However, since your project is xamarin andorid app, it uses PackageReference nuget manage format, and content folder does not work for it. Instead, you should use ContentFiles folder, but this nuget package does not contain it.
To make this issue more clearly, you should contact the author of the nuget package to report this problem.

How to make Visual Studio Setup Project detect nuget dependencies consistent with build?

I created a setup project using Microsoft Visual Studio Installer Projects (0.9.3, this is latest for Visual Studio 2019). After setup is executed it installs Nuget package assemblies that are different from the assemblies generated during build.
Why is it doing that and how can I make it to chose assemblies consistent with build assemblies?
My application is for 4.7.2 framework. Typical example is System.ValueTuple.dll (4.0.2)
Build retrieves assembly from:
C:\Users\.nuget\packages\system.valuetuple\4.5.0\lib\net47\System.ValueTuple.dll
Install retrieves assembly from:
C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework.NETFramework\v4.7.2\Facades\System.ValueTuple.dll
While install based on 4.0.2 creates a concern but works, when I upgrade nuget package to version 4.6 (and assembly to 4.0.3) install switches to using assembly C:\Users\vgdev.nuget\packages\system.valuetuple\4.5.0\ref\net47\System.ValueTuple.dll
If you look closer, you will notice path above has \ref folder and it contains "reference" assembly. Reference assemblies are not meant to be installed and cause errors BadImageformatException.
The build after Nuget package upgrade continues to pull packages from the correct \lib folder and application works fine. So what I want to do is to make installer work consistently with build. Any advice?
Install retrieves assembly from: C:\Program Files (x86)\Reference
Assemblies\Microsoft\Framework.NETFramework\v4.7.2\Facades\System.ValueTuple.dll
Which way do you reference that package? I can only reproduce this issue when I add reference manually.(Right-click project=>Add reference=>Browse...) If you're doing so, please remove that reference, and add that reference back by Nuget Package Manager UI.
My application is for 4.7.2 framework. Typical example is
System.ValueTuple.dll (4.0.2). When I upgrade nuget package to version 4.6 (and assembly to 4.0.3)
I can only find it with latest 4.5.0 here. And I think it contains the assembly version 4.0.3 instead of 4.0.2.
(I guess something corrupts the process when VS recognize your assembly version cause in most machines it displays 4.0.3 while in one machine, it displays 4.0.2, quite strange...)
The build after Nuget package upgrade continues to pull packages from
the correct \lib folder and application works fine. So what I want to
do is to make installer work consistently with build. Any advice?
Cause of the issue:
This strange behavior may have something to do with Setup project. I can reproduce same situation and I found this issue only occurs when I use PackageReference format to manage nuget packages in my application.(.net 4.7.2)
PackageReference format is the new nuget package manage format after VS2017. I'm not sure if the Setup project fully support for it.
Here're two suggestions which may help:
1.I found this issue only occurs when using PackageReference format. So you can try using Packages.config format in your application. And I've checked the setup project can recognize this format well.
Uninstall all PackageReference format packages, and go Tools=>Nuget Packages Manager=>Nuget Package Manager to set the Allow format selection... to true.
Clean all nuget cache and click ok. After that delete bin and obj folders, then restart VS to add those packages back using Packages.config format.
2.If you continue to use PackageReference format. Try excluding the assembly from ref folder, and manually add that from lib folder by Add=>Assembly=>Browse.
Note: Since Setup project may not fully support packageReference format projects, actually I think #1 could be more suitable for your situation. And you can create a new simple project with packages.config format to check if the issue can be resolved by Packages.config format. Hope it helps :)
It seems that the root cause of the problem is the usage of the BuiltProjectOutputGroupDependencies target by visual studio setup projects instead of the ReferenceCopyLocalPathsOutputGroup target (see PackageReferences put ref instead of lib assemblies in the output group used by VS installer projects).
The proposed workaround is to overwrite the BuiltProjectOutputGroupDependencies target at the end in the project file of your main project:
<Target
Name="BuiltProjectOutputGroupDependencies"
DependsOnTargets="$(BuiltProjectOutputGroupDependenciesDependsOn)"
Returns="#(BuiltProjectOutputGroupDependency)">
<ItemGroup>
<BuiltProjectOutputGroupDependency Include="#(ReferenceCopyLocalPaths->'%(FullPath)');
#(ReferenceDependencyPaths->'%(FullPath)');
#(NativeReferenceFile->'%(FullPath)');
#(_DeploymentLooseManifestFile->'%(FullPath)');
#(ResolvedIsolatedComModules->'%(FullPath)');
#(ReferenceComWrappersToCopyLocal->'%(FullPath)')"/>
</ItemGroup>
</Target>

How does VS 2017 determine .NET Standard dependencies from Paket?

I have a proof-of-concept solution that has a .NET Standard project in it. I use Paket to manage my nuget dependencies. I am able to use paket add and dotnet restore, per these instructions, to add a nuget dependency to that project. When I reopen my solution, I see that a paket.references file has been added to that project, and that a "NuGet" section has been added under the project's "Dependencies" section in "Solution Explorer".
I'm curious, how does VS2017 know what dependencies to list that "NuGet" section?
From the instructions I linked to above:
In contrast to traditional .NET projects Paket will not add assembly
references to your project files. Instead it will only generate a
single line:
<Import Project="..\..\.paket\Paket.Restore.targets" />
This hook tells the .NET SDK to restore packages via Paket's restore
mechanism. A nice benefit is that your project files are now much
cleaner and don't contain many assembly references.
I'm sure I'm missing something, but I don't see anything in Paket.Restore.targets that would tell Visual Studio where to look to find the dependency chain of the nuget package I added to the project. There are no direct references to any dependencies mentioned in the project file.
For context, I have a repo where I'm trying to add a .NET Standard project to a solution that is full of .NET Framework projects. I'm running into an issue where paket add seems to correctly create a paket.references file for the new project, but dotnet restore doesn't seem to be causing the project references to update, resulting in my project not having a reference to the nuget dependency I'm trying to have it reference. I'm having trouble creating a reproducible example (my proof-of-concept seems to be working fine), so I'm trying to better understand how this infrastructure works to help with debugging.

Visual Studio dotnet core copy and paste references

I've known about copy/paste references in Visual Studio since 2010/2012. Has this been updated to work with Core 2?
Here's the SO Question asking about the old style references (before Core, and before the reboot of csproj format): Is it possible to copy / paste References from one project to another in Visual Studio?
Maybe now that dotnet add package is available, we don't need copy/paste references in VS?
"Add Google social login" walkthrough for ASP.NET Core 2.0 suggests using the dotnet CLI to add a package reference:
To install with .NET Core CLI, execute the following in your project
directory:
dotnet add package Microsoft.AspNetCore.Authentication.Google
source: https://learn.microsoft.com/en-us/aspnet/core/security/authentication/social/google-logins?tabs=aspnetcore2x
Writing this answer to my own question so the "just use the CLI" folks have something to upvote.
If you are talking about NuGet package references, don't try to copy the resolved references to dll files manually (the are generated from the obj\project.assets.json file during the design-time build after loading the project).
In the new SDK-based project model and the PackageReference way of referencing NuGet packages (also available for "classic" projects), NuGet references automatically flow transitively across package references. So when your app references a library that uses a NuGet package, you no longer need to install the NuGet package in both the library and the app (and potentially test projects).
Only for "classic" references, this issue remains. However, if you need to import them into all projects (say you got a few .dll files from a 3rd party), you can create a Directory.Build.targets in the solution folder to add them to all projects in your solution (technically, this file is automatically imported into all projects in the directory hierarchy):
<Project>
<ItemGroup>
<Reference Include="AssemblyName">
<HintPath>shared-libs\AssemblyName.dll</HintPath>
</Reference>
</ItemGroup>
</Project>
(you may want to change the reference if you want the "specific version" feature or strong-name references as described in https://stackoverflow.com/a/16580870/784387)

Is there a way to support snapshots with NugGet and native libraries?

We use Visual Studio to write and maintain native Windows apps. We are looking into using NuGet to handle our dependencies, which consist of native static libs.
After some research, I've managed to use NuGet, package.config and the CoApp PowerShell scripts to create and consume NuGet packages with native libs in them. The issue we're facing right now is that we need to have Snapshot support.
The rollover PreRelease mechanism (with * for version rollover) that NuGet 3 and onwards supports looks great, however, it seems to only work with project.json and not with package.config. Project.json, however, doesn't seem to work with native packages, as they don't get installed in the local solution folder so the build can't find the headers and libs.
The question boils down to:
Is there a way to use project.json and NuGet 3 with native static libs?
If not, then, what alternatives are out there to support this use case? (The use case being build-time dependency distribution for native, unmanaged Windows static libraries).
EDIT:
At the end, we decided to use Maven for dependency management since NuGet doesn't seem to support our use case. I filed an issue about two weeks ago but it hasn't received any response. However, if we had decided to force NuGet into our use case, the solution proposed by Wendy would probably be the way to go, so I'm accepting it.
There are two ways could add content files into project that uses project.json file. One is "contentFiles" node and another is "files" node in nuspec file. Detailed steps please refer to:
http://blog.nuget.org/20160126/nuget-contentFiles-demystified.html
But please note, these ways only support UWP and Portable class libraries.
This feature is only for packages that will be installed to projects that are managed using a project.json file. Currently only two projects types are managed by a project.json.
1.UWP apps
2.Portable class libraries
The contentFiles option is not available for other project types
If you are using .NET Core application or other type project that use project.json, the content files in nuget package is not supported added into project at present.

Resources