New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support setting CopyLocal to false on references added by NuGet #329

Closed
eerhardt opened this Issue Apr 1, 2015 · 13 comments

Comments

Projects
None yet
8 participants
@eerhardt

eerhardt commented Apr 1, 2015

There are plenty of scenarios where NuGet package authors want CopyLocal set to 'false' on a reference by default after installing their package. One such example is when using the VSIX packaging to create Visual Studio extensions. When CopyLocal is true, the referenced assembly will automatically be packaged into the output VSIX.
Currently, the only way to set CopyLocal to false is to use a powershell script:
http://stackoverflow.com/questions/11105286/create-nuget-package-which-installs-references-with-copy-local-set-to-false
http://nuget.codeplex.com/workitem/1340
http://geekswithblogs.net/JoshReuben/archive/2012/09/23/real-world-nuget.aspx (See section “Forcing ‘copy local=false’)

However, guidance from Yishai Galatzer has been to not use powershell because "they only work from within VS, and they tend to be fragile long term."

NuGet should officially support CopyLocal=false references.

@yishaigalatzer yishaigalatzer added this to the 3.1.0-Beta milestone Apr 14, 2015

@yishaigalatzer

This comment has been minimized.

Show comment
Hide comment
@yishaigalatzer

yishaigalatzer Nov 25, 2015

@eerhardt have been trying to understand the core reason to prevent copy local to false (at the package level), and I don't see a really good one.

Can you share your scenario, so we can look again at prioritizing this item.

CC @davidfowl

yishaigalatzer commented Nov 25, 2015

@eerhardt have been trying to understand the core reason to prevent copy local to false (at the package level), and I don't see a really good one.

Can you share your scenario, so we can look again at prioritizing this item.

CC @davidfowl

@eerhardt

This comment has been minimized.

Show comment
Hide comment
@eerhardt

eerhardt Nov 30, 2015

At the time, I was building a VS extension point. In order for VS extensions to consume our APIs, we need to ship them a “Contracts” assembly that they will reference. We will ship this Contracts assembly as a NuGet package. Using the VSIX packaging technology, whenever you have a CopyLocal=true reference, that reference will automatically be included in the output VSIX.

Since our Contracts assembly ships as part of VS, there is no need for a bunch of different VS extensions to package and install multiple copies of this Contracts assembly in each of their VSIXs. The Contracts assembly will already be installed and loaded in VS. Thus, by default we want CopyLocal to be set to ‘false’, so that this Contracts assembly isn’t included in all these extensions’ VSIXs.

Since VS is starting to ship all of its Contracts assemblies as NuGet packages: https://www.nuget.org/profiles/VisualStudioExtensibility, this same scenario can be applied to any VS extension. There is no need for every VS extension to package all of the VS Contracts assemblies in their VSIXs, since VS already has them installed and loaded.

eerhardt commented Nov 30, 2015

At the time, I was building a VS extension point. In order for VS extensions to consume our APIs, we need to ship them a “Contracts” assembly that they will reference. We will ship this Contracts assembly as a NuGet package. Using the VSIX packaging technology, whenever you have a CopyLocal=true reference, that reference will automatically be included in the output VSIX.

Since our Contracts assembly ships as part of VS, there is no need for a bunch of different VS extensions to package and install multiple copies of this Contracts assembly in each of their VSIXs. The Contracts assembly will already be installed and loaded in VS. Thus, by default we want CopyLocal to be set to ‘false’, so that this Contracts assembly isn’t included in all these extensions’ VSIXs.

Since VS is starting to ship all of its Contracts assemblies as NuGet packages: https://www.nuget.org/profiles/VisualStudioExtensibility, this same scenario can be applied to any VS extension. There is no need for every VS extension to package all of the VS Contracts assemblies in their VSIXs, since VS already has them installed and loaded.

@yishaigalatzer yishaigalatzer modified the milestones: 3.5 Beta, 3.3.0 Mar 10, 2016

@yishaigalatzer

This comment has been minimized.

Show comment
Hide comment
@yishaigalatzer

