将NuGet包中的本机文件添加到项目输出目录

将NuGet包中的本机文件添加到项目输出目录,nuget,nuget-package,nuget-spec,Nuget,Nuget Package,Nuget Spec,我正在尝试为一个.Net程序集创建NuGet包,该程序集不会对本机win32 dll进行pinvoke。 我需要打包程序集和本机dll,并将程序集添加到项目引用中(这部分没有问题),本机dll应该复制到项目输出目录或其他相关目录中 我的问题是: 如果visual studio不尝试将本机dll添加到引用列表中,如何打包本机dll 我是否必须编写install.ps1来复制本机dll?如果是,我如何访问包内容以进行复制 我不能解决你的确切问题,但我可以给你一个建议 您的关键要求是:“并且不让它自动

我正在尝试为一个.Net程序集创建NuGet包,该程序集不会对本机win32 dll进行pinvoke。 我需要打包程序集和本机dll,并将程序集添加到项目引用中(这部分没有问题),本机dll应该复制到项目输出目录或其他相关目录中

我的问题是:

  • 如果visual studio不尝试将本机dll添加到引用列表中,如何打包本机dll
  • 我是否必须编写install.ps1来复制本机dll?如果是,我如何访问包内容以进行复制

  • 我不能解决你的确切问题,但我可以给你一个建议

    您的关键要求是:“并且不让它自动注册引用”

    因此,您必须熟悉“解决方案项”

    参见此处的参考:

    您必须编写一些powershell voodoo,才能将本机dll的副本放入其主目录中(同样,因为您不希望触发自动添加引用voodoo)

    这是我写的一个ps1文件……将文件放在第三方参考文件夹中

    这里有足够的内容让您能够了解如何将本机dll复制到某个“主页”…而不必从头开始

    再说一次,这不是直接的打击,但总比没有好

    param($installPath, $toolsPath, $package, $project)
    if ($project -eq $null) {
    $project = Get-Project
    }
    
    Write-Host "Start Init.ps1" 
    
    <#
    The unique identifier for the package. This is the package name that is shown when packages are listed using the Package Manager Console. These are also used when installing a package using the Install-Package command within the Package Manager Console. Package IDs may not contain any spaces or characters that are invalid in an URL.
    #>
    $separator = " "
    $packageNameNoVersion = $package -split $separator | select -First 1
    
    Write-Host "installPath:" "${installPath}"
    Write-Host "toolsPath:" "${toolsPath}"
    Write-Host "package:" "${package}"
    <# Write-Host "project:" "${project}" #>
    Write-Host "packageNameNoVersion:" "${packageNameNoVersion}"
    Write-Host " "
    
    <# Recursively look for a .sln file starting with the installPath #>
    $parentFolder = (get-item $installPath)
    do {
            $parentFolderFullName = $parentFolder.FullName
    
            $latest = Get-ChildItem -Path $parentFolderFullName -File -Filter *.sln | Select-Object -First 1
            if ($latest -ne $null) {
                $latestName = $latest.name
                Write-Host "${latestName}"
            }
    
            if ($latest -eq $null) {
                $parentFolder = $parentFolder.parent    
            }
    }
    while ($parentFolder -ne $null -and $latest -eq $null)
    <# End recursive search for .sln file #>
    
    
    if ( $parentFolder -ne $null -and $latest -ne $null )
    {
        <# Create a base directory to store Solution-Level items #>
        $thirdPartyReferencesDirectory = $parentFolder.FullName + "\ThirdPartyReferences"
    
        if ((Test-Path -path $thirdPartyReferencesDirectory))
        {
            Write-Host "--This path already exists: $thirdPartyReferencesDirectory-------------------"
        }
        else
        {
            Write-Host "--Creating: $thirdPartyReferencesDirectory-------------------"
            New-Item -ItemType directory -Path $thirdPartyReferencesDirectory
        }
    
        <# Create a sub directory for only this package.  This allows a clean remove and recopy. #>
        $thirdPartyReferencesPackageDirectory = $thirdPartyReferencesDirectory + "\${packageNameNoVersion}"
    
        if ((Test-Path -path $thirdPartyReferencesPackageDirectory))
        {
            Write-Host "--Removing: $thirdPartyReferencesPackageDirectory-------------------"
            Remove-Item $thirdPartyReferencesPackageDirectory -Force -Recurse
        }
    
        if ((Test-Path -path $thirdPartyReferencesPackageDirectory))
        {
        }
        else
        {
            Write-Host "--Creating: $thirdPartyReferencesPackageDirectory-------------------"
            New-Item -ItemType directory -Path $thirdPartyReferencesPackageDirectory
        }
    
        Write-Host "--Copying all files for package : $packageNameNoVersion-------------------"
        Copy-Item $installPath\*.* $thirdPartyReferencesPackageDirectory -recurse
    }
    else
    {
            Write-Host "A current or parent folder with a .sln file could not be located."
    }
    
    
    Write-Host "End Init.ps1" 
    
    param($installPath、$toolsPath、$package、$project)
    如果($project-eq$null){
    $project=获取项目
    }
    写入主机“Start Init.ps1”
    $separator=“”
    $packageNameNoVersion=$package-split$分隔符|选择-First 1
    写入主机“installPath:${installPath}”
    写入主机“toolsPath:${toolsPath}”
    写入主机“包:${package}”
    写入主机“PackageNameOversion:${PackageNameOversion}”
    写入主机“”
    $parentFolder=(获取项目$installPath)
    做{
    $parentFolderFullName=$parentFolder.FullName
    $latest=Get ChildItem-Path$parentFolderFullName-File-Filter*.sln |选择对象-第一个1
    如果($latest-ne$null){
    $latestName=$latest.name
    写入主机“${latestName}”
    }
    如果($latest-eq$null){
    $parentFolder=$parentFolder.parent
    }
    }
    while($parentFolder-ne$null-和$latest-eq$null)
    if($parentFolder-ne$null-和$latest-ne$null)
    {
    $thirdPartyReferencesDirectory=$parentFolder.FullName+“\ThirdPartyReferences”
    if((测试路径-路径$thirdPartyReferencesDirectory))
    {
    写入主机”--此路径已存在:$thirdPartyReferencesDirectory------------------
    }
    其他的
    {
    写入主机”--创建:$thirdPartyReferencesDirectory------------------
    新项目-项目类型目录-路径$thirdPartyReferencesDirectory
    }
    $thirdPartyReferencesPackageDirectory=$thirdPartyReferencesDirectory+“\${PackageNameOversion}”
    if((测试路径-路径$thirdPartyReferencesPackageDirectory))
    {
    写入主机”--正在删除:$thirdPartyReferencesPackageDirectory------------------
    删除项目$thirdPartyReferencesPackageDirectory-Force-Recurse
    }
    if((测试路径-路径$thirdPartyReferencesPackageDirectory))
    {
    }
    其他的
    {
    写入主机”--创建:$thirdPartyReferencesPackageDirectory------------------
    新项目-项目类型目录-路径$thirdPartyReferencesPackageDirectory
    }
    写入主机”--复制包的所有文件:$PackageNameOversion------------------”
    复制项$installPath\*.$thirdPartyReferencesPackageDirectory-递归
    }
    其他的
    {
    Write Host“找不到包含.sln文件的当前文件夹或父文件夹。”
    }
    写入主机“End Init.ps1”
    
    有点晚了,但我已经为此创建了一个nuget包

    这个想法是在你的nuget包中有一个额外的特殊文件夹。我相信你已经知道Lib和Content了。我创建的nuget包查找名为Output的文件夹,并将其中的所有内容复制到projects Output文件夹

    您所要做的唯一一件事就是向包中添加nuget依赖项

    我写了一篇关于它的博客:

    最近,当我试图构建一个包含托管程序集和非托管共享liraries(也必须放在
    x86
    子目录)的EmguCV NuGet包时,我遇到了同样的问题,在每次构建之后,该包必须自动复制到构建输出目录

    下面是我提出的一个解决方案,它只依赖于NuGet和MSBuild:

  • 将托管程序集放置在包(明显部分)的
    /lib
    目录中,并将非托管共享库和相关文件(例如pdb包)放置在
    /build
    子目录中(如中所述)

  • 将所有非托管的
    *.dll
    文件结尾重命名为不同的名称,例如
    *.dl
    ,以防止NuGet抱怨声称的程序集放置在错误的位置(“问题:程序集在lib文件夹之外”)

  • /build
    子目录中添加一个自定义的
    .targets文件,其内容如下(有关说明,请参阅下文):

  • 
    详细信息请参阅文件

  • 自定义目标,
    CopyNativeBinaries
    ,包含两个复制任务。第一个负责将任何
    *.dl
    文件复制到输出目录,同时将其扩展名更改回原始
    *.dll
    。第二个简单地将其余文件(例如任何
    *.pdb
    文件)复制到同一位置。这可以由一个复制任务和一个脚本代替,该脚本必须在包安装期间将所有
    *.dl.
    文件重命名为
    *.dll

  • 然而,这种溶质
    private static void UnpackNativeLibrary(string libraryName)
    {
        var assembly = Assembly.GetExecutingAssembly();
        string resourceName = $"{assembly.GetName().Name}.{libraryName}.dll";
    
        using (var stream = assembly.GetManifestResourceStream(resourceName))
        using (var memoryStream = new MemoryStream(stream.CanSeek ? (int)stream.Length : 0))
        {
            stream.CopyTo(memoryStream);
            File.WriteAllBytes($"{libraryName}.dll", memoryStream.ToArray());
        }
    }
    
    /Content
     /bin
       /Debug
          native libraries
       /Release
          native libraries
    
    <ItemGroup>
        <NativeLibs Include="$(MSBuildThisFileDirectory)**\*.dll" />
        <None Include="@(NativeLibs)">
          <Link>%(RecursiveDir)%(FileName)%(Extension)</Link>
          <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
        </None>
    </ItemGroup>