BizTalk Server Application Project fails to compile with .NET 4.7.2 - azure-devops

In my newly created BizTalk 2020 Dev environment when I'm adding a BizTalk Server Application Project (.btaproj) to the solution, the dialog window where you set the name of the project is showing the .NET framework selector and it defaults to version 4.7.2 as expected.
However when the project is added to the solution I can see in the properties for the project that it is targeting .NET 4.6.1. Has anyone seen this? is it a bug or something wrong with installation?
Naturally I change it to version 4.7.2 as the regular BizTalk project and everything compiles fine in Visual Studio.
But on our build server the same project fails. We use Azure Devops for CICD.On the build server we have the same version of VS installed (2019 enterprise) and BizTalk Server Extention (v3.12.1.0) is installed as well as msbuild tools from BizTalk server installation.
In the logs I first get a Warning:
C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\MSBuild\Current\Bin\Microsoft.Common.CurrentVersion.targets(2106,5): warning MSB3274: The primary reference "A.dll" could not be resolved because it was built against the ".NETFramework,Version=v4.7.2" framework. This is a higher version than the currently targeted framework ".NETFramework,Version=v4.6.1". [B.btaproj]*
And further down in the log the btaproj will not find the assemblies to include in the .zip package.
Message above implies that I have different target versions but I don't.
Now the strange thing is that I can log on to the build server and clone the same project and compile it with VS just fine.
The only way to make the build server compile the project successfully (or any other BizTalk project with .btaproj for that matter) is to change .NET to 4.6.1 (for both .btproj and .btaproj) and it all compiles nicely and deploys to BizTalk environment.
I have checked project files and files checked in to Git and everything seems OK with the sources files. The clean flag I set to clean sources and output directory. I Can compile a regular BizTalk project and .NET application with 4.7.2 on build server just fine it's only when I involve a .btaproj project where it starts to misbehave.
Can anyone point out where to start to look? the .btaproj seems fishy to begin with but it can also be isolated to the msbuild on build server and it differs from compiling with Visual Studio.

Since the BizTalk Server Application project e.g .btaproj defaults to target framework moniker 4.6.1 when added to the solution you will need to manually change the version manually for BOTH debug and release.
Do not get misled by the create project dialog where it defaults to version 4.7.2

As a workaround ,you can specify /p:TargetFrameworkVersion=v4.7.2 in the MSBuild Arguments column of the MSBuild task.
MSBuild lets you set properties on the command line by using the -property (or -p) switch. These global property values override property values that are set in the project file. This includes environment properties, but does not include reserved properties, which cannot be changed.
For details ,please refer to this document.

Related

Visual Studio 2022 can't find nuget package

What am I doing wrong here?
I have a DLL in .net Standard 2.0, and a console application, also in .net standard 2.0. The DLL is going to eventually be a custom nuget package for internal use by my dev team.
I installed System.Text.Json version 6.0.0 and I get the following runtime error:
"Could not load file or assembly 'System.Text.Json, Version=6.0.0.0".
I can see the nuget package in the location that Visual Studio 2022 is looking in.
Any thoughts on how I debug this?
I tried to explicitly install each of the dependencies, but that did not work.
***EDIT: I just realized that I no longer get that FileNotFound Exception if I explicitly copy that package's DLL into the console app's execution directory, but then I get a new FileNotFound exception for one of its dependencies. When I explicitly copy that DLL, I get another FileNotFound exception for the next dependency, and so on. I just assumed that the dependent nuget packages would get encapsulated in the dll that's using them. Copying each of the dependent DLL's is not really an acceptable solution.
After some investigation, I thought my issue might be related to:
Dependent DLLs of a NuGet package not copied to output folder
or related to:
MSBuild doesn't copy references (DLL files) if using project dependencies in solution
but that was not the case.
The output of my console app project was a DLL, even though it was clearly set to "Console Application". I just assumed that this was a new runtime method for VS2022, but that's not it. My console application Target was set to ".Net Standard 2.0", which is intended for DLL's. Once I set the Target to ".Net 6.0", everything worked as expected, and all the DLL's and packages were copied over correctly.
My DLL, which is being turned into a Nuget package, was properly set to ".net Standard 2.0".

