Install NuGet package programmatically - nuget

I'm trying to install a simple nuget-package programatically. I have created a package with a Site.css file in it. So it resides in the content folder of the package.
Using this code
public void TestInstall(string packageID, string physicalPath)
{
var rep = PackageRepositoryFactory.Default.CreateRepository(new PackageSource("http://nuget.testserver.lan/nuget", "Default"));
var packagemgr = new PackageManager(
rep,
new DefaultPackagePathResolver("http://nuget.testserver.lan/nuget"),
new PhysicalFileSystem(physicalPath)
);
var package = rep.FindPackagesById(packageID).First();
packagemgr.InstallPackage(package, false);
}
Lets say I provide packageID = 'Testpackage' and physicalPath = 'c:\inetpub\test' it creates:
c:\Inetpub\test\Testpackage
and that folder contains:
the content folder with the Site.css AND the Testpackage.0.1.nupkg
Not quite what I'm trying to do but sort of :)
Is it possible to change it so:
I can specify where it should place the package for its cache-functionality
Make it place whatever resides in the content folder to the specified path?
If the package contains dll's in the lib-folder have them go in the bin-directory (create if not exist)

A lot of the functionality of NuGet currently relies on Visual Studio automation, so outside of VS it's difficult to get all of the same behaviour.
Lot of people have asked for functionality that would require changes from using VS automation, so I suspect it's probably on the roadmap, as it's significant work, I don't think it will be soon.
Don't forget you can install packages in the Visual Package Manager console, so it's only a single command (Install-Package MarkdownHelper) and doesn't require clicking through the UI.

Related

Nuget package missing .target file in build folder

I have build a nuget package at published it to a nuget.server site. But when I try to use the package form the server the .targets file from build folder is not in the file. But if I use the package from a local folder it works as it should. How do I get it to work ?
If i look in the package in the folder on the server it looks ok.
It's not clear to me if you mean using (referencing and restoring) a package, or building (packing) a package.
If the problem is with packing the nupkg, NuGet requires the props and targets files to have specific filenames in specific folders, but if you got it to work at least once, you probably already know that. If this is not the problem with packing, you need to give us more information because not using the correct filename convention is the most common problem and I can't guess what else the problem could be. In particular, if the package is being packed differently on your local machine compared to when it is packed on the server, it means there is something different between how you pack on the two computers, so we need more information about how the build and pack work with your project.
If the problem is with using (restoring) the package, there are a few possibilities. My best guess is that you once had a package without the targets file working correctly, and you restored the package on the server. By design, NuGet packages are immutable which means it's invalid for the contents of a package (same ID and version) to change. This allows NuGet to download the package from a remote feed once, save it in the global package folder (not a cache; they never expire) and the next time NuGet needs to restore the same package (id + version) it uses the one in the global package folder, it does not download again. This means if you once built a bad nupkg and restored it on a machine, then fix the nupkg and kept the same version number, that machine will never get the fixed nupkg. You need to delete it from the global packages folder. I'm not 100% sure, but I think if you have a local file feed and you restore a project that uses packages.config, the nupkg does not get saved in the global packages folder, so doesn't have the same problem. In short, I think the problem is that you changed the nupkg contents once without changing the version number, and one of the machines has the old copy in its global packages folder that it keeps using.
If that's not the problem, the next most likely cause is that the nupkg on the server feed has different contents to the nupkg in the local feed. I've never used NuGet.Server, but some nuget respositories (like nuget.org) do not allow overwriting nupkgs. So, if you pushed a nupkg to your server, fixed a problem in your nupkg without changing the version, then tried to push again, the second push might have failed.
In summary, your question doesn't provide enough information for us to help you, but I wrote about the most common issues above. If it doesn't help, you need to provide us with more information. An example of the problem is the best way to give us enough information to help you.

How to change the tutorial folder in Orange?

