27

我正在尝试为依赖 ghostscript 的库创建一个 Nuget 包,因此引用 gsdll32.dll - 一个非托管库。我不能只包含一个标准的 dll 引用。我在哪里把它放在 nuget 目录结构中?

4

6 回答 6

19

将一个build文件夹添加到包中,例如,如果包具有 id MyPackage,则添加一个名为MyPackage.targets该文件夹的 MSBuild 目标文件。.targets文件与文件同名很重要.nuspec。在.nuspec文件中,您必须有这样的部分:

<files>
    <file src="lib\*.*" target="lib" />
    <file src="build\MyPackage.targets" target="build" />
</files>

这将在项目文件中添加一个指向该.targets文件的 MSBuild 元素。

此外,要仅注册托管 dll,请添加如下部分:

<references>
    <reference file="MyManaged.dll" />
</references>

.targets文件应如下所示:

<?xml version="1.0" encoding="utf-8"?> 
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> 
  <Target Name="CopyMyPackageFiles" AfterTargets="AfterBuild"> 
    <ItemGroup> 
      <MyPackageFiles Include="$(MSBuildThisFileDirectory)..\lib\*.*"/> 
    </ItemGroup> 
    <Copy SourceFiles="@(MyPackageFiles)" DestinationFolder="$(OutputPath)" > 
    </Copy> 
  </Target> 
</Project>

现在,所有文件(包括非托管文件)都将在构建后复制到项目输出文件夹(例如 \bin\debug)。

于 2015-10-09T15:06:37.147 回答
9

上面的参考可以工作,但它实际上修改了您的构建后事件以推送文件,如果您遇到我们遇到的情况,这实际上可能无法解决您的问题。

我们遇到的问题是一个依赖 DLL 无法注册,但必须与另一个需要由 nuget 注册的 DLL 并存,因此它需要存在于 lib 目录中但不能注册。

nuspec 引用现在允许您指定lib目录中的哪些 DLL 现在在 Visual Studio 项目中显式注册,您只需在元数据区域的 nuspec 文件中添加一个显式引用列表(如果这不存在默认行为nuget 的目的是尝试在 lib 下注册所有内容)。

这是我的意思的示例 nuspec 文件:

<?xml version="1.0" encoding="utf-8"?>
<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
    <metadata>
        <id>SomePackageID</id>
        <version>1.0.1</version>
        <title>Some Package Title</title>
        <authors>Some Authors</authors>
        <requireLicenseAcceptance>false</requireLicenseAcceptance>
        <description>Blah blah blah.</description>
        <references>
            <reference file="ceTe.DynamicPDF.Rasterizer.20.x86.dll" />          
        </references>
    </metadata>
    <files>
        <file src="\\SomeNetworkLocation\ceTe.DynamicPDF.Rasterizer.20.x86.dll" target="lib\ceTe.DynamicPDF.Rasterizer.20.x86.dll" />
        <file src="\\SomeNetworkLocation\DPDFRast.x86.dll" target="lib\DPDFRast.x86.dll" />
    </files>
</package>

如您所见,ceTe.DynamicPDF.Rasterizer.20.x86.dll需要注册,但DPDFRast.x86.dll只需要存在于该目录中以支持其他 DLL 并且不会被注册,但通过一些动态引用魔法最终将被复制到目标bin目录中,因为 Visual Studio 看到第一个 DLL 依赖于第二个。

这是原始的nuspec 参考

于 2014-04-14T19:17:45.570 回答
3

Nuget 论坛上的回复:http: //nuget.codeplex.com/discussions/352689

pranavkm:SQLCE 包有一个类似的问题,我们通过 PS 脚本处理。在https://bitbucket.org/davidebbo/nugetpackages/src/1cba18b864f7/SqlServerCompact/Tools查看脚本 。

于 2012-04-18T18:10:40.033 回答
3

