none
How to resolve NuGet package local path RRS feed

  • Question

  •    Actually the main question is not that straightforward. The problem is that I need to include multiple versions of a NuGet package to a project. As I understood from searching for an answer on the internet the only option is to add App.config with the following lines

    <runtime>
       <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
          <dependentAssembly>
             <assemblyIdentity name="Deep" culture="neutral" publicKeyToken="f694e838567cfe72" />
             <codeBase version="1.0.0.0" href="Deep-1.0.0.0.dll" />
             <codeBase version="2.0.0.0" href="Deep.dll" />
             <bindingRedirect oldVersion="1.0.0.0" newVersion="1.0.0.0" />
             <bindingRedirect oldVersion="1.0.0.0" newVersion="2.0.0.0" />
             <bindingRedirect oldVersion="2.0.0.0" newVersion="2.0.0.0" />
          </dependentAssembly>
       </assemblyBinding>
    </runtime>
    

       Thus, I instruct the framework to load Deep-1.0.0.0.dll version when the code calls that particular assembly version. To make it work on the step of building the project I created an msbuild task. First of all I specify locations of assemblies I want to add to the project target directory, then the task goes over those assemblies, extracts their version numbers, adds them as -Major.Minor.0.0 to the file name, and copies the assemblies to the project target directory. Along with that it makes sure aforementioned configuration is added to the App.config.

       Now, I would like to do something similar for NuGet packages and the main problem is to find the right assembly in the NuGet assembly cache. For example if the NuGet assembly is referenced like

      <ItemGroup>
        <PackageReference Include="log4net">
          <Version>2.0.8</Version>
        </PackageReference>
      </ItemGroup>
    

       How do I find that assembly on the hard drive? I found it manually. It's at C:\Users\{UserName}\.nuget\packages\log4net\2.0.8\lib\net45-full. How can I find it while building the project? Is there a task or target I can call for that? Is it possible to find parts of this path somehow? Where to get the base path (C:\Users\{UserName}\.nuget\packages) from? How to figure out what should be the last part of the path which in this case is "net45-full"?

       Please, let me know if I'm complete on the wrong path and there is an easy way to include multiple versions of the same assembly to a project.

    Thank you


    Alex

    Thursday, October 19, 2017 6:19 PM

All replies

  • Hi Alex K M,

    Thanks for posting here.

    >>>How can I find it while building the project? Is there a task or target I can call for that? Is it possible to find parts of this path somehow? Where to get the base path (C:\Users\{UserName}\.nuget\packages) from?

    Take a look at obj\projectName.csproj.nuget.g.props in your .net core project. You should see all package folders used in the property: NuGetPackageFolders. For the base path (C:\Users\{UserName}\.nuget\packages), you can get the base path by the property: $(NuGetPackageRoot).

    >>>there is an easy way to include multiple versions of the same assembly to a project.

    I`m not sure if it is an easy way, but you can use it as a reference. You can manually rename the dlls with different names, for example, log4net_Version1.dll, log4net_Version2.dll. Then pack them with different nuget packages, log4net_Version1.nupakg,  log4net_Version2.nupakg, so that you can use those two version packages in the project.

    Hope this helps.


    MSDN Community Support Please remember to click &quot;Mark as Answer&quot; the responses that resolved your issue, and to click &quot;Unmark as Answer&quot; if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    Friday, October 20, 2017 10:52 AM
  •    That was a great hint about NuGetPackageFolders and the .nuget.g.props file in general. That helps to find the local root of the NuGet packages. The outstanding questions is still how to build the rest of the path to the particular assembly of the particular version. I, also, found this property TargetFrameworkMoniker which in my case for my test project is ".NETFramework,Version=v4.5". Then I found a NuGetFramework class in the NuGet.Client library (which resides on NuGet). Then if I do

                var nuGetFramework = NuGetFramework.ParseFrameworkName(".NETFramework,Version=v4.5", DefaultFrameworkNameProvider.Instance);
                var shortFolderName = nuGetFramework.GetShortFolderName();
    
    shortFolderName will be "net45". However the actual folder for log4net is "net45-full". Again, I'm not sure I'm digging in the right direction. There is no documentation for the NuGet.Client and I'm blindly stepping through, playing with methods and trying to find one which will help me to build the path to the log4net of a particular version. I'm almost sure NuGet.Client should have a method building the full path but again may be there is another way.


    Alex

    Friday, October 20, 2017 3:10 PM
  • As far as I know, there is a string for _frameworkProfile, which you can get the profile about the .net framework in the NuGetFramework class:

    https://github.com/NuGetArchive/NuGet.Packaging/blob/master/src/NuGet.Frameworks/NuGetFramework.cs

    You can check it for detail info. 

    Besides, there is a sample How to programmatically install a NuGet package?, you can check if it give you helps:

    https://stackoverflow.com/questions/41803738/how-to-programmatically-install-a-nuget-package


    MSDN Community Support Please remember to click &quot;Mark as Answer&quot; the responses that resolved your issue, and to click &quot;Unmark as Answer&quot; if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.


    Monday, October 23, 2017 3:36 PM
  •    The question is not about how to install a NuGet package. The question is about how to find a full path to the binary which is cached at C:\Users\{UserName}\.nuget\packages if you know the name of the package, its version and TargetFrameworkMoniker of the current build.

       Let me recap again. I build a project which references a NuGet package. I want to add extra steps to the build process and for that I need to find full paths to the binaries of the referenced NuGet packages. How can I do that?

       As I stated in my last message I'm having problems with finding the last part of the path. Now, I know how to find the root by using $(NuGetPackageRoot). It gives me the first path of the path C:\Users\{UserName}\.nuget\packages. I know the package name "log4net", so I append that. I know the version number 2.0.8. I append that. Then I append lib and eventually have this path C:\Users\{UserName}\.nuget\packages\log4net\2.0.8\lib which is missing the last part. I know for my particular case it should be "net45-full" but I don't understand why it's "net45-full". I noticed that for another NuGet packages it can be simply net45 without -full.


    Alex

    Monday, October 30, 2017 6:51 PM
  • What's new in .NET Framework 4 Client Profile RTM explains the differences of -full and -client. At this moment, have no idea how to get the last part of the path except give the full path manually. I will keep this thread open, hope there are other magic can get this path.


    MSDN Community Support Please remember to click &quot;Mark as Answer&quot; the responses that resolved your issue, and to click &quot;Unmark as Answer&quot; if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    Tuesday, October 31, 2017 9:52 AM
  • Try the following items: @(ReferenceCopyLocalPaths)

    You can for example print the items in a .target file like so:

    <Message Text="ReferenceCopyLocalPaths: @(ReferenceCopyLocalPaths)" />

    which in my case prints:

    "ReferenceCopyLocalPaths: C:\Users\<USERNAME>\.nuget\packages\log4net\2.0.8\lib\net45-full\log4net.dll"

    I found out about the existence of these items by printing all the MSBuild items and properties, running the command "MSBuild.exe MyProject.sln /filelogger /fileLoggerParameters:Verbosity=diag" (techblog.dorogin.com/msbuild-a-simple-way-to-find-out-all-properties-and-their-values-while-building-a-csproj-file-d14bcbe8fadc). This creates a "msbuild.log" next to the  "MyProject.sln" file with a lot of interesting information.

    Hint: Run the command in the "Developer Command Prompt for VS20XX".

    I hope this helps!

    Tuesday, November 26, 2019 3:25 PM