Restoring NuGet packages to the cache - .net-core

I have a .net-core application that works on my machine but when I deploy it on another one, it complains about missing packages and points me to the TheApp.deps.json.
My theory is that on my machine the app looks for packages in some NuGet cache where they were probably installed by the IDE during development because the app's output-dir contains only a couple of internal dlls so the other nuget.org dependecies are definitely missing.
I'm building the app with
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp2.2</TargetFramework>
<RuntimeIdentifier>win10-x64</RuntimeIdentifier>
</PropertyGroup>
and then xcopy it to the other machine.
Question
Is there a way to restore or install the missing packages to the cache on the target machine based on the *.deps.json file?

dotnet build (and the F5/Build function in Visual Studio) simply build the code that you have provided via your source files (i.e cs, fs, vb, etc.).
Whereas dotnet publish (and the Build > Publish function in Visual Studio) does a full package restore, builds your source code, and resolves any external dependencies before moving the output to a specific directory ready for publishing to another machine.
The description on the dotnet publish command documentation states:
dotnet publish compiles the application, reads through its dependencies specified in the project file, and publishes the resulting set of files to a directory. The output includes the following assets:
Intermediate Language (IL) code in an assembly with a dll extension.
.deps.json file that includes all of the dependencies of the project.
.runtime.config.json file that specifies the shared runtime that the application expects, as well as other configuration options for the runtime (for example, garbage collection type).
The application's dependencies, which are copied from the NuGet cache into the output folder.
dotnet build is only really useful for building on your development machine, and when used in conjunction with dotnet run against a project file.

Related

AssemblyInfo ingrored when building from GitLab-Runner

On a Windows machine there is a GitLab-Runner run from a domain user with admin rights. When I log as this user and call dotnet build -c release to build an ASP.NET Core app, the dll has all the information from the AssemblyInfo.cs file. When I do the same as part of a CI job, the produced dll is missing all this information (for example the version number).
The AssemblyInfo.cs file is not part of the repository, instead, it is produced by a prebuild event (using gitWCRev.exe tool). However after running some tests I can see that the AssemblyInfo.cs is actually generated when the job is run by the runner.
Any help as to why the file is ignored and how to overcome this issue would be appreciated.
At first I thought that this might be related to Pre-build task of Visual Studio project fails in GitLab Runner issue, but I don't get any build errors.
On the same machine, I build a .Net Framework app which has the same AssemblyInfo setup, but is compiled using msbuild /property:Configuration=Release by the runner and the produced dll file has all the expected information.
It turns out the problem was partially related to the AssemblyInfo.cs file not being part of the repository.
SDK-style csproj normally don't list the files in the project, but figure them out based on the folder contents. When dotnet build was run, AssemblyInfo.cs wasn't present in the project directory (GitLab-Runner usually clears out files not present in the repository before starting a job/pipeline), so build tools had no idea they needed to load it. It made no difference that the file was being created by the build tools.
The solution proved to be creating an empty AssemblyInfo.cs file before running dotnet build. This way build tools knew they needed to compile it. Actual compilation still happened after prebuild events, so all the needed information was there.
I created the empty AssemblyInfo.cs file using PowerShell:
New-Item -Path "Properties/AssemblyInfo.cs" -ItemType File
Also, checking the build logs helped me finally figure it out. To get the build logs I've called build tools like this:
dotnet build -c release /flp:v=diag
The .Net Framework app didn't have this problem because it wasn't an SDK-style project. All the files needed for compilation were listed in the project file and build tools knew to load them, even if they were created during the prebuild event.

How to pack .NET Core projects recursively without running pack on the entire solution?

I have a solution of a hundred plus .NET Core projects. Not all of them needs to be packed, but only those which are transitive dependencies of a few special projects.
However, when I run dotnet pack it attempts to pack all kinds of projects that it should not and there are errors here and there. I would like instead to run pack on the special projects only in a recursive fashion, so that only them and their transitive dependencies (project references, of course) are packed.
I figured I can implement it by scripting around the dotnet list reference command, but it does not sound right. There must be a better way to do it.
EDIT 1
The solution must work on the command line where we have dotnet and msbuild and possibly nuget, but no VS IDE.
You can modify your project settings to generate *.nupkg file during dotnet build, without explicit dotnet pack call. And as soon as dependencies get builded automatically when "parent" project builds - you will receive nuget packages prepared for all dependencies too when you run dotnet build for "parent" project only.
For each project that should produce nuget package add this lines into csproj file:
<PropertyGroup>
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
</PropertyGroup>
Or, instead, you may enable checkbox "Generate NuGet package on build" from Visual Studio, in project properties ("Package" tab) - this will add same line into project file.

Compile a .NET Core application as an EXE file using Visual Studio 2017

