繁体   English   中英

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

[英]Getting the path of a nuget package programmatically

我正在安装一个带有可执行文件的nuget软件包。 为了从解决方案中的项目文件(尤其是在MVC控制器中)中引用可执行文件,此刻,我需要对文件夹路径进行硬编码,这特别令人讨厌,因为其中包含版本号。 因此,当我更新nuget包时,需要更改所有这些引用。

好像很傻

我对Microsoft堆栈还是相当陌生的但是没有某种方法可以仅请求nuget依赖项的路径吗?

当使用NuGet进行软件包管理时,添加新软件包时会发生以下情况:NuGet从存储库中提取依赖项,将文件添加到特定的软件包目录(其位置取决于解决方案本地NuGet配置中的值),并且将软件包“ lib”文件夹中的所有文件添加为对项目的引用。 其他目录中的文件(例如工具,src等)用于其他目的,但不会将它们添加为引用(除非在install.ps1脚本中手动完成)。

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

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

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

     // This returns the URI of the assembly containing the 'MyClass' type, // eg: 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)" /> 

每次构建项目时都完成了所有这些操作,应将可执行文件复制到输出目录,然后可以从代码中调用可执行文件。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM