【问题标题】:How to distribute a .net core 2.0 console application on osx如何在 osx 上分发 .net core 2.0 控制台应用程序
【发布时间】:2026-02-08 15:20:02
【问题描述】:

我正在使用Visual Studio for Mac,我的应用程序已编写,它可以满足我的需求。用户的目标平台是 OSX。它依赖于 2 个具有自己依赖项的 Nuget 包,具体来说:

  • NetMQ
  • Microsoft.Extensions.Configuration.CommandLine

我向build应用程序运行以下命令:

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 aka ./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 &lt;dll&gt;我很高兴,我只需要让它运行。

这里一定是我遗漏了一些东西,否则 netcore2.0 应用程序的这个细节、分布就被忽略了?

在挖掘更多内容时,这似乎也是一个有用的命令:

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

这会添加所有类型的 DLL 以及所有依赖项 DLL。像publish 这样的词让我觉得这就是我们应该走的路。

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

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

【问题讨论】:

    标签: macos .net-core .net-standard .net-standard-2.0


    【解决方案1】:

    您对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 的目录。使用 that 目录(和 not bin/Release/netcoreapp2.0/)作为您的发布存档。您的用户应该只运行dotnet ./path/to/publish/MyApp.dll

    查看https://docs.microsoft.com/en-us/dotnet/core/deploying/ 了解更多信息。

    【讨论】:

    • 谢谢。有没有办法创建一个瘦 SCD?我想创建一个最小的 SCD。目前,即使是一个简单的“Hello World”大小也有 60+ MB,并且不需要整个 .NET Core 运行时。
    【解决方案2】:

    跟进@omajid's answer

    如果您想将控制台应用程序打包在一个漂亮整洁的包中,您只需“单击”它并打开一个终端来启动您的应用程序...这是一个示例应用程序(带有树形图标):

    你首先需要一个像这样的文件夹/文件结构(从 mkdir 开始!):

    然后在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 site off the internet 获取您的“trees.icns”。

    然后将 dotnet publish -c Release --framework netcoreapp3.1 --runtime osx-x64 命令中的所有内容复制到 osx-x64 文件夹中(这里将有大量 .dll 文件。我有 ~197 个)

    最后在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
    

    然后瞧...进入您的查找器并单击“MyApp”应用程序

    参考:packaging jar tutorial

    【讨论】:

      【解决方案3】:

      这仍然可以追溯到他最初的观察,即我所看到的,可执行文件“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 为什么我们不能自动生成包装器?有没有一种简单的方法可以将该目录打包为单个文件或类似的文件?
      • @Andz 我同意,他们应该遵循几乎所有其他 MacOS 应用程序使用的约定