Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to distribute a .net core 2.0 console application on osx

I am using Visual Studio for Mac, my application is written, it does what I want. The user's target platform is OSX. It relies on 2 Nuget Packages with their own dependencies, specifically:

  • NetMQ
  • Microsoft.Extensions.Configuration.CommandLine

I run the following command to build the application:

dotnet build -c Release -r osx.10.11-x64

The output tells me it succeeded and shows me where it put the files.

Contained in that folder are the following files, this folder is what I assume I distribute to my user, but that leads to errors hence this question:

MyApp <---- executable
MyApp.deps.json
MyApp.dll
MyApp.pdb
MyApp.runtimeconfig.dev.json
MyApp.runtimeconfig.json
libhostfxr.dylib
libhostpolicy.dylib

So my user receives this and they have the dotnet runtime installed. When they go to run the executable (Here MyApp aka ./MyApp)they receive the following error:

An assembly specified in the application dependencies manifest (MyApp.deps.json) was not found:
package: 'AsyncIO', version: '0.1.26'
path: 'lib/netstandard1.3/AsyncIO.dll'

Now, AsyncIO is a dependency of NetMQ so that's where that is coming from. However, I can ./MyApp from anywhere on my filesystem and it works. So I'm left to think that the Nuget packages being installed on my system as the development system are still accessible where as on the new users's system they are not. I haven't really found any documentation pertaining to distribution from a Mac. The only thing I can think to do right now is to distribute the project files instead and instruct the user to run:

dotnet run -p MyApp.csproj

Which, if I understand correctly, will install the nuget packages.

I can also have the user use:

dotnet MyApp.dll

I have seen this form around in my googling. That begs they question though, of why an executable is generated though. Beggars can't be choosers, if the way to do it dotnet <dll> I'm happy, I just need to get it to run.

There has to be something I'm missing here or else this detail, distribution, of netcore2.0 apps was just overlooked?

In digging around some more this also seems like a useful command:

dotnet publish -c Release --framework netcoreapp2.0 --runtime osx.10.11-x64

And that adds ALL kinds of DLLs and all of the dependency DLLs as well. Words like publish make me think this is the way this needs to go.

These 2 links are where I am primarily getting my info:

https://docs.microsoft.com/en-us/dotnet/core/deploying/deploy-with-cli https://docs.microsoft.com/en-us/dotnet/core/tools/project-json-to-csproj

like image 403
AJ Venturella Avatar asked Oct 19 '17 12:10

AJ Venturella


People also ask

How do I publish a .NET Core console application?

Right-click on the HelloWorld project (not the HelloWorld solution) and select Publish from the menu. On the Target tab of the Publish page, select Folder, and then select Next. On the Specific Target tab of the Publish page, select Folder, and then select Next. On the Location tab of the Publish page, select Finish.


2 Answers

You have the right intuition about the difference between build and publish.

dotnet build will build the application for local development. One aspect is that the build will assume all dependencies are available via local nuget cache.

dotnet publish will build the application for deployment to other machines. This deals with dependencies explicitly.

There are two modes of publishing: self-contained deployments and framework-dependent deployments.

Framework-dependent deployments work by relying on a framework already present on the system. If you publish your application in this mode, you will only include your application and its dependencies.

To publish in a FDD, use:

dotnet publish -c Release --framework netcoreapp2.0

Self-containted deployments, in contrast, will include the entire .NET Core runtime and your application and its dependencies.

To publish a SCD, use:

dotnet publish -c Release --framework netcoreapp2.0 --runtime osx-x64

(Btw, please do use the more general osx-x64 rather than the very specific osx.10.11-x64)

Do you see the difference between the two modes of publishing? It is just the presence/absence of the runtime id. When, in your example, you use --runtime flag, you are asking your application to be published as a SCD, which ends up including all of .NET Core runtime as well. Just leave it out and you should get what you expect.

When you publish your application as a FDD, you should see a directory called bin/Release/netcoreapp2.0/publish in your source code. Use that directory (and not bin/Release/netcoreapp2.0/) as your release archive. Your users should just run dotnet ./path/to/publish/MyApp.dll.

Take a look at https://docs.microsoft.com/en-us/dotnet/core/deploying/ for more information.

like image 66
omajid Avatar answered Oct 10 '22 02:10

omajid


Following up on @omajid's answer,

If you want to pack your console application in a nice and tidy package where you just 'click' it and it opens a terminal to start your app... heres an example app (with a tree icon):

You first want a folder/file structure like this (begin the mkdir!):

enter image description here

Then in info.plist, just paste in

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>CFBundleDevelopmentRegion</key>
    <string>English</string>
    <key>CFBundleExecutable</key>
    <string>launcher</string>
    <key>CFBundleIconFile</key>
    <string>trees.icns</string>
    <key>CFBundleInfoDictionaryVersion</key>
    <string>6.0</string>
    <key>CFBundlePackageType</key>
    <string>APPL</string>
    <key>CFBundleShortVersionString</key>
    <string>2.2</string>
    <key>CFBundleSignature</key>
    <string>xmmd</string>
    <key>CFBundleVersion</key>
    <string>2.2</string>
    <key>NSAppleScriptEnabled</key>
    <string>NO</string>
</dict>
</plist>

Get your 'trees.icns' from some .icns site off the internet.

then copy everything from dotnet publish -c Release --framework netcoreapp3.1 --runtime osx-x64 command into the osx-x64 folder (theres going to be a TON of .dll files in here.. i had ~197)

enter image description here

Finally in launcher add the following script:

#!/bin/sh

# Set the working directory
DIR=$(cd "$(dirname "$0")"; pwd)

# Run the application
echo "running from $DIR/osx-x64"

open -a Terminal $DIR/osx-x64/dotnetconsole

Then Voila... go into your finder and click the "MyApp" application enter image description here

reference: packaging jar tutorial

like image 25
Ryu S. Avatar answered Oct 10 '22 02:10

Ryu S.