Using NuGet packages in VSIX extension - vsix

I am trying to build a VSIX extension that is using some NuGet packages.
When running the project I get an exception "Could not load file or assembly or its dependencies". I've included the package dlls themselves and they get copied over, but I suspect they're missing one of the numerous dependencies. But I don't know which ones.
I've found many old links here with similar issue and tried everything, but nothing seems to work.
Specifically I am trying to use MdXaml nuget package. It looks like it's relying on AvalonTextEdit, and that itself is relying on bunch of other stuff.

Related

How to wrap a NUnit Engine Extension as a NuGet package?

I am working on a nunit engine extension which will be shipped as a nuget package.
Following the advises in How to implement NUnit's NUnit.Engine.ITestEventListener i was able to write the extension.
This solution is working as long as the project which contains the extension (the .cs file as well as the .addins file) is being imported to the target project which will perform the nunit tests.
As soon as I create a nuget package (following Quickstart: Create and publish a NuGet package using Visual Studio (.NET Standard, Windows only)) from the extension project and install this package to a test project, the extension doesn't work anymore.
I assume there is a problem with providing the .addins file within the nuget package so that the nunit engine in the target project can find the extension.
I already tried to ship the .addins file within the nuget package by adding the following lines to the .csproj file of the extension project.
<ItemGroup>
<Content Include="file.addins">
<Pack>true</Pack>
</Content>
</ItemGroup>
If I add the .addins file to the target project by hand, the engine extension starts working.
How can a nunit engine extension be shipped as a nuget package without any adjustments by hand?
Im using NUnit(3.13.2).
Im quite new to nunit, nuget and writing questions on stack overflow. So if I'm missing something obvious here, I'm sorry.
This is one of those areas where I wish things were less complicated, unfortunately. Since extensions are found through a relative path from the NUnit engine to the package content, it depends on where both the engine and runner are located and where the package is located on your machine.
Here are some initial guidelines...
How to structure the package itself... your extension assembly itself should be in the tools directory. If there are other assemblies with it, which it references, it's best to also include a .addins file in the same directory, which lists that assembly on a single line. That way, the NUnit engine will save time by only examining the extension assembly.
A NuGet extension package will automatically be found by the engine if the runner has been installed as a nuget package as well. This works no matter how the packages are installed on your machine, i.e. using packages.config or in a nuget cache, provided both packages were installed the same way. (That proviso is a real gotcha and it may be that a future version of the engine needs to actually understand nuget.) See the addins file provided with the the NUnit 3 console runner as an example of why this works.
The same thing is true if both the runner and the extension are installed as chocolatey packages, because they are both in the chocolatey cache. If you do provide one (which I recomend) it has to be a "native" package - one that includes the actual binaries. A chocolatey package that merely invokes the nuget package will not work. See the source for any of the NUnit-provided extensions for an example of how this this is done.
If the executing copy of the engine (usually in the same directory as the runner) is anywhere else, there is no automatic way for the extension to be found. This includes the case where you are building a runner yourself and want the extension to be available while you are developing. In that case, you need to fully understand how the engine finds extensions (see the docs) and manually create an addins file (next to any that was distributed with the engine) containing the proper relative path.
This is especially complicated if you are developing an extension for general release. Then you have to deal with various runners installed in different ways by different people. OTOH, if you are doing this for internal use in your company, you may only need to deal with one of them. If you add more specifics about your goal to the question, I'll edit this with some more specific suggestions.

Internal NuGet install fails to install

I setup an internal NuGet server to host internal dll packages. The setup went smoothly. The spec and nupkg were created successfully. However, when I launch a test project and attempt to install it from Manage NuGet Packages it fails.
The internal package shows up under Manage NuGet Packages with an install button. I hit install but it does nothing. I check my references folder and saw nothing added.
If I check the Manage NuGet Packages at solution level, it has a green check mark indicate that it's installed but doesn't give me a Manage option to see which project it was installed to.
My issue is somewhat similar to this post below. The only difference is that I don't have sub folders for my library. I just have 1 dll and I'm putting the nupkg file directly under the Packages folder.
NuGet package fails to install
I'm not sure what I did wrong. Any suggestions?
Thanks to #MattWard for mentioned that the package got installed at the solution level. I went back to the official documentation here: https://docs.nuget.org/create/creating-and-publishing-a-package to review the differences with creating solution level package vs project level package and most important of all is the nuget naming convention when creating packages (the lib, content, etc. folder). I re-package my dll again with the naming convention and it works!

How do I correctly install nuget packages outside of VS and keep track of them?

