Let us imagine that we have two projects:
AspNetRunnerProject – an ASP.NET 6 project which is capable of loading DLLs of classlibs and serves as a driver/executor of such classlibs.
ClassLibraryProject – a .netstandard 2.1 classlib project which uses AspNetRunnerProject's nuget as its driver
What I've been able to do so far is to publish ClassLibraryProject as a self-contained app. This way all the DLLs that are needed (any kind of NuGet package or .NET 6 runtime DLLs) are bundled inside a common folder and the app can be executed with dotnet AspNetRunnerProject.dll. This way the driver project loads the classlibs it needs and runs it all.
Is it possible to publish the ClassLibraryProject (which has a NuGet reference towards the AspNetRunnerProject) as a framework dependent deployment instead of self contained app so that it can still be run with dotnet AspNetRunnerProject.dll?
If I try to execute something like the last command I get the info that "AspNetRunnerProject.deps.json" file does not exist, because the file that exists is actually "ClassLibraryProject.deps.json"?
Simple copying of this file to desired name does not solve the issue.
After researching for a few days I came to the following conclusions:
Find the ClassLibraryProject.runtimeconfig.json file in the published artifacts and rename it to AspNetRunnerProject.runtimeconfig.json
Execute the app with dotnet AspNetRunnerProject.dll
Alternatively it is possible to have a global appname.runtimeconfig.json file which could be used across multiple such projects.
For more info check https://learn.microsoft.com/en-us/dotnet/core/runtime-config/#runtimeconfigjson
Related
I am migrating a medium-sized Win10 app (.NET Framework 4.8) to net5-windows. The solution contains about 30 projects.
While the migration process worked rather straightforward in Visual Studio 2019 (Version 16.8.3) the only problem remained to package everything in a self-contained exe. Instead of struggling with the project entries in VS, I am using the command-line method discussed by Scott Hanselmann in his blog. This also worked smooth and produced an exe of about 140MB size.
One issue remains: Not all of the system dll's are included in the exe. The following ones have to be copied manually to the directory of choice:
Without these DLLs the app does not work.
My question: What is the reason for this behavior, and how can these dll's be included in the self-contained exe?
To include a system DLLs into single file app you should use IncludeNativeLibrariesForSelfExtract property or /p:IncludeNativeLibrariesForSelfExtract=true switch for dotnet publish command, as mentioned in single file publish design document
I am looking for a way to list all NuGet libraries I have (manually) in ASP.Net Core 2.2.
I found a solution for .NET in general which involves parsing the packages.config. When launching via IIS however, the executable is in a completely different directory, preventing me from easily accessing the file.
Another option was to get all assemblies, but this includes System.* assemblies and custom assemblies I do not want to display.
Parse the output of dotnet list package. I think it can be done with 3 or 4 regexes. There's ongoing, but low-priority work to make it work with packages.config projects projects, and there's already a request to make the output more easily parsable.
I have created a system which loads dynamically a library and executes it's main class.
Everything works perfect, the problem I have is how to publish this DLL with all it's dependencies. As no executable project is referencing it I have to manually retrieve the dependencies: try to load the library, check the needed DLL's, go to the NuGet cache folder, copy the libraries, try again, check if it complains about more dependencies and so on until it has all the required libraries.
This is a true pain and I haven't found any information on how to do this, is it possible or am I stuck with this?
The library is a .net standard 2.0 library, I did this before with .net classic and the output folder always contained all the required libraries even the ones comming from a NuGet package, but with .net standard something has changed and now only libraries from referenced projects are being copied, no referenced NuGet package is being copied to the output folder.
Cheers.
Try:
dotnet publish
All the dependent libraries should be copied to the publish output folder.
At the time of writing, it looks like it's by design and there's quite some fuss and confusion about it, see logged issue on GitHub.
Moreover, when publishing a NuGet package for project A referencing project B,
B becomes a NuGet dependency in A; B's assemby is not included in A's NuGet package.
I deal with it by publishing my own NuGet packages.
I only don't like it to have a NuGet package for project B if that one is only relevant to be used with/by project A, as it will appear seperately in my NuGet feed.
TLDR: Convert your Class Library project into an Application, publish the application, and use application DLL as a library.
The long of it:
I tested this approach by deploying a full build with a plugin with many external dependencies to Ubuntu 18.04 and it ran perfectly.
Create a new project of type Console Application instead of Class Library. Put all your library code files into the Console Application and add the dependencies. Get rid of your original Class Library project (you don't need it anymore). Finally, publish the Console Application. You will get a DLL with all of the dependencies. You can use this DLL like any other DLL.
I suggest naming the console app project with "Library" on the end of it and adding a README just to document its not really an application even though the project is configured to build as one.
Is it possible to make Visual Studio to copy all dependencies of referenced projects into the output path?
Example
In the Solution, Project A (Library, .NET Standard) defines some functions and is dependent on Library L1 (via NuGet) and Library L2 (local .dll, referenced and copied to project)
Project B (Console Application) references Project A.
When building B, The output folder contains all direct dependencies of B and A.dll. L1 and L2 are not available in the output. Therefore, the program does not work correctly.
How can I force VS to copy also L1 and L2 to the output of B?
The only way I found so far is packing A as NuGet, but this seems to be unnecessary overhead and uncomfortable. I think I am just forgetting something everyone else seems to know...
Edit (clearifying Example)
My solutions consists of two projects.
Project MongoWrapper
.NET Standard 2.0 class Library
depends on NuGet MongoDB.Driver package
Actually uses this dependency (no zombie dependency)
Project ConsoleUser
.Net Framework 4.6.1 Console Application
References MongoWrapper project
Actually uses MongoWrapper
Observation
When debugging the ConsoleUser application, it compiles and starts. During runtime, when it calls a method in the MongoWrapper which uses the MongoDB.Driver, the application crashes, as the MongoDB.Driver dependency was not copied into the output folder of the ConsoleUser.
How to fix this?
The problem was introduced by the usage of .Net Standard library and a .Net Framework application.
TLDR
Open the .csproj file of the .Net Framework project with a text editor. Inside the first PropertyGroup add the line
<RestoreProjectStyle>PackageReference</RestoreProjectStyle>
Save the file, reopen Solution in Visual Studio and perform Clean & Build
Dependencies in different project file versions
.Net Framework projects use an old version of the .csproj project files. References/Dependencies are stored in the additional packages.configfile. By default, building a .Net Framework project makes the system to search for a packages.config file in the referenced projects. If no such file is found, the build task treats the referenced project as having no dependencies. Therefore, in the example, the MongoDB.Driver library is not added.
By adding the proposed line in the .csproj project file, the build task searches the project file of the referenced project for dependencies, where they are stored in .Net Standard project files.
.Net Core projects by default search for the newer project file structure.
The default behavior for new projects can be set in the Options -> NuGet -> General -> Package Management
Is it possible to make Visual Studio to copy all dependencies of referenced projects into the output path?
Yes.
This is what publishing the application does - it prepares the application for deployment. When you publish, it will include all of the dependencies that the application requires to run in the output.
Use the Publish tool to deploy to a local folder. The exact options available depend on your app type. In Solution Explorer, right-click your project and choose Publish, and then choose Folder. For more information, see Deploy to a local folder.
Tutorial: Publish your Hello World application with Visual Studio 2017
Also see: .NET Core application deployment.
My end goal is to create a cross-platform (non-web) console application, so I'm exploring .NET Core right now.
In my previous .NET projects, I did all the development inside Visual Studio, but I also created a batch/MSBuild file so I could build the whole project (including setups, NuGet packages, zip files with binaries etc.) with one single click. Here's an example from a previous project.
In the end, I want to do something similar with my .NET Core test project.
But right now I'm failing at the first step: I'm unable to build it outside Visual Studio, so that the result works on another Windows machine without .NET Core installed.
(in the first step, I'm ignoring the cross-platform part - I'll be happy to get it to work on Windows)
What I have
I managed to get it to work inside Visual Studio 2015 Community Edition as follows:
create new project in Visual Studio: "New Project" ⇒ "Web" ⇒ "Console Application (Package)"
create new publish profile inside Visual Studio ("Build" ⇒ "Publish" in the menu).
This will create a PowerShell script (and an XML file with settings)
Here's my test project on GitHub.
When I do "Build" ⇒ "Publish" in the menu again, Visual Studio apparently executes the previously created PowerShell script again.
The result is slightly over 90 MB, consists of 825 files in 598 folders, and looks like this:
When I copy it on another machine (Win 7 / .NET 4 installed / .NET Core not installed), it works.
What I tried to get the same result outside Visual Studio
1. dotnet publish
This answer and this answer sound like I can use dnu publish to achieve the same result via the command line.
I understand that parts of .NET Core are still moving targets right now, so apparently dnu is now dotnet instead.
So I tried to execute dotnet publish (and created a batch file) for it:
dotnet publish "%~dp0\src\CoreTestVisualStudio" -c Release -r win7-x64 -o "%~dp0\release\cli"
The result consists of an .exe file and a bunch of DLLs, only 25 files and 1.5 MB, all in one single folder:
Obviously the .NET Core runtime is missing here, and as expected, this app crashes when I try to execute it on a machine without .NET Core installed (the same one as mentioned above).
2. The PowerShell script from the publish profile
I tried to execute the PowerShell script (which was created when I created the publish profile) outside Visual Studio, but it failed because the script expects some parameters and I don't know what to pass:
param($publishProperties, $packOutput, $nugetUrl)
There's also this line in the script:
# to learn more about this file visit http://go.microsoft.com/fwlink/?LinkId=524327
...but the link just points to the landing page of the .NET Web Development and Tools Blog.
TL;DR
What am I doing wrong?
I know that the first release of .NET Core mainly focuses on ASP.NET, but as I understood it, ASP.NET Core apps are just console apps as well, so I thought a basic console app would work now.
On the other hand, most of the console app "getting started" docs are still missing, so maybe it's just too early and dotnet publish for console apps is not finished yet?
Edit after a few days: I'm suspecting that I'm doing nothing wrong and that it's an issue in the.NET Core command line tools, so I posted it to the command line tools' issue tracker.
Problem solved!
I posted it on the issue tracker of the .NET Core command line tools, and it turned out that it was a bug in dotnet publish - it didn't bundle the C++ runtime, which is needed to execute the compiled app on a machine without .NET Core installed.
The temporary solution was to install the C++ runtime.
The "real" solution was made in a pull request three days ago, which is included in the latest installer now.
With this version, dotnet publish does bundle the C++ runtime, so the result will work on a machine without .NET Core.
For dnu:
There's an option for dnu publish called --runtime that specifies the runtime to include when publishing. You would use the full runtime name with the command, e.g.:
dnu publish --runtime dnx-clr-win-x86.1.0.0-rc1
For dotnet:
You don't need to specify the runtime or framework versions -- by default, dotnet publish will use the framework from project.json and the current runtime flavor. However, the documentation states that:
dotnet-publish command also requires certain dependencies in the project.json to work. Namely the Microsoft.NETCore.Runtime package must be referenced as a dependency in order for the command to copy the runtime files as well as the application's files to the published location.