The default orange tutorial folder is the following:
..\Canopy32\User\Lib\site-packages\Orange\OrangeCanvas\application\tutorials\
What if I want to change this location? Or add another folder?
Also would it be possible to achieve this by simply having a configuration file inside OrangeWidget folder?
Help please,
Many thanks.
You cannot change the default location of tutorials, but you can add additional tutorial folders using entry point in setup.py.
First, you need to create a python package containing schema (ows) files. Then you need to add an entry point in the setup.py pointing to the location of the package you have created.
If the package with custom tutorials can be imported using import my_tutorials, your entry_point will look like this:
ENTRY_POINTS = {
'orange.widgets.tutorials': (
'my_tutorials = my_tutorials',
),
}
I have created a sample add-on that registers additional tutorials. It is available on github:
https://github.com/astaric/orange-custom-tutorials-example
If you download the code and run python setup.py install, you will see a new entry in the tutorials.

NuGet Package Manager to manage packages fills hard drive over time

I have an application that uses NuGet packages to manage versions of tooling available to an instance of the application.
For instance, A Test Manager, the actual Tests that are executed by the Manager are contained in a .nupkg file. If you want to change which tests are executed all you have to do is replace the .nupkg file. When the application runs it finds the package and uses the package manager to get all the files out and add them into my app domain.
The package manager extracts all the files into a temp folder and returns the directory they were extracted to.
Unfortunately every time the application runs it extracts to a new random location because of this block of code in OptimizedZipPackage:
protected virtual string GetExpandedFolderPath()
{
return Path.GetRandomFileName();
}
Yes it is virtual and I can override it in my own version of the package, but in order to use my own version of the package I also have to have my own version of the LocalPackageRepository class, with an override.
What I'm hoping for is an way to get fixed folder names so it uses the same folder for the same package/version every time without having to write override classes.

Why NuGet adds app.config with assemblyBinding to LIBRARY projects during a NuGet package update?