NuGet: references to assemblies in runtimes folder not added

I have a project that targets two different operating systems/frameworks:
net461 on Windows and
netcoreapp2.0 on OSX
I'm trying to figure out how to correctly package this for NuGet. According to this post I should be able to package them like this:
/runtimes/win/lib/net461/myassembly.dll
/runtimes/osx/lib/netcoreapp2.0/myassembly.dll
By when I add the NuGet package to another project, the packaged assemblies aren't added as references to the target project.
Then I read somewhere that you also need to add reference libraries to the /ref folder so I tried this:
/runtimes/win/lib/net461/myassembly.dll
/runtimes/osx/lib/netcoreapp2.0/myassembly.dll
/ref/net461/myassembly.dll
/ref/netcoreapp2.0/myassembly.dll
In this case the assemblies get added as a reference to the target project and I can build it, but the required assemblies aren't copied to the output folder.
The documentation on all this is extremely vague and I'm fairly lost.
What am I missing?
Associated NuGet Issue: https://github.com/NuGet/Home/issues/7316
Update: I've put together a sample project that demonstrates what I'm trying to achieve. In particular see the bottom of the readme, titled "NuGet Packaging".
This is what I've finally figured out/guessed (because as best I can tell there's no official documentation for some of this)
Files added to the /runtimes folder aren't automatically added as references to the target project.
The /ref and /runtime folder should be used in conjunction with each other and only for the .NET Core target. As best I can .NET Framework targets apparently don't support these folders.
The /ref folder is for compile time references and anything added here will be added as a reference to the target project.
Assemblies in the /ref folder don't need to have an implementation - every public API could just throw a not implemented exception. In practice however you typically just take a copy of one of the implementation assemblies and declare it as the compile time API.
I've read (but haven't tested myself) that assemblies in the /ref folder must be "Any CPU" builds. You can use CorFlags utility to patch an implementation assembly for this if necessary.
The /runtimes folder is used to provide an implementation assemblies for any references included in the /ref folder. These assemblies are used at runtime and during deployment.
The /runtimes folder can include additional assemblies that are only required at runtime and don't need to be seen by the client project. These additional assemblies won't be included as references in the target project but will be available for run/deployment.
As mentioned by others, the files in the /runtimes folder aren't copied to the output folder of the build. Instead config files are placed there that tell the runtime how to locate the /runtimes files from the NuGet cache.
For .NET Framework targets (ie: net461) just use the /lib folder as there's no other runtimes for .NET aside from Windows anyway.
Putting this all together, my original example, should have looked like this:
/lib/net461/myassembly.dll (net461/Windows Compile and Runtime)
/runtimes/osx/lib/netcoreapp2.0/myassembly.dll (netcore/OSX Runtime)
/runtimes/win/lib/netcoreapp2.0/myassembly.dll (netcore/Win Runtime)
/ref/netcoreapp2.0/myassembly.dll (netcore/* Compile Time)
I spent a fair amount of time trying your project on OSX in both Visual Studio for Mac and VS Code. I'll try to stick with factual observations without getting into "why don't you do X instead".
The runtimes/{rid}/lib/{tfm}/*.dll paths look ok
target="lib/{tfm}/..." assemblies are automatically referenced, runtimes/... are not
Using target framework of netstandard seems like it would make your package work in both netcoreapp and netstandard projects (e.g. use target="lib/netstandard1.6/..."). Compare with this
runtimes/ seems to be intended for platform-dependent assemblies you'll load at runtime. For example, 32/64-bit native assemblies in runtimes/win-x64/native/ and runtimes/win-x86/native/) loaded with AssemblyLoadContext (another post by McMaster)
Using separate slns for Windows and OSX, or separate platform-specific projects that reference platform-agnostic projects (like Xamarin) would obviate some of the configuration wrangling
I found no documentation on target="ref/...", but you can add Explicit Assembly <references> (inside the nuspec <metadata> block)
Packaged assemblies won't appear in the output directory, but when prepared for distribution with dotnet publish they'll be included:
.NET Core and .NETSTANDARD don't copy dependencies to output directory, they are mapped using deps.json which points to relative paths from local NuGet cache.
This has been a very useful thread to get more information and hints on how to create a NuGet package that references native DLLs, and is consumed in both .NET Framework as well as .NET Core / modern .NET libraries / applications.
My experience so far has been that if this library (let's call it library A) only targets .NET Standard, consuming this library in a .NET Core / 5.0 or 6.0 application does lead to the native assemblies being pulled in correctly from the runtimes folder. In a .NET Framework 4.7 application however, this does not appear to be the case. Unless the runtime is explicitly specified when compiling, e.g.:
dotnet build ... --runtime win-x86
When using library A in a .NET Core or .NET 5.0/6.0 application however, this runtime identifier is not required - all runtimes are made available and the right one is selected at runtime.
If you want library A to be consumed in applications that also target .NET Framework, and you don't want the user to have to specify the runtime explicitly, then it seems to be necessary to:
Target both .NET Standard and .NET Framework
Ensure that the native assemblies end up in the following folder structure in the NuGet package:
"lib/{tfm}/..."
While the .NET documentation referenced by tm1 earlier here talks about how to get this to work using nuspec files, it is less clear how to do so in the SDK .csproj format. I managed to do this in the NLoptNet project, see the relevant .csproj file here. Final relevant point (in addition to the two bullets above):
Use "<None Include" rather than "<None Update" to add the native assemblies
So far - this works, but there is one quirk - as you can see here it generates warning MSB3246 when consuming library A in a .NET Framework application. See also this Stack Overflow post. This leads me to believe that maybe the above is not the right approach, and therefore to some questions:
Is this the intended way to consume library A in .NET Core, modern .NET and .NET Framework applications?
Should one always specify the runtime identifier when using dotnet build / dotnet test?
Can you try to target .NET Standard 2.0 instead of net461 and netcoreapp2.0? Libraries built against netstandard2.0 should work with .NET Core 2.0 and .NET Framework 4.6.1: https://learn.microsoft.com/en-us/dotnet/standard/net-standard
Are you using the new csproj format? If so it has built in support for multiple target frameworks.
For example running dotnet pack against a .csproj file with this content:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>net461;netcoreapp2.1;netstandard2.0</TargetFrameworks>
</PropertyGroup>
</Project>
will result in a .nupkg that works for .NET Framework 4.6.1, .NET Core 2.1 and .NET Standard 2.0.
Various trick can then be used to include specific parts for each framework depending on what's available.
I'm trying to solve the same problem.
The solution proposed by you works fine, but there is one question ...
The case of Win and net46 is clear. And now I need to add a reference to the assembly in the project for a netcoreapp for the Win and for Linux. The problem is that this is a DIFFERENT assembly with the SAME name. Those my package looks like this:
/lib/net461/myassembly1.dll (net461/Windows Compile and Runtime)
/runtimes/ubuntu/lib/netcoreapp2.0/myassembly2.dll (netcore/Ubuntu Runtime)
/runtimes/win/lib/netcoreapp2.0/myassembly1.dll (netcore/Win Runtime)
/ref/netcoreapp2.0/???
Update: Actually, the myassembly1.dll and myassembly2.dll are both called myassembly.dll. But to show that one is assembled for Windows, and the second one for Linux, I will leave here such a name.
The most interesting thing is that I tried to put any assembly in the folder ref, and it works on both Windows and Linux.
This version works on both systems
/lib/net461/myassembly1.dll
/runtimes/ubuntu/lib/netcoreapp2.0/myassembly2.dll
/runtimes/win/lib/netcoreapp2.0/myassembly1.dll
/ref/netcoreapp2.0/myassembly1.dll
And this too
/lib/net461/myassembly1.dll
/runtimes/ubuntu/lib/netcoreapp2.0/myassembly2.dll
/runtimes/win/lib/netcoreapp2.0/myassembly1.dll
/ref/netcoreapp2.0/myassembly2.dll
But I think this is not right and I was wrong somewhere.

Can Powershell Tools for Visual Studio 2015 projects make Project References

I have a Powershell Tools for Visual Studio 2015 project that is a script module. I would like to add a project reference to a .NET 4.5 class library that is also a project in the same solution. From a visual perspective the dependency is listed under the references tree in the powershell project but it has the warning overlay icon on it. When running the pester tests they error out with a type resolution error (Cannot find type [IHE.Cda.TrifoliaParser]: verify that the assembly containing this type is loaded). I cannot find any documentation which indicates whether what I am attempting is even possible. Thus my question is whether it is possible or if the references list is just a artifact of being in visual studio.
Solution Explorer View
The References are an artifact of VisualStudio. It would be possible to generate an Import-Module <PathToThe>.dll line on top of every script in your project, but that's very obtrusive, and not every script will need all the dependencies.

MSBuild: What do I need on my build server to Build my project

I am looking to build projects on a build server (right now it is just a server but I want to use MSBuild to build projects on there). I want to use PowerShell scripts to get my code from a repository (Doesn't matter what type), put the source into a common directory, put all dependencies into a common directory (similar to how it is build in my workspace on my local machine), build everything and put all the deployable binaries into a bin which I will be moving to the deployment directories using other Powershell scripts.
I assume I am going to have to have MSBuild installed on the server that I will doing all of this on. Do I need to have the .Net framework installed on that server to accomplish this? Do I just need the EXE to have this work? Is there a good way to managed dependencies? Should I have them in a specific folder?
A lot of the core .NET assemblies are stored in the Windows Global Assembly Cache (GAC). You won't have to worry about those. Yes, you'll need the Microsoft .NET Framework installed, in order to compile (build) .NET projects. I believe msbuild.exe is included with the .NET Framework, so you'll find it under a location such as: C:\windows\Microsoft.NET\Framework64\v4.0.30319\msbuild.exe.
Your PowerShell script will have to copy any external dependencies (assemblies (DLLs and EXEs), .NET resource files, image files, external binaries, etc.) to the appropriate target location after compilation, such that the software executes successfully. You'll need to work with your software development team to determine [comprehensively] what those dependencies are.
MsBuild.exe moved, and is now part of Visual Studio as of v2013.
To get the latest version of MsBuild.exe without having to install Visual Studio 2013, download Microsoft Build Tools 2013

Nuget - Package restore is disabled by default. To give consent, open the Visual Studio Options dialog. (Nuget package restore on a build server)

So, the error I'm getting when my build server builds my project is:
Package restore is disabled by default. To give consent, open the
Visual Studio Options dialog.
I'm aware of what this error means and how to resolve it. The problem is I cannot change anything on the build server - my company won't allow it. Additionally, creating an environment variable called EnableNuGetPackageRestore and setting it to true is not an option because that involves modifying the build server.
My question is: is it possible to simply check all of the NuGet packages that are part of a solution into source control so then the build server won't have any reason to go out and re-download them? If so, then perhaps you could explain why this error is still happening, when I've verified that all of the NuGet packages (.nupkg) are in the packages folder in source control:
Second Question: Forgive my ignorance, but what is the reason for the "package restore" feature? Is it to ensure that each package is up to date with the latest version of that package? It seems to me that this "feature" should be a setting that shouldn't hinder building a project on a build server. In my mind, if we want the build server to look for newer packages, then sure, do it, otherwise if I have all my packages in source control and we tell the build server somehow to NOT look for newer packages, that sounds reasonable to me.
So, my situation specifically was I downloaded the source code for the actual Nuget site (to create an internal implementation of Nuget in my company), and when I tried to deploy it, that's when I got the error above.
What I had to do was:
Delete the .nuget folder.
Within your file system (not via Visual Studio), modify the .csproj files (delete where it said <packageRestore>true</packageRestore>, as well as where it imported the project that had nuget.targets in the line - just do a "find" for "nuget.targets", and delete all lines that have an import.
Save your .csproj file changes.
Check in your changes into TFS.
Deploy your solution.