如何在OSX上分发.NET Core 2.0控制台应用程序

16

我正在使用Visual Studio for Mac,我的应用程序已经编写完成,它能够满足我的要求。用户的目标平台是OSX。它依赖于两个具有自己依赖关系的Nuget包,即:

  • NetMQ
  • Microsoft.Extensions.Configuration.CommandLine

我运行以下命令来构建应用程序:

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

输出告诉我它成功了,并向我展示了文件的放置位置。

该文件夹中包含以下文件,我认为这个文件夹是我要分发给用户的,但这会导致错误,因此提出了这个问题:

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

所以我的用户收到了这个,他们已经安装了dotnet运行时。当他们尝试运行可执行文件(这里是MyApp,也就是./MyApp)时,他们会收到以下错误:

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'

现在,AsyncIONetMQ的一个依赖项,这就是它来自哪里。但我可以从我的文件系统的任何地方运行./MyApp并且它可以工作。所以我认为在开发系统中安装的Nuget包仍然可以访问,而在新用户的系统上则不行。我没有找到关于从Mac进行分发的任何文档。现在我能想到的唯一办法就是分发项目文件,并指示用户运行:

dotnet run -p MyApp.csproj

如果我理解正确的话,这将安装NuGet包。

我还可以让用户使用:

dotnet MyApp.dll

我在搜索中看到过这个表单。尽管如此,问题是为什么要生成可执行文件。但如果用dotnet <dll>的方法可以运行,那我就很开心了。

我可能遗漏了一些东西,或者说这个细节,即Netcore2.0应用程序的分发,被忽视了?

在进一步挖掘中,我还发现了一个有用的命令:

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

这会添加所有类型的DLL和所有相关的依赖DLL。像publish这样的词使我认为这是必须采取的方式。

以下两个链接是我主要获取信息的地方:

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

3个回答

20

您对 buildpublish 之间的区别有正确的直觉。

dotnet build 将为本地开发构建应用程序。其中一个方面是,构建过程将假定所有依赖项都可以通过本地NuGet缓存获得。

dotnet publish 将为部署到其他机器上的应用程序进行构建。这会明确处理依赖项。

有两种发布模式:自包含部署和基于框架的依赖项部署。

基于框架的依赖项部署 通过依赖于系统中已经存在的框架来工作。如果您以此模式发布应用程序,则只包括您的应用程序及其依赖项。

要在 FDD 中发布,请使用:

dotnet publish -c Release --framework netcoreapp2.0

自包含部署则会包含完整的.NET Core运行时以及您的应用程序和其依赖项。

要发布SCD,请使用:

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

(顺便说一句,请使用更通用的osx-x64而不是非常具体的osx.10.11-x64)

您是否看到了这两种发布模式之间的区别?它只是运行时 ID 的存在/不存在。在您的示例中,当您使用--runtime标志时,您要求应用程序作为 SCD 发布,这最终会包含所有 .NET Core 运行时。只需省略它,您应该得到您期望的结果。

当您将应用程序作为 FDD 发布时,应该在您的源代码中看到一个名为bin/Release/netcoreapp2.0/publish的目录。使用那个目录(而不是bin/Release/netcoreapp2.0/)作为您的发布归档文件。您的用户只需运行dotnet ./path/to/publish/MyApp.dll即可。

请参阅https://learn.microsoft.com/en-us/dotnet/core/deploying/ 以获取更多信息。


1
谢谢。有没有办法创建一个轻量级的SCD?我想要创建一个最小化的SCD。目前,即使是一个简单的“Hello World”也有60多MB的大小,而它并不需要整个.NET Core运行时。 - Jabba

5

继续@omajid's answer的内容,

如果你想将控制台应用程序打包成一个漂亮整洁的包,只需“点击”它即可打开终端启动应用程序...这是一个带有树形图标的示例应用程序:

首先,您需要像这样的文件夹/文件结构(开始mkdir!):

enter image description here

然后在info.plist中,只需粘贴即可。
<?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>

从互联网上的.icns网站获取您的“trees.icns”。
然后将dotnet publish -c Release --framework netcoreapp3.1 --runtime osx-x64命令中的所有内容复制到osx-x64文件夹中(这里会有大量.dll文件..我有约197个)。

enter image description here

最后在launcher中添加以下脚本:

#!/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

然后,进入您的Finder并单击"MyApp"应用程序在此输入图像描述

参考:打包jar教程


1

他最初的观察仍然适用,即我所看到的是,可执行文件'MyApp'并非真正独立的二进制文件。如果将该二进制文件移动到另一个目录,则会出现找不到'MyApp.dll'的错误。

具体而言,我使用的命令如下:

dotnet new console
dotnet publish -c Release --runtime osx.10.12-x64 --self-contained true

我有同样的问题,我的“MyApp”并不是一个独立的应用程序。事实上,我发现“MyApp”至少需要在其所在目录中包含以下文件:

MyStatic     ----> my 'exe'                   
MyStatic.dll                    
libhostpolicy.dylib
MyStatic.deps.json              
MyStatic.runtimeconfig.dev.json

任何自包含的二进制文件都不应该需要所有这些垃圾才能独立运行。

不要称它为垃圾。它是自包含的,这意味着它不需要在目标系统上安装运行时。如果你想要一个单独的exe文件,你可以随时在它周围构建一个包装器。 - Marcell Toth
1
@Marcell我们为什么不能自动生成包装器?有没有一种简单的方法将该目录打包成一个文件,或者接近于一个文件的形式呈现? - Andz
@Andz 我同意,他们应该遵循几乎所有其他 MacOS 应用程序使用的约定。 - Ryu S.
只需要添加 <PropertyGroup> <PublishSingleFile>true</PublishSingleFile> </PropertyGroup>,所有的依赖项等将被打包在一个文件中。 - saurabh
现在您可以在 Visual Studio 的“高级”选项下,在发布配置文件中进行配置。 - John Lord

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接