【问题标题】:Create NuGet package with external .exe files using dotnet pack使用 dotnet pack 使用外部 .exe 文件创建 NuGet 包
【发布时间】:2017-12-29 08:54:45
【问题描述】:

编辑:我做了什么来解决这个问题:

使用以下 nuspec 创建了一个新的 NuGet 包:

<package>
  <metadata>
    <id>VIPSNuget</id>
    <version>1.0.0.0</version>
    <title>$title$</title>
    <authors>Devedse</authors>
    <owners>Devedse</owners>
    <licenseUrl>https://github.com/jcupitt/libvips/blob/master/COPYING</licenseUrl>
    <projectUrl>https://github.com/jcupitt/libvips</projectUrl>
    <requireLicenseAcceptance>false</requireLicenseAcceptance>
    <description>Just the EXE file for VIPS</description>
    <releaseNotes>First release</releaseNotes>
    <copyright>Copyright 2017</copyright>
    <tags>VIPS exe file</tags>
  </metadata>
  <files>
    <file src="VIPS\*.*" target="tools" />
  </files>
</package>

将所有 .exe 文件放在该文件夹中。

现在我在 ImageOptimizer 中使用以下代码:

    var userProfileDir = System.Environment.GetEnvironmentVariable("USERPROFILE");
    string pathVips = Path.Combine(userProfileDir, Constants.VipsDir, "vips.exe");

一些背景

我目前正在开发一个图像处理库,该库需要使用名为 VIPS 的外部工具将图像从 JPEG 转换为 PNG。 (https://github.com/jcupitt/libvips)。

由于我不想将来自 VIPS 的二进制文件包含在我自己的项目中,我想,让我们制作一个 NuGet 包,可以从我的代码中调用 .exe 文件。

我采取的步骤

我使用“dotnet new console”命令创建了一个新的 dotnet 核心解决方案。之后,我创建了一个名为“VIPS”的目录并将所有二进制文件粘贴在那里。

然后我创建了一个包含以下 XML 的 nuspec 文件:

<?xml version="1.0"?>
<package>
  <metadata>
    <id>$id$</id>
    <version>$version$</version>
    <title>$title$</title>
    <authors>Devedse</authors>
    <owners>Devedse</owners>
    <licenseUrl>https://github.com/jcupitt/libvips/blob/master/COPYING</licenseUrl>
    <projectUrl>https://github.com/jcupitt/libvips</projectUrl>
    <requireLicenseAcceptance>false</requireLicenseAcceptance>
    <description>Just the EXE file for VIPS</description>
    <releaseNotes>First release</releaseNotes>
    <copyright>Copyright 2017</copyright>
    <tags>VIPS exe file</tags>
  </metadata>
  <files>
    <file src="VIPS\*.*" target="tools" />
  </files>
</package>

我编辑了我的 .csproj 文件,使其仅包含以下内容:

<Project Sdk="Microsoft.NET.Sdk">    
  <PropertyGroup>
    <TargetFramework>netstandard1.0</TargetFramework>
    <Version>1.0.4.0</Version>
  </PropertyGroup>    
</Project>

问题

每当我现在运行“dotnet pack”命令时,一切似乎都很顺利:

但是 VIPS 目录中的所有文件都不包含在我创建的 nupkg 中:

(我选择工具的原因是因为在早期版本的 dotnet 框架/NuGet 中,我使用了像 ILRepack 这样的工具,这些工具会自动安装在工具目录中,然后可以从部署的 .exe 文件的相对路径调用)。

(另请参见第 92 行 https://github.com/gluck/il-repack/blob/master/build.gradle 中的 nuspec 代码,其中还包括在“工具”目标中创建的 .exe 文件)

进一步调查

然后我尝试将 VIPS 目录中的所有文件添加到我的 csproj 文件中,并将构建操作设置为 Content。

现在所有二进制文件都包含在以下 2 个目录中(所以所有重复文件也很奇怪): vipsnuget.1.0.0.nupkg\content\VIPS\ vipsnuget.1.0.0.nupkg\contentFiles\any\netstandard1.0\VIPS\

但是,当我现在将 NuGet 包包含在另一个项目中,然后打包该项目时,它似乎也再次包含该包中的所有二进制文件:

(所有 VIPS 二进制文件现在都放在:DeveImageOptimizer.1.0.0.nupkg\contentFiles\any\netstandard1.5\ 和 content\VIPS)

这是不可取的,因为 DLL 的实际大小应该只有几个 Kb。

这种方法的另一个问题

我实际上不确定是否有更好/更好的解决方案,但目前,当 NuGet 包恢复时,它将被提取到 %userprofile%.nuget\packages\vipsnuget...

所以每当我想对 VIPS.exe 运行命令时,我需要将 Process.Start 参数指向 %userprofile%... 。有一个更好的方法吗? (比如找到代码中恢复NuGet包的地方?)

我最想要什么

基本上我最想要的是创建一个 NuGet 包,如果包含它,某个目录将被复制到项目的构建输出中。

类似: DeveImageOptimizer\bin\debug\VIPS...

如果不存在

如果没有办法做到这一点,我想听听将某些“工具”放入 NuGet 包并从 C# 代码中调用它们的正常方法。

【问题讨论】:

    标签: c# nuget .net-core


    【解决方案1】:

    当您不带任何参数调用 dotnet pack 时,它会使用当前文件夹中的 .csproj 文件来创建 nuget 包并忽略任何 .nuspec 文件。如果查看dotnet pack 参数,您将找不到如何直接指定.nuspec

    但是,dotnet-pack docs 说我们可以为打包过程的 dotnet pack 命令提供 MSBuild 属性。来自NuGet metadata properties

    NuspecFile

    用于打包的 .nuspec 文件的相对或绝对路径。 注意

    如果指定了 .nuspec 文件,则它专门用于打包 信息和项目中的任何信息都不会被使用。

    NuspecBasePath

    .nuspec 文件的基本路径。

    所以修改您的.csproj,添加以下内容

    <PropertyGroup>
      <NuspecFile>location to your nuspec file</NuspecFile>
    </PropertyGroup>
    

    注意:你总是可以直接使用nuget pack 命令。

    【讨论】:

    • 这确实解决了我没有包含工具的问题:)。但是,我现在如何调用 VIPS.exe 文件?我真的应该在 Users\.....\.nuget 目录中调用它吗?或者我能不能让它被复制到我的程序的输出目录中?
    • @Devedse 查看Set content files to “copy local : always” in a nuget package。主要思想是使用CopyToOutputDirectory标志到copy files to output
    • 因此,您是否必须使用 Copy Local 将所有 DLL/EXE 文件包含在 csproj 文件中,或者您也可以在 nuspec 文件中执行此操作?
    • 而且,看起来我实际上需要将文件添加为“内容”而不是“工具”(从您链接的帖子中读取)。如果我这样做,是不是所有的文件都会再次添加到 NuGet 包中两次? (就像我第一次尝试的情况一样)?
    • @Devedse - 如果您提出单独的问题,请在此处发布链接。如果您没有找到合适的答案,我可以为您提供该问题的解决方案。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-10-13
    • 2017-07-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-03-02
    相关资源
    最近更新 更多