{"action":"created","issue":{"url":"https://api.github.com/repos/cake-build/cake/issues/373","labels_url":"https://api.github.com/repos/cake-build/cake/issues/373/labels{/name}","comments_url":"https://api.github.com/repos/cake-build/cake/issues/373/comments","events_url":"https://api.github.com/repos/cake-build/cake/issues/373/events","html_url":"https://github.com/cake-build/cake/issues/373","id":102875172,"number":373,"title":"Issue with External nugets used directly via #addin directive","user":{"login":"jrnail23","id":392612,"avatar_url":"https://avatars.githubusercontent.com/u/392612?v=3","gravatar_id":"","url":"https://api.github.com/users/jrnail23","html_url":"https://github.com/jrnail23","followers_url":"https://api.github.com/users/jrnail23/followers","following_url":"https://api.github.com/users/jrnail23/following{/other_user}","gists_url":"https://api.github.com/users/jrnail23/gists{/gist_id}","starred_url":"https://api.github.com/users/jrnail23/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jrnail23/subscriptions","organizations_url":"https://api.github.com/users/jrnail23/orgs","repos_url":"https://api.github.com/users/jrnail23/repos","events_url":"https://api.github.com/users/jrnail23/events{/privacy}","received_events_url":"https://api.github.com/users/jrnail23/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"milestone":null,"comments":11,"created_at":"2015-08-24T19:42:20Z","updated_at":"2015-08-27T21:36:47Z","closed_at":null,"body":"I did some experimenting with using external nuget packages through the `#addin` directive, and I found that it only works when there is only a single dll file for each dll name in the referenced nupkg file.\r\n\r\nBefore I get into detail here, I should say that I assume what I'm trying to do here isn't really what the developer of Cake's `#addin` directive intended when writing it (there's really no documentation that I could find to explain the intended usage for the various ways to reference such dependencies).\r\n\r\nI'm sure my initial explanation was about as clear as mud, so here's an example:\r\n\r\nLet's say I want to use [Polly](https://www.nuget.org/packages/Polly) in my Cake script, so I do this:\r\n\r\n```C#\r\n#r \"./tools/Polly/lib/net45/Polly.dll\"\r\nusing Polly;\r\n\r\nTask(\"Default\")\r\n\t.Does(() => Policy.Handle<IOException>()\r\n\t\t.WaitAndRetry(10, i => TimeSpan.FromMilliseconds(50))\r\n\t\t.Execute(() => CleanDirectory(@\"c:\\MyFakeBinaries\")));\r\n\r\nRunTarget(\"Default\");\r\n```\r\nOk, so I run that, and it works.\r\n\r\nHowever, if I want to use Polly as an addin like this (because I don't want to have to specify the path to Polly.dll for various reasons -- among them being that I might like to specify the tools directory at runtime), I'm out of luck:\r\n\r\n```C#\r\n#addin Polly\r\nusing Polly;\r\n\r\nTask(\"Default\")\r\n\t.Does(() => Policy.Handle<IOException>()\r\n\t\t.WaitAndRetry(10, i => TimeSpan.FromMilliseconds(50))\r\n\t\t.Execute(() => CleanDirectory(@\"c:\\MyFakeBinaries\")));\r\n\r\nRunTarget(\"Default\");\r\n```\r\nResults in this:\r\n<pre>\r\nAll packages listed in packages.config are already installed.\r\nInstalling 'Polly 2.2.3'.\r\nSuccessfully installed 'Polly 2.2.3'.\r\nAddin: Polly, adding Reference C:/Dev/tools/Addins/Polly/lib/net35/Polly.dll\r\nAddin: Polly, adding Reference C:/Dev/tools/Addins/Polly/lib/net40/Polly.dll\r\nAddin: Polly, adding Reference C:/Dev/tools/Addins/Polly/lib/net45/Polly.dll\r\nAddin: Polly, adding Reference C:/Dev/tools/Addins/Polly/lib/portable-net45+netcore45+wpa81+wp8+MonoAndroid1+MonoTouch1/Polly.dll\r\n<b>Error: error CS1704: An assembly with the same simple name 'Polly' has already been imported.  Try removing one of the references (e.g. 'C:\\Dev\\tools\\Addins\\Polly\\lib\\net45\\Polly.dll') or sign them to enable side-by-side.</b>\r\n</pre>\r\n\r\nOkay, so apparently if I want to (and I don't really want to), I can use [Polly-Signed](https://www.nuget.org/packages/Polly-Signed) instead to resolve this, although when I did, I got this:\r\n \r\n<pre>\r\nAll packages listed in packages.config are already installed.\r\nAddin: Polly-Signed, adding Reference C:/Dev/tools/Addins/Polly-Signed/lib/net35/Polly.dll\r\nAddin: Polly-Signed, adding Reference C:/Dev/tools/Addins/Polly-Signed/lib/net40/Polly.dll\r\nAddin: Polly-Signed, adding Reference C:/Dev/tools/Addins/Polly-Signed/lib/net45/Polly.dll\r\nAddin: Polly-Signed, adding Reference C:/Dev/tools/Addins/Polly-Signed/lib/portable-net45+netcore45+wpa81+wp8+MonoAndroid1+MonoTouch1/Polly.dll\r\n<b>Error: C:/Dev/PollyTest.csx(5,14): error CS0012: The type 'System.Object' is defined in an assembly that is not referenced.  You must add a reference to assembly 'System.Runtime, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'.</b>\r\n</pre>\r\n\r\nSince I never really wanted to use Polly-Signed anyway, let's ignore this -- I just wanted to include that for your info.\r\n\r\nAs you can see from the output above, the Polly nupkg has the following file structure:\r\n\r\n> - /Polly\r\n>   - /lib\r\n>     - /net35\r\n>       - Polly.dll\r\n>     - /net40\r\n>       - Polly.dll\r\n>     - /net45\r\n>       - Polly.dll\r\n>     - /portable-net45+netcore45+wpa81+wp8+MonoAndroid1+MonoTouch1\r\n>       - Polly.dll\r\n\r\nCake's [AddInDirectiveProcessor](https://github.com/cake-build/cake/blob/develop/src/Cake.Core/Scripting/Processors/AddInDirectiveProcessor.cs#L182) recursively finds all DLLs (not named Cake.Core.dll) under `/Addins/Polly/` and loads them all, regardless of name or target version, causing the above error (`Error: error CS1704: An assembly with the same simple name 'Polly' has already been imported. `).\r\n\r\nSo that seems to be the heart of the issue -- that Cake doesn't use a particular target version to load assemblies from nuget.  Further research suggested that because it's being added outside the context of Visual Studio, we don't have the context to decide which version is appropriate, but I managed to figure out how this can be remedied.\r\n\r\nIn [NuGet.Core](https://www.nuget.org/packages/NuGet.Core/), there's a `NuGet.VersionUtility` class that can be used to match those target-version-specific folder names to the current runtime framework version, like this:\r\n\r\n```C#\r\nvar version = VersionUtility.GetShortFrameworkName(new FrameworkName(AppDomain.CurrentDomain.SetupInformation.TargetFrameworkName)));\r\n\r\n// version == \"net452\" when running under 4.5.2 (AppDomain.CurrentDomain.SetupInformation.TargetFrameworkName == \".NETFramework,Version=v4.5.2\")\r\n```\r\n\r\nOf course the downside of this is that it would require taking a dependency on NuGet.Core (unless simply duplicating NuGet's implementation of `GetShortFrameworkName()` is preferable).\r\n\r\nSo.... any thoughts? Am I barking up the wrong tree entirely?"},"comment":{"url":"https://api.github.com/repos/cake-build/cake/issues/comments/135562536","html_url":"https://github.com/cake-build/cake/issues/373#issuecomment-135562536","issue_url":"https://api.github.com/repos/cake-build/cake/issues/373","id":135562536,"user":{"login":"RichiCoder1","id":2391878,"avatar_url":"https://avatars.githubusercontent.com/u/2391878?v=3","gravatar_id":"","url":"https://api.github.com/users/RichiCoder1","html_url":"https://github.com/RichiCoder1","followers_url":"https://api.github.com/users/RichiCoder1/followers","following_url":"https://api.github.com/users/RichiCoder1/following{/other_user}","gists_url":"https://api.github.com/users/RichiCoder1/gists{/gist_id}","starred_url":"https://api.github.com/users/RichiCoder1/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/RichiCoder1/subscriptions","organizations_url":"https://api.github.com/users/RichiCoder1/orgs","repos_url":"https://api.github.com/users/RichiCoder1/repos","events_url":"https://api.github.com/users/RichiCoder1/events{/privacy}","received_events_url":"https://api.github.com/users/RichiCoder1/received_events","type":"User","site_admin":false},"created_at":"2015-08-27T21:36:47Z","updated_at":"2015-08-27T21:36:47Z","body":"@jrnail23 We should target the version that makes the most sense when interoping with Nuget feeds. If we really want the ability to potentially target a newer (or older) nuget, we could make the resolution library external and then have Cake import it so you can swap out your own. Use the interface that @patriksvensson mentioned and MEF and baring any major changes you're good. It basically needs to do two things: Install this package to this folder with this info (version, prerelease, etc...), and tell me what dlls I can/should reference for that package."}}