2014-03-24 37 views
1

我正在安裝帶有可執行文件的nuget包。要在解決方案中的項目文件(更具體地說是在mvc控制器)中引用可執行文件,此刻我需要對文件夾路徑進行硬編碼,因爲文件夾路徑中包含版本號,所以特別是在文件夾路徑中。所以當我更新nuget包時,我需要更改所有這些引用。以編程方式獲取nuget包的路徑

這似乎是愚蠢的

我還是相當新的Microsoft堆棧,但是是不是有一些方法,只是請求的NuGet依賴的路徑?

+0

這是第三方軟件包還是您自己的軟件包之一?換句話說,您是否有能力將「install.ps1」腳本添加到可用於添加依賴項的包中? – Petrik

+0

第三方,所以沒有。 – nimrod

+0

好的,這很煩人。在這種情況下,你能否解釋一下你試圖達到的目標?你是否試圖在代碼或項目文件中使用路徑或? – Petrik

回答

5

當使用NuGet作爲包管理器時,當添加一個新包時會發生什麼情況,NuGet會從存儲庫中提取依賴項,將這些文件添加到特定的包目錄中(其位置取決於解決方案中的值本地NuGet配置),並添加包「lib」文件夾中的所有文件作爲對項目的引用。其他目錄中的文件(例如工具,src等)被用於其他目的,但不會被添加爲引用(除非在install.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腳本解決方案文件夾,然後首先將下列行添加到您的項目文件

      <SolutionDir Condition="'$(SolutionDir)' == '' or '$(SolutionDir)' == '*undefined*'">$(MSBuildProjectDirectory)\..</SolutionDir> 
      
    • 的第一個PropertyGroup在您的項目文件的底部有兩個評價指標,一個叫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)" /> 
      

有了這一切完成每一個你建立你的項目的可執行文件應該被複制到您的輸出目錄,然後你可以調用你的代碼中的可執行時間。

+0

謝謝,真的很感謝廣泛的答覆! – nimrod

相關問題