我在很大程度上使用 Lars Michael 的方法来解决这个问题,但我需要补充的一件事来自 James Eby 的回答。Visual Studio 试图在我的lib目录中注册所有 dll,所以我references在 nuspec 文件的元数据中添加了一个元素,告诉它只注册托管 dll:

<references>
    <reference file="FANNCSharp.dll" />          
</references>

也在

<MyPackageFiles Include="$(MSBuildProjectDirectory)\..\Packages\MyPackage\lib\*.*"/>

我首先尝试了我的 package 的 id FANNCSharp-x64,但它需要完整的包名:FANNCSharp-x64.0.1.4.

于 2016-04-08T01:23:12.227 回答
1

我遇到的一个问题是包路径相对于项目文件并不总是在同一个地方。以下对我有用:

  1. 在 NuGet 包中,将非托管 DLL 放在 lib\native 文件夹中。

  2. 将以下脚本添加到工具文件夹:

安装.ps1

#This script creates or updates a PackagesPath property in the project file
param($installPath, $toolsPath, $package, $project)

$project.Save()

#Load the csproj file into an xml object
[xml] $xml = Get-Content -path $project.FullName

#grab the namespace from the project element 
$nsmgr = New-Object System.Xml.XmlNamespaceManager -ArgumentList $xml.NameTable
$nsmgr.AddNamespace('a',$xml.Project.GetAttribute("xmlns"))

#find or create the property
$property = $xml.Project.SelectSingleNode("//a:PropertyGroup//a:PackagesPath", $nsmgr)
if (!$property)
{
    $property = $xml.CreateElement("PackagesPath", $xml.Project.GetAttribute("xmlns"))
    $propertyGroup = $xml.CreateElement("PropertyGroup", $xml.Project.GetAttribute("xmlns"))
    $propertyGroup.AppendChild($property)
    $xml.Project.InsertBefore($propertyGroup, $xml.Project.ItemGroup[0])
}

#find the relative path to the packages folder
$absolutePackagesPath = (get-item $installPath).parent.FullName
push-location (split-path $project.FullName)
$relativePackagesPath = Resolve-Path -Relative $absolutePackagesPath
pop-location

#set the property value
$property.InnerText = $relativePackagesPath

#save the changes.
$xml.Save($project.FullName)
  1. 将目标文件添加到构建文件夹。(将“MyPackage”更改为您的包裹名称)。为目标使用唯一名称,如“CopyMyPackage”,避免与试图定义“AfterBuild”目标的其他包发生冲突。此目标文件使用上述脚本定义的 $(PackagesPath) 属性。

MyPackage.targets

<?xml version="1.0" encoding="utf-8"?> 
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> 
  <Target Name="CopyMyPackage" AfterTargets="AfterBuild"> 
    <ItemGroup> 
      <MyPackageSourceFiles Include="$(PackagesPath)\MyPackage.*\lib\native\*.*"/> 
    </ItemGroup> 
    <Copy SourceFiles="@(MyPackageSourceFiles)" DestinationFolder="$(OutputPath)" > 
    </Copy> 
  </Target> 
</Project>
  1. 最后,将“MyPackageReadMe.txt”添加到 Content 文件夹。这将使软件包能够安装。

另见:http ://alski.net/post/2013/05/23/Using-NuGet-25-to-deliver-unmanaged-dlls.aspx

于 2016-03-29T15:56:03.080 回答
0

对于 .NET Core,如果您知道本机代码的目标运行时平台,这非常简单。构建时,您可能会注意到 bin 树下的 .NET Core 构建文件夹中有一个名为“runtimes”的文件夹。它看起来像这样:

.NET Core 中的运行时平台文件夹

这些文件夹旨在保存任何特定于平台的内容,包括非托管/本机 DLL。

在您的 NuGet 包中,在“文件”部分下添加以下内容:

<file src="[source path for file in package]" target="runtimes\[platform]\native\[file name]" />

在执行应用程序时,运行时环境会在相应的平台目录中寻找非托管的 dll。

如果要针对多个平台,只需为每个平台添加另一个文件条目。

于 2022-01-26T21:36:10.393 回答