Isn't this information necessary only in the executable's project?
How to disable this file creation?
NuGet 2.8
EDIT
Library projects were exceptions in NuGet 2.7, behavior changed in 2.8 by fixing this issue: http://nuget.codeplex.com/workitem/3827 with commit: https://github.com/NuGet/NuGet2/commit/448652d028e3f01ba4022e147baaf4e1fb3f969b
The reason that the NuGet package manager adds assembly binding redirects to library projects is because there are types of projects where the output type is a library, but there are special mechanisms in place to assure that the library's app or web config file will be applied at runtime. This is opposed to more typical library usage that you're probably familiar with, wherein the library's config file is not used at all.
For example, Azure Web and Worker role projects in Azure SDK 1.8+ will produce libraries, but when they are wrapped in an exe by IIS, the library's config file will be set as the default for that exe. That way you get all your application configuration without having to explicitly publish a special config file with the same name as the wrapping executable, which is how it used to be done. Now the build process outputs the renamed config file (e.g. app.config -> myWebRoleLibrary.dll.config), and everything works as it should.
XUnit also does something similar; loading the app.config of the test assembly instead of the app config of the test runner process.
It's worth mentioning that you can also manually load a config file in any project, library or not. You would have to ensure that the config file ended up in the right place, but it is possible. This is less applicable for binding redirects though, since usually those are solely used by the assembly loader in the CLR. I suppose you could hook AssemblyLoad but now we're well on our way to poorly reinventing the wheel.
So, the answer to "is it necessary in my library project?" is maybe. If your library project is not a web or worker role or test project, and it doesn't manually load a configuration file, then the app.config is probably benign but unnecessary.
As for disabling it, you can only do that at the Visual Studio level. You can find the option in VS2019 at: Tools -> Options... -> NuGet Package Manager -> General -> Skip applying binding redirects.
What uses my configuration files?
The Compiler (csc.exe)
The compiler uses the config file of the assembly being built for one reason: to find and use supportPortability elements.
The link above lays out rare scenario where you would need that compiler option, but an overwhelming majority of users will not. Suffice it to say, if you don't know if you're using that feature, you are not.
It does not parse any of the other elements of the config file, including assembly binding redirects which are the elements that NuGet adds.
The Build Engine (msbuild)
MSBuild uses app configs in a few of its steps but importantly not to find the primary dependencies, which it will pass to csc.exe in the form of /reference: options.
In order to find the primary references MSBuild (and specifically the ResolveAssemblyReference task) will search a collection of paths enumerated in the common targets file. If it cannot find an explicit dependency in your csproj, it will issue a warning and likely an error further on if the dependency is required for compilation.
After that it will search for transitive dependencies. It does not pass these files to the compiler, but instead uses them to generate a list of files that need to be considered in subsequent build steps for things like generating license files, trust information, and suggested binding redirects. This step does consider the project's config file, and specifically uses its binding redirects to inform the list of transitive dependencies. It's important to note that building an exe will not consider its library's app.config files during the build, and a library's app.config will not change the way that library’s dll is produced.
The Runtime (CLR)
The CLR uses the config files to change the way it locates assemblies.
IIS
IIS will read elements of your web.config file to change the way your web app behaves. For example, caching characteristics.
Applications
Applications may manually retrieve configuration data from config files using the ConfigurationManager.
Assembly binding redirects are as valid in a class library as they are in executable projects.
Think about this; when building your application, how will the compiler know which version of referenced assemblies to use (for the class libraries)?
Often this will work just fine, without the redirects, but when you stumble over a machine that has a GAC'ed version of the assembly, you could get into trouble.
I suggest you read the assembly binding redirect documentation to better understand what it is and does.
NuGet adds the app.config with redirects to help you, and quite frankly, I don't get the fuzz about an extra app.config for everything to work as expected.
As of today, it will add redirects to all projects, except the following types:
WiX
JS
Nemerle
C++
Synergex
Visual Studio
Windows Store App
As far as I know, there's no way of turning this off. You could create an issue at Github if this is a problem.
The source code for adding assembly binding redirects can be found here.
I created a little console app that checks all the date of the app.config files and then auto deletes them from your .csproj and the file. Todo: delete from tfs.
Perhaps this could help.
class Program
{
private static string RootFolder;
private static string AppConfigName;
private static bool AskConfirmation = true;
static void Main(string[] args)
{
try
{
AppConfigName = "app.config";
RootFolder = #"<Your project path>";
ScanDir(RootFolder);
Console.WriteLine();
Console.WriteLine("DONE!");
Console.WriteLine("Press ENTER to finish...");
Console.ReadLine();
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
private static void ScanDir(string directoryParent)
{
var dirs = Directory.GetDirectories(directoryParent);
foreach (var dir in dirs)
{
var dirInfo = new DirectoryInfo(dir);
if (dirInfo.Name == "bin" || dirInfo.Name == "obj" || dirInfo.Name == "debug" || dirInfo.Name == "tempPE" || dirInfo.Name == "java" || dirInfo.Name == "res") continue;
var files = Directory.GetFiles(dir, "app.config");
if (files.Length == 0)
{
ScanDir(dir);
continue;
}
Process(dir);
//ScanDir(dir);
}
}
private static void Process(string dir)
{
var fi = new FileInfo(Path.Combine(dir, AppConfigName));
if (fi.CreationTime.Date != DateTime.Now.Date) return;
if (AskConfirmation)
{
Console.WriteLine("Scan " + dir.Replace(RootFolder, ""));
Console.Write("Remove (y)es or (n)o ?");
var key = Console.ReadKey();
Console.WriteLine();
if (key.Key.ToString() =="Y")
// remove app.config
RemoveAppConfig(dir, fi);
}
else
RemoveAppConfig(dir, fi);
}
private static void RemoveAppConfig(string dir, FileInfo fi)
{
var csProjs = Directory.GetFiles(dir, "*.csproj");
foreach (var csProj in csProjs)
{
var txt = File.ReadAllText(csProj);
txt = Regex.Replace(txt,"<None Include=\"App.Config\" />", "",RegexOptions.IgnoreCase);
File.Delete(csProj);
File.WriteAllText(csProj, txt);
}
File.Delete(fi.FullName);
// todo: undo in tfs
Console.WriteLine("Deleted");
}
}

How to read local packages folder using NuGet?

I am trying to read my local solution packages folder using NuGet.Core.
If I create new UnzippedPackageRepository(pathToPackages) and call GetPackages() on it, the result is empty. I am looking at the source of UnzippedPackageRepository and it has:
from file in FileSystem.GetFiles("", "*" + Constants.PackageExtension)
let packageName = Path.GetFileNameWithoutExtension(file)
where FileSystem.DirectoryExists(packageName)
select new UnzippedPackage(FileSystem, packageName)
So it seems to expect *.nupkg for each package in top level?
Anyway, what is right way to read solution package store aside from going through each folder and creating UnzippedPackage manually?
Solved it, solution packages folder is handled by SharedPackageRepository.