yishaigalatzer Mar 10, 2016

The guidance from andrew arnott was not to go this way. #452

yishaigalatzer commented Mar 10, 2016

The guidance from andrew arnott was not to go this way. #452

@Andrey-Bushman

This comment has been minimized.

Show comment
Hide comment
@Andrey-Bushman

Andrey-Bushman Jul 20, 2016

It is very strange that @yishaigalatzer don't understand when it is necessary and marked it as WontFix... Set CopyLocal to false is often required for plugins developing. For example it is required for AutoCAD plugins developing. Of course it is true for plugins developing for other applications also. Reopen this issue, please.

Andrey-Bushman commented Jul 20, 2016

It is very strange that @yishaigalatzer don't understand when it is necessary and marked it as WontFix... Set CopyLocal to false is often required for plugins developing. For example it is required for AutoCAD plugins developing. Of course it is true for plugins developing for other applications also. Reopen this issue, please.

@yishaigalatzer

This comment has been minimized.

Show comment
Hide comment
@yishaigalatzer

yishaigalatzer Jul 20, 2016

Andrey, please spell out the exact reason. The scenario Eric brought up was not a valid one and the visual studio team recommended not to go there.

yishaigalatzer commented Jul 20, 2016

Andrey, please spell out the exact reason. The scenario Eric brought up was not a valid one and the visual studio team recommended not to go there.

@Andrey-Bushman

This comment has been minimized.

Show comment
Hide comment
@Andrey-Bushman

Andrey-Bushman Jul 20, 2016

Autodesk company provides AutoCAD .NET API for developers. This API is part of ObjectARX SDK. It requires set CopyLocal to false for its managed DLL files. Look here the position number 3, please:

Browse to the install directory for AutoCAD Civil 3D, and select the base libraries acdbmgd.dll, acmgd.dll, accoremgd.dll, AecBaseMgd.dll, and AeccDbMgd.dll.
Note:

These are the base AutoCAD and AutoCAD Civil 3D managed libraries. Your .NET assembly can use classes defined in additional libraries.

To allow debugging and reduce the disk space requirements for your projects, select these libraries in the Visual Studio Solution Explorer, and set the Copy Local property to False.

So, it is necessary for each developer which writes the extensions for AutoCAD or its vertical products. Without changing of this property the debugging of AutoCAD extensions will not be possible.

Andrey-Bushman commented Jul 20, 2016

Autodesk company provides AutoCAD .NET API for developers. This API is part of ObjectARX SDK. It requires set CopyLocal to false for its managed DLL files. Look here the position number 3, please:

Browse to the install directory for AutoCAD Civil 3D, and select the base libraries acdbmgd.dll, acmgd.dll, accoremgd.dll, AecBaseMgd.dll, and AeccDbMgd.dll.
Note:

These are the base AutoCAD and AutoCAD Civil 3D managed libraries. Your .NET assembly can use classes defined in additional libraries.

To allow debugging and reduce the disk space requirements for your projects, select these libraries in the Visual Studio Solution Explorer, and set the Copy Local property to False.

So, it is necessary for each developer which writes the extensions for AutoCAD or its vertical products. Without changing of this property the debugging of AutoCAD extensions will not be possible.

@yishaigalatzer

This comment has been minimized.

Show comment
Hide comment
@yishaigalatzer

yishaigalatzer Jul 20, 2016

I see, this is a similar scenario to the visual studio extensibility. I would assume that a developer should not reship these libraries and they should go through a common package that Autodesk ships (and revs us necessary), I would advise contacting them for that rather than reshipping and bundling your own.

Now back to your question: are you shipping these internally or do you plan to ship on nuget.org?

I believe you can achieve the guidance for either packages.config scenarios OR project.json scenarios OR both, each has a slightly different solution. As we are trying to slowly move everyone to the project.json model, I would suggest starting with that:

Just add the dlls to a ref folder (requires vs 2015)

If you want it for packages.config as far as I know most people use an install.ps1 script to change the flag.

