在哪里为非托管库放置dll?

时间:2012-04-17 20:14:24

标签: dll dependencies unmanaged nuget

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

5 个答案:

答案 0 :(得分:17)

向程序包添加build文件夹,如果程序包的标识为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)。

答案 1 :(得分:9)

以上参考可以使用,但它实际上会修改您的帖子构建事件以推送文件,如果您遇到我们的情况,这可能无法解决您的问题。

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

nuspec参考现在允许您指定 lib 目录中的哪些DLL现在在visual studio项目中显式注册,您只需要在元数据<中添加到您的nuspec文件中/ strong>区域显式引用列表(如果不存在,则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 reference

答案 2 :(得分:3)

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

  

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

答案 3 :(得分:3)

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

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

同样在

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

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

答案 4 :(得分:1)

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

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

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

  3. install.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)属性。
    2. 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”添加到“内容”文件夹中。这将使包安装。
      2. 另请参阅:http://alski.net/post/2013/05/23/Using-NuGet-25-to-deliver-unmanaged-dlls.aspx