I'm trying to use nuget.exe outside of Visual Studio as part of our build infrastructure. The idea is that the various build tools are fetched by a bootstrapper script that initializes a working copy. The bootstrapper does this by using a file that specifies the required tools and their version.
Broken approach 1 - use manually edited packages.config
At first, it seemed like a good idea to keep a manually edited packages.config file and use nuget restore to install them during bootstrapping. However, this does not work for tools that have dependencies, unless I list every single dependency in the packages.config as well, a much to arduous approach to be feasible, because I found no easy way to recursively find all dependencies of a package.
See also using nuget.exe commandline to install dependency .
Broken approach 2 - use nuget install to update packages.config
The second idea was then to use nuget install to install the packages, and let that command update the packages.config, very similar to the Install-Package cmdlet in the package manager console. But, surprisingly, nuget install does not support this! It either takes a packages.config or a package ID as parameter, but I found no way to update the packages.config with the new package and its dependencies.
This problem can also be found in another (two year old) SO question, see nuget.exe install not updating packages.config (or .csproj)?.
Is there a working (and non-hacky) approach at all?
This must be a problem that many people face when using nuget outside of VS, so what is the best approach in that case?
Of course, I could just parse the packages.config and emit a nuget install for each package, but I really don't want to re-invent the dependency management part of nuget, this is what I'm using nuget for in the first place. So I'm left with the feeling that either an -WithDependencies switch on nuget restore or an -UpdatePackagesConfig switch on nuget install is missing...
Note that there are other SO questions regarding the broken approaches described above. What I'd like to know it what the best approach is to solve the root problem, i.e. manage packages with dependencies outside of VS.
nuget install does not currently make changes to the project file.
nuget install can be used to either restore the NuGet packages listed in a packages.config file or download and extract them.
If you do not need the project being modified then your solution of reading the packages in the packages.config file and calling nuget install seems like a reasonable approach.
If you need the project to be modified then you could look at one of the following:
Ripple - a command line tool that adds extra features to NuGet. It has a ripple install command line which is similar to nuget install but it also updates the project file. It has a lot of other features for supporting build servers so this might be a good fit.
NuGet packages outside of Visual Studio with SharpDevelop - this was an experiment I put together to see whether full NuGet support could be achieved, including PowerShell scripts, from the command line without using Visual Studio. It uses PowerShell and quite a bit of SharpDevelop.
Customise NuGet.exe to do what you need. nuget update, for example, does modify the project file, at least for file references, but will not run PowerShell scripts. So you could take the NuGet.exe source code and extend it.
Of the above only 3) would give you exactly what you need. The other two would require a bit of work to read the packages from the packages.config file or some other list and then install them.
See my answer to Why does the nuget command line tool not follow dependencies?
nuget install My.Package.Id will follow dependencies. However, if you want to install multiple packages, you will need to create a batch file with a separate nuget install command for each package. These are top-level packages. You don't need to "install" the dependencies, as they will get downloaded automatically.
If you ultimately want a packages.config file, I imagine you can generate one by enumerating all the packages that were downloaded. However, you would have to take care not to include multiple versions of the same package.
I believe that how nuget 3 works with project.json files may do what you are looking for. Essentially my understanding is that the unit of dependency becomes the package and not necessarily individual assemblies. From what I recall, the idea is the have only one place to manage these types of package references which the project (IDE/Editor), package manager, and other command line tools can use.
What I don't understand and feel somewhat frustrated about is that it appears that the project.json concept is being canceled. I don't know if plans are to reintroduce it at anytime in the future. In the mean time I keep on hearing updated info on tooling that takes advantage of project.json such as nuget so where you can actually rely on this is something that is unclear to me at this point.

Get current version of package outside of Visual Studio

We are migrating over to using packages and NuGet for managing our dependencies on 3rd party components. This works well when referencing packages from within Visual Studio or building on the build server via msbuild.
However there are a number of files that we would like to access in our build scripts and installers. Previously these would be in source control with a well known path, now as the version of the package that we are consuming changes so the path to the package and hence the files is changing.
Is there a simple way I can get the path to a given package? The best solution I currently have is to search for all packages.config files and extract the package version from them.
Examples of the files that we need to access are
The NUnit console executable from the NUnit.Runners package for running unit tests.
License files from various packages that we redistribute with our installer.
Using the packages.config file is a pretty good solution. NuGet itself uses two approaches:
Reading the package information from the packages.config and using that to resolve to the packages path.
Enumerating all the directories in the packages directory.
You could use NuGet.Core to do either of the above if you do not want to write the code yourself. The classes that can be used are the DefaultPackagePathResolver, the PackageReferenceFile and LocalPackageRepository or SharedPackageRepository.
One problem with the second approach is that sometimes NuGet may occasionally leave behind NuGet packages that are not necessarily referenced by a project. In that case looking at the package directories may give you the incorrect information.
The only other approach I can think of might be to read the project files looking for the assembly references. Although that would not work for a solution level package such as NUnit.Runners.