I created a .NET Core application (v1.1) in Visual Studio 2017. When I compile it, I get a DLL file produced instead of the expected EXE file for the built project. I did check the csproj file and confirmed the output type is set to exe, but no dice.
Why is Visual Studio 2017 is still producing a DLL file?
I'm sure it's a quick setting somewhere that I forgot...
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp1.1</TargetFramework>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
<PlatformTarget>AnyCPU</PlatformTarget>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\Core.EF.SqlServer\Core.EF.SqlServer.csproj" />
</ItemGroup>
</Project>
Update 2019:
.NET Core 3.0+ projects will now include an executable for the platform you build on by default. This is just a shim executable and your main logic is still inside a .dll file.
But .NET Core 3.0 also introduced single-file deployments so deploying with
dotnet publish -r win-x64 -p:PublishSingleFile=True --self-contained false
will create a single .exe file containing all your dependencies. You can change --self-contained to true to also include the .NET Core Runtime as well so .NET Core does not need to be installed globally on the target machine.
Original
.NET Core applications are supposed to be .dllfiles. OutputType set to Exe in this case means "executable" and does everything necessary to ensure that the output is runnable (entry point from Main() method, .runtimeconfig.json file). The resulting DLL file is meant to be run using:
dotnet yourapp.dll
This DLL file works across all platforms that are supported by the .NET Core runtime (Windows, Linux, and macOS). This is called a "portable" or "framework dependent" deployment.
If you want really a .exe file, consider self-contained deployments. This will create an output that contains its own copy of the .NET Core runtime and an yourapp.exe file - but it also increases the size of the published application and it needs to be updated when new versions of the runtime are released.
Also, the resulting application only works on the operating system published for.
Refer to .NET Core application deployment for more details on the deployment options and how to set them up.
In Visual Studio 2017:
Right click on your project and select Publish (In Visual Studio 2019, click on menu Build → Publish <projectName>)
Select 'Folder' and create a new profile
In tab 'Publish', click 'Configure...'
Select Deployment Mode: Self-contained, Target Runtime: win-x86 (or win-x64)
Save
Publish
In the folder <Your project>\bin\Debug\netcoreapp2.1\win-x86\ you will see the EXE file:
Starting with .NET Core 2.2 you can build framework-dependent executables
Although building a self-contained deployment can be a good solution, it has its own drawbacks. (See R.Titov and Martin Ullrichs' answers on SCD-s.)
Fortunately, .NET Core 2.2 supports the building of so called framework-dependent executable-s, that are essentially a wrapper binary (.exe on Windows) around the standard dll-s.
This way you have all the advantages (and disadvantages) of the standard framework-dependent deployment (again, see Martin's answer), but you have a convenient way to launch it, without having to call it through the dotnet CLI.
You can publish your app as a Framework-Dependent Executable using the following syntax:
dotnet publish -c Release -r <RID> --self-contained false
Where RID is the usual runtime identifier, e.g. win-x64 or whatever platform you wish to build for (see the catalog here).
That's how you do a self-contained publish with command-line in any OS:
dotnet publish C:\src\App\App.csproj -c release -r win-x64 -o output-win-x64
Besides, you might want to get the output decreased from typical ~60 MB for a simple Hello World app to ~30 MB by using ILLink.
Also, you might want to go further and get a single .exe file of a size at around 5 MB and use ILCompiler. See this reply.
The other answers are good, but what I find sometimes convenient is:
Not have it self-contained because the target machine is likely to have .NET Core of the correct version installed. This cuts on number of the DLL files I need to ship.
Not have to specify dotnet on the command line
For this, a bat file wrapper can be used, similar to these lines:
#ECHO OFF
REM see http://joshua.poehls.me/powershell-batch-file-wrapper/
SET SCRIPTNAME=%~d0%~p0%~n0.dll
SET ARGS=%*
dotnet "%SCRIPTNAME%" %ARGS%
EXIT /B %ERRORLEVEL%
If your application ends up in yourapp.dll, name the bat file yourapp.bat and place it along side the DLL file. Now instead of dotnet yourapp.dll params you can call yourapp params.
Note that the context of this answer is in-house tooling, so all the developers using the utility will have a pretty standard development machine setup. If this is to be distributed to an external customer who is running who knows what on their boxes, the self-contained option is far superior.

Change .NET Core application generated exe description

I have created a .NET Core application. When I do:
dotnet publish -r win81-x64
All files needed to execution are deployed in the following folder:
\bin\Debug\netcoreapp1.1\win81-x64\publish
There, among all the files I have a dll file with the name Example.dll and the exe file named Example.exe. Now, my problem is when I execute the exe, in the task manager the application description says:
dotnet
I would like to change that to Example, for that I tried to edit my csproj to contain the following:
<PropertyGroup>
<OutputType>Exe</OutputType>
<Version>1.0.0.0</Version>
<Description>Example</Description>
<TargetFramework>netcoreapp1.1</TargetFramework>
<RuntimeIdentifiers>win81-x64</RuntimeIdentifiers>
<Satellite_Description>Example</Satellite_Description>
</PropertyGroup>
But it doesn't seems to have any affect in the generated exe file, only ind the dll. How can I change the exe description?
Currently this is not possible in the build process.
Unlike classic .NET projects, this .exe file isn't actually compiled but is a pre-built binary (dotnet.exe, in 2.0 apphost.exe) acquired via a NuGet package and copied/renamed to the publish output.
There is an issue on GitHub about changing the description after being launched, but at the time of writing it is not assigned to a milestone of an expected release.
There is known issue in populating assemblyino manifest into EXE file. Looks like will be supported in .net core 3.0 release.
see: https://github.com/dotnet/sdk/issues/1899

Where is the default output folder for dotnet restore?

I tried to create a simple .net core using commandline
dotnew new
in a certain folder called netcoreExample and I could see that there are two files created which are program.cs and project.json. Then I add Microsoft.EntityFrameworkCore to dependencies entry in project.json
When I try to run the command
dotnet restore
it shows the package is restores successfully. However, when I inspect the folder where I run dotnet restore from, I didn't see the "packages" folder which is usually created when with the old C# projects running Nuget restore.
I wonder where the dotnet restore output all of the dependencies to.
On Windows by default its %userprofile%\.nuget\packages. I wish dotnet restore -verbosity <verbosity-level> printed out where it was restoring to.
On other OSes its like <HOME-environment-variable-location>/.nuget/packages

Resources