在何处放置非托管库的DLL?

在何处放置非托管库的DLL?,dll,dependencies,unmanaged,nuget,Dll,Dependencies,Unmanaged,Nuget,我正在尝试为一个依赖于ghostscript的库创建一个Nuget包,因此它引用了gsdll32.dll—一个非托管库。我不能只是把它包含在标准dll引用中。我应该把它放在nuget目录结构的什么地方?nuget论坛上的回应: pranavkm: SQLCE包有一个类似的问题,我们通过PS来处理 脚本。签出脚本在 上面的引用可以工作,但它实际上修改了构建后事件以将文件推送过来,如果您遇到了我们所遇到的情况,这实际上可能无法解决您的问题 我们遇到的问题是一个依赖DLL无法注册,但必须与另一个需要

我正在尝试为一个依赖于ghostscript的库创建一个Nuget包,因此它引用了gsdll32.dll—一个非托管库。我不能只是把它包含在标准dll引用中。我应该把它放在nuget目录结构的什么地方?

nuget论坛上的回应:

pranavkm: SQLCE包有一个类似的问题,我们通过PS来处理 脚本。签出脚本在


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

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

nuspec引用现在允许您指定在visual studio项目中显式注册lib目录中的哪些DLL。现在,您只需在元数据区域的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>

一些包装
1.0.1
一些包裹的标题

有这样一个部分:

<files>
    <file src="lib\*.*" target="lib" />
    <file src="build\MyPackage.targets" target="build" />
</files>
<references>
    <reference file="MyManaged.dll" />
</references>
<?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>
.targets
文件应如下所示:

<files>
    <file src="lib\*.*" target="lib" />
    <file src="build\MyPackage.targets" target="build" />
</files>
<references>
    <reference file="MyManaged.dll" />
</references>
<?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)。

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

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

  • 将以下脚本添加到“工具”文件夹:

  • 安装.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)
    
  • 将目标文件添加到生成文件夹。(将“MyPackage”更改为包的名称)。为目标使用唯一的名称,如“CopyMyPackage”,可避免与试图定义“AfterBuild”目标的其他包发生冲突。此目标文件使用上述脚本定义的$(PackagePath)属性
  • 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>
    
    
    
  • 最后,在内容文件夹中添加一个“MyPackageReadMe.txt”。这将使软件包能够安装

  • 另请参见:

    我基本上是使用Lars Michael的方法实现的,但我需要添加一件事,这来自James Eby的回答。Visual Studio试图注册我的
    lib
    目录中的所有dll,因此我在nuspec文件的元数据中添加了
    引用
    元素,告诉它只注册托管dll:

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

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

    我首先尝试了我的包的id
    FANNCSharp-x64
    ,但它需要完整的包名:
    FANNCSharp-x64.0.1.4
    “…通过一些动态引用魔法最终将被复制到目标bin目录中…”。这似乎对未更改的dll不起作用,这就是问题所在。好吧,它在我的情况下不起作用,但确实起了作用。我很感激这个Lars-你能将它编辑到你的答案中吗?博客链接往往会停止工作。你让我过了一天(句号)。@Jérôme有点晚了,但我认为你的问题仍然值得回答。有轻微的问题(而且绝对不明显).target文件的陷阱:名称必须与包名称相同。如果是这样,在包安装时,目标会自动添加到.csproj文件中。您可以在接近末尾的某个包中检查是否引用了您的目标。只有这样,它才会起作用。不涉及其他魔法。您可以避免硬编码精确路径,如下所示:
    @elliotwods在.nuspec文件()中…目标文件需要根据您放置本机文件的位置进行自定义。在本例中,它们被放置在名为
    lib
    的文件夹中。我修改了原始答案以解决您提到的问题。谢谢。