Last method that will work everywhere is to create an msbuild target and include the references any way you choose to while disabling copy to output.

yishaigalatzer commented Jul 20, 2016

I see, this is a similar scenario to the visual studio extensibility. I would assume that a developer should not reship these libraries and they should go through a common package that Autodesk ships (and revs us necessary), I would advise contacting them for that rather than reshipping and bundling your own.

Now back to your question: are you shipping these internally or do you plan to ship on nuget.org?

I believe you can achieve the guidance for either packages.config scenarios OR project.json scenarios OR both, each has a slightly different solution. As we are trying to slowly move everyone to the project.json model, I would suggest starting with that:

Just add the dlls to a ref folder (requires vs 2015)

If you want it for packages.config as far as I know most people use an install.ps1 script to change the flag.

Last method that will work everywhere is to create an msbuild target and include the references any way you choose to while disabling copy to output.

@BenKmann

This comment has been minimized.

Show comment
Hide comment
@BenKmann

BenKmann Nov 8, 2016

In the current Release Notes ( https://docs.nuget.org/ndocs/release-notes/nuget-3.5-RTM ) you mark this Ticket as a new Feature.
But it seems to be, that this isn't the case.

I really would like this as a Feature. It is a useful Feature for every AddIn Developer, who wants to use (Internal) Nuget-Packages which are not allowed to be copied to the output Folder, because Frameworks like Microsoft MEF don't like it, when you double the Assemblies in your AddIn Folder that the Executable already has loaded.

The Problem with the Alternatives, like the install.ps1 skript from Stackoverflow is, that it produces duplicate/new CopyLocal Entries in the csproj-File and makes the csproj buggy (as the user here http://stackoverflow.com/questions/11105286/create-nuget-package-which-installs-references-with-copy-local-set-to-false#comment64690207_11106429 also describes).

BenKmann commented Nov 8, 2016

In the current Release Notes ( https://docs.nuget.org/ndocs/release-notes/nuget-3.5-RTM ) you mark this Ticket as a new Feature.
But it seems to be, that this isn't the case.

I really would like this as a Feature. It is a useful Feature for every AddIn Developer, who wants to use (Internal) Nuget-Packages which are not allowed to be copied to the output Folder, because Frameworks like Microsoft MEF don't like it, when you double the Assemblies in your AddIn Folder that the Executable already has loaded.

The Problem with the Alternatives, like the install.ps1 skript from Stackoverflow is, that it produces duplicate/new CopyLocal Entries in the csproj-File and makes the csproj buggy (as the user here http://stackoverflow.com/questions/11105286/create-nuget-package-which-installs-references-with-copy-local-set-to-false#comment64690207_11106429 also describes).

@borland

This comment has been minimized.

Show comment
Hide comment
@borland

borland Jul 31, 2017

We have this scenario as well, I'll explain ours:

We have a base application, which includes references to various Nuget packages.

Our application supports plugins - we have a "Plugins" folder where we drop dll's in, and they're all loaded using the Managed Extensibility Framework (MEF).

When creating a plugin dll, those plugins neccessarily need to add references to components from the base application (interfaces, utility libraries, contracts and such). Some of those in turn take a dependency on third party things like Newtonsoft.Json, Microsoft.WebApi.Core and so forth.

We used to largely ignore Nuget and just have all our DLL's stored locally in TFS, and as such we'd add references manually to dll's and set copy local: false on them, which was fine.
If someone forgot to set copy local: false, then there'd end up being a copy of Newtonsoft.Json, WebApi.Core and whatever else in both the base application directory AND the plugins sub directory. This would cause two copies of things to get loaded and screw things up, usually causing our application to fail to start.

We've now switched various things over to Nuget and the new CSProj format using and the inability to set copy local: false on these things results in the above problem (A copy of dll's in both the base AND plugins directories - causing our application not to start.

borland commented Jul 31, 2017

We have this scenario as well, I'll explain ours:

We have a base application, which includes references to various Nuget packages.

Our application supports plugins - we have a "Plugins" folder where we drop dll's in, and they're all loaded using the Managed Extensibility Framework (MEF).

When creating a plugin dll, those plugins neccessarily need to add references to components from the base application (interfaces, utility libraries, contracts and such). Some of those in turn take a dependency on third party things like Newtonsoft.Json, Microsoft.WebApi.Core and so forth.

We used to largely ignore Nuget and just have all our DLL's stored locally in TFS, and as such we'd add references manually to dll's and set copy local: false on them, which was fine.
If someone forgot to set copy local: false, then there'd end up being a copy of Newtonsoft.Json, WebApi.Core and whatever else in both the base application directory AND the plugins sub directory. This would cause two copies of things to get loaded and screw things up, usually causing our application to fail to start.

We've now switched various things over to Nuget and the new CSProj format using and the inability to set copy local: false on these things results in the above problem (A copy of dll's in both the base AND plugins directories - causing our application not to start.

@kellcomnet2

This comment has been minimized.

Show comment
Hide comment
@kellcomnet2

kellcomnet2 Nov 24, 2017

I have this need as well with another plugin architecture, the code has to use the existing copy of the dll on the end pc but to develop against it I import the reference then set copy local to false.

kellcomnet2 commented Nov 24, 2017

I have this need as well with another plugin architecture, the code has to use the existing copy of the dll on the end pc but to develop against it I import the reference then set copy local to false.

@jnm2

This comment has been minimized.

Show comment
Hide comment
@jnm2

jnm2 Nov 24, 2017

I ran into this too. Right now I'm dealing with it by including this .targets:

<Project>

  <Target Name="PreventFooSDKCopyLocal" AfterTargets="ResolveReferences">
    <ItemGroup>
      <ReferenceCopyLocalPaths Remove="@(ReferenceCopyLocalPaths)" Condition="'%(ReferenceCopyLocalPaths.NuGetPackageId)' == 'Foo.SDK.PackageId'" />
    </ItemGroup>
  </Target>

</Project>

jnm2 commented Nov 24, 2017

I ran into this too. Right now I'm dealing with it by including this .targets:

<Project>

  <Target Name="PreventFooSDKCopyLocal" AfterTargets="ResolveReferences">
    <ItemGroup>
      <ReferenceCopyLocalPaths Remove="@(ReferenceCopyLocalPaths)" Condition="'%(ReferenceCopyLocalPaths.NuGetPackageId)' == 'Foo.SDK.PackageId'" />
    </ItemGroup>
  </Target>

</Project>
@jnm2

This comment has been minimized.

Show comment
Hide comment
@jnm2

jnm2 Dec 28, 2017

Fails miserably in projects that use packages.config, though. There is still a reason to use packages.config in projects that use this SDK package, sadly, because VS2012 is the latest version of Visual Studio that doesn't crash when using the designer with controls that use the legacy security policy (see https://stackoverflow.com/questions/20978721/visual-studio-2013-crashes-with-netfx40-legacysecuritypolicy-dynamic-operation).

Anyone know of a way to cause <Reference> elements added to legacy csproj while installing a NuGet package to have Private="False"?

jnm2 commented Dec 28, 2017

Fails miserably in projects that use packages.config, though. There is still a reason to use packages.config in projects that use this SDK package, sadly, because VS2012 is the latest version of Visual Studio that doesn't crash when using the designer with controls that use the legacy security policy (see https://stackoverflow.com/questions/20978721/visual-studio-2013-crashes-with-netfx40-legacysecuritypolicy-dynamic-operation).

Anyone know of a way to cause <Reference> elements added to legacy csproj while installing a NuGet package to have Private="False"?

@teocomi

This comment has been minimized.

Show comment
Hide comment
@teocomi

teocomi Mar 27, 2018

I'm encountering this issue too, especially when creating VSIX templates for software addins/plugins. CopyLocal needs to be set to False.

teocomi commented Mar 27, 2018

I'm encountering this issue too, especially when creating VSIX templates for software addins/plugins. CopyLocal needs to be set to False.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment