以编程方式获取nuget包的路径

本文关键字:路径 nuget 获取 编程 方式 | 更新日期: 2023-09-27 17:53:14

我正在安装一个带有可执行文件的nuget包。要从项目文件中的解决方案中引用可执行文件(更具体地说,在mvc控制器中),目前我需要硬编码文件夹路径,这是特别重要的,因为它有一个版本号。因此,当我更新nuget包时,我需要更改所有这些引用。

看起来很傻

我仍然是相当新的微软堆栈,,但是不是有一些方法只是请求nuget依赖的路径?

以编程方式获取nuget包的路径

当使用NuGet作为包管理器时,当添加一个新包时,NuGet会从存储库中提取依赖项,将文件添加到特定的包目录中(该目录的位置取决于解决方案本地NuGet配置中的值),并将包'lib'文件夹中的所有文件添加为项目引用。其他目录中的文件(例如tools, src等)用于其他目的,但它们不会被添加为引用(除非在安装中手动完成)。ps1脚本)。

与node.js这样的解释性语言的区别之一在构建二进制文件时变得很重要。在构建过程中,编译器将引用复制到输出目录。这意味着当您执行实际代码时,包的位置在很大程度上是无关紧要的,因为该代码位于不同位置的二进制文件中(通常您只将二进制文件复制到服务器,而不是将整个解决方案文件夹复制到服务器)。

因此,根据所需的可执行文件在包中的位置,有几种情况:

  • 如果可执行文件是包'lib'文件夹,那么它应该被你的ASP引用。MVC项目。在这种情况下,可执行文件将被复制到输出目录。在这种情况下,您可以通过执行以下代码来获取可执行路径:

    // This returns the URI of the assembly containing the 'MyClass' type, 
    // e.g.: file:///C:'temp'myassembly.dll
    var codeBase = typeof(MyClass).Assembly.CodeBase;
    // This return the file path without any of the URI qualifiers
    var location = new Uri(codeBase).LocalPath;
    
  • 如果可执行文件不在包'lib'文件夹中,在这种情况下它不会被引用,因此不会在二进制文件夹中。这意味着您需要将二进制文件复制到二进制文件夹中。一种简单的方法是使用构建前或构建后事件。使用这种方法的缺点是,您需要在每次更新包时更新构建事件,因为文件夹名称包含包版本,因此会更改。如果你不想这样做,那么使用一些MsBuild魔法,你可以设置一个系统,允许你处理更改文件夹名称。

    • 首先,您需要能够找到保存可执行文件的文件夹。下面的MsBuild脚本可用于搜索给定文件(在您的示例中是可执行文件)的包目录(NuGet解包的目录)。把这个脚本放在一个你可以从你的项目文件中引用它的位置(例如在你的解决方案目录中)

      <Project xmlns='http://schemas.microsoft.com/developer/msbuild/2003' 
               ToolsVersion="4.0">
          <!--
              Finds the full path for a tool that was installed by NuGet
              Define:
              - PackagesDir: Directory that contains the 'installed' packages.
              - FileToLocate: Name of the executable file for which the path should be located.
              - Path: Return variable containing the full path of the executable file.
          -->
          <UsingTask TaskName="FindToolDirectoryFromPackages" 
                     TaskFactory="CodeTaskFactory" 
                     AssemblyFile="$(MSBuildToolsPath)'Microsoft.Build.Tasks.v4.0.dll">
              <ParameterGroup>
                  <PackagesDir ParameterType="System.String" Required="true" />
                  <FileToLocate ParameterType="System.String" Required="true" />
                  <Path ParameterType="System.String" Output="true" />
              </ParameterGroup>
              <Task>
                  <Using Namespace="System.Linq" />
                  <Code Type="Fragment" Language="cs">
                      <![CDATA[
                          Path = System.IO.Directory.EnumerateFiles(PackagesDir, FileToLocate, SearchOption.AllDirectories)
                              .OrderBy(k => System.IO.Path.GetDirectoryName(k))
                              .Select(k => System.IO.Path.GetDirectoryName(k))
                              .LastOrDefault();
                      ]]>  
                  </Code>
              </Task>
          </UsingTask>
      </Project>
      
    • 接下来你需要更新你的ASP。MVC项目文件。如果您将上述MsBuild脚本添加到解决方案文件夹中,那么首先将以下行添加到项目文件

      的第一个PropertyGroup中。
      <SolutionDir Condition="'$(SolutionDir)' == '' or '$(SolutionDir)' == '*undefined*'">$(MSBuildProjectDirectory)'..</SolutionDir>
      
    • 在你的项目文件的底部是两个评论的目标,一个叫BeforeBuild和一个叫AfterBuild。取消注释,哪个都无所谓。然后添加以下代码:

      <FindToolDirectoryFromPackages PackagesDir="$(SolutionDir)'..'RELATIVE_PATH_TO_PACKAGE_DIRECTORY" 
                                     FileToLocate="FILE_NAME_OF_EXECUTABLE">
          <Output TaskParameter="Path" PropertyName="DirMyExecutableFile" />
      </FindToolDirectoryFromPackages>
      <ItemGroup>
          <Files Include="$(DirMyExecutableFile)'**'*.*" />
      </ItemGroup>
      <!-- OutputPath should be the directory to which the compiler will copy your binaries -->
      <MakeDir Directories="$(OutputPath)" 
               Condition="!Exists('$(OutputPath)')" />
      <Copy SourceFiles="@(Files)" 
            DestinationFolder="$(OutputPath)'%(RecursiveDir)" />
      

当你每次构建你的项目时,可执行文件应该被复制到你的输出目录中,然后你可以从你的代码中调用可执行文件