NuGet package files not being copied to project content during build

I am building an MVC4 web application with VS2012 professional with NuGet Package Manager version 2.2.31210. I have multiple projects in my solution, all sharing various packages I installed using NuGet. One of my projects is an MVC4 web application where I am using packages such as bootstrap, jquery UI, etc, all installed using NuGet.
When I clone a fresh copy of my entire solution from my repository and build my MVC4 project, the package restore feature seems to be working: it creates the packages directory under the solution direcotry and populates it will all the versions of the packages I expect to see. However, the content files do not get copied to the appropriate places in the MVC app directory. The weird thing is that it does create directories for the content, but does not copy the content files themselves.
For example, I am using the Twitter Bootstrap package which appears in the packages/Twitter.Bootstrap.2.2.2. In the MVC project a directory called bootstrap (containing css, img, and js directories) gets created in the Content directory. But, no css or js files are copied into those directories!
Does anyone have a clue what magic incantation I must utter to get the build to copy these content files from the NuGet packages directory?
This is a very common issue we are all having. I've created an MSBuild Task NugetContentRestoreTask that will do this trick for you. Run the following command in the Package Manager Console:
Install Nuget Content Restore MSBuild Targets
PM> Install-Package MSBuild.NugetContentRestore
The only thing left is to call it from your BeforeBuild Target with something like this:
Project File Targets
<Target Name="BeforeBuild">
<NugetContentRestoreTask SolutionDir="$(SolutionDir)" ProjectDir="$(ProjectDir)" />
</Target>
You can take a look at the source repo and find it on nuget.org
Additional Content Folders
This nuget only includes the default folders scripts, images, fonts, and content, it is not a recursive directory includes. For additional content subfolders - you must assign the property AdditionalFolders.
<Target Name="BeforeBuild">
<NugetContentRestoreTask SolutionDir="$(SolutionDir)" ProjectDir="$(ProjectDir)"
AdditionalFolders="less;sass;common" />
</Target>
I have found a workaround, but it is ugly. By executing the following command in the NuGet Package Manager Console: Update-Package -Reinstall all the files are indeed copied to their proper places within the Mvc project Content and Scripts directories.
Unfortunately, this is risky because you are likely to end up with the wrong versions of certain packages. For example, in my case after the command finishes executing (which takes quite a while by the way), I end up with jQuery version 1.4.4. This is way old, and I assume it must be an explicit dependency of some other package that is being updated. So it appears that the order in which the packages actually get updated by NuGet is significant (it does not appear to parse the entire dependency tree for all packages and pick only the latest versions from the union of all dependencies, which seems like it would be the preferred behavior). Rather, as the command executes I see it replacing the jQuery package several times with different versions as it works its way through all the packages and their dependencies, only to end up with a very old version.
A similar approach is the execute the Update-Package -Reinstall command explicitly for each package that is causing my problem, but this is incredibly tedious and error prone.
The NuGet Package Restore feature should yield the same result as manually executing the Install-Package or Update-Package -Reinstall command for a package, but it does not.
I don't like to have the thirdparty JavaScript files under source control either. Thats why I've followed Jeff Handley advice in http://nuget.codeplex.com/workitem/2094 to create a solution my self. I didn't go the executable way, but created a nuget solution level package which does the trick.
http://www.nuget.org/packages/Baseclass.Contrib.Nuget.GitIgnoreContent/
It's tied to git, as it automatically updates the .gitignore file.
Short description:
Ignore nuget content files in git:
Generate entries in the .gitignore file to exclude nuget content files from the source repository
Restore nuget content files before building (Automatically in VS and manually with a powershell script
I've written a blog post describing how to use it.
http://www.baseclass.ch/blog/Lists/Beitraege/Post.aspx?ID=9&mobile=0
In Visual Studio 2015 Update 1, they now support contentFiles. The caveat with this is that it only works in projects that use project.json.
In reference to the problem that you are having, there is a good blog post that explains why you see this behaviour: NuGet Package Restore Common Misconceptions.
For my projects it turned out that content files work with PackageReferences only:
Existing project with nuget references via packages.config
Installed NuGet package with content files
Build project
No content files in output directory
Conversion of packages.config to PackageReferences
Build project
Content files have been copied to output directory
IDE is Visual Studio 2017. The project is an application project which means it is in the old csproj format.