简体   繁体   中英

NuGet packages: Place dll and config files under a sub-directory

Found many outdated and/or relevant-but-not-enough solutions, hence i will give it a shot hoping that i am not asking a duplicate question.

Context

  • I use a plugin system which loads the plugin dlls located under the 'bin/ Plugin ' folder.
  • Each plugin comes with a config file (ie MyPlugin.dll + MyPlugin.config)
  • Each plugin is distributed using a private NuGet server .
  • There are no '.nuspec' files in my project. The '.nupkg' package is generated using '.csproj' and the 'nuspec' is auto-generated by the nuget pack command.
  • Both the NuGet project and the project that consumes the NuGet are using .NetFramework and packages.config (instead of packageReferences ).

Goal

Since the plugins are distributed using NuGet, there are 2 points to be taken care of:

  1. When installing the NuGet package, instead of placing the dll to the 'bin' folder, it should be placed in the 'bin/Plugin' sub-folder.
  2. Include the '.config' in the NuGet package and place it under the same location.

Any suggestions on how to accomplish (1) and (2)?


Removed the previously added unsuccessful steps from the question and posted an answer

In order to achieve this , you should create a <package_id>.props file which can copy these files into the target path as you want.

1) In your MyPlugin library project, you should create a file called <package_id>.props under Build folder.

在此处输入图片说明

then add these content in that new file:

<Project>
    <Target Name="CopyToFolder" BeforeTargets="Build">
        <ItemGroup>
            <Files Include="$(MSBuildThisFileDirectory)..\File\*.*"></Files>
        </ItemGroup>
        <Copy SourceFiles="@(Files)" DestinationFolder="$(ProjectDir)bin\Plugin"></Copy>
        
    </Target>

</Project>

2) add these node in your MyPlugin.csproj file:

<ItemGroup>
    <None Include="xxx\MyPlugin.dll(the path of MyPlugin.dll in your project)" Pack="true" PackagePath="File"></None>
    <None Include="xxx\MyPlugin.config(the path of MyPlugin.dll in your project)" Pack="true" PackagePath="File"></None>
    <None Include="Build\MyPlugin.props" Pack="true" PackagePath="build"></None>
</ItemGroup>
    

3) the repack MyPlugin project by click Pack menu. And before you install this new version of nuget package, you should first clean nuget caches or delete all caches files under C:\\Users\\xxx(current user)\\.nuget\\packages .

Besides , there is also a similar thread you can refer to .

===================================================

Update 1

For Step 1 description:

The .props file must be named as your package_id so that it will work on the nuget nupkg file. Please see my link which I provided on the above.

For an example , if you nuget package is named as MyPlugin.1.0.0.nupkg , so the props file should be named as MyPlugin.props file. The propose of the target is copy the files from the File folder of the nupkg into the target main project's bin\\Plugin folder.

For Step 2 description:

The steps pack the content of your MyPlugin project files into the nupkg.

So if your MyPlugin.config is under bin\\Release folder of your MyPlugin project, you should use:

<None Include="bin\Release\netstandard2.0\MyPlugin.config(the path of MyPlugin.dll in your project)" Pack="true" PackagePath="File"></None>

You should make sure that bin\\Release\\netstandard2.0\\MyPlugin.config is right and you can find the file due to its relative path(compare with the path of csproj file).

PackagePath="File" means that it should pack MyPlugin.config file into File folder of the nupkg.

<None Include="Build\MyPlugin.props" Pack="true" PackagePath="build"></None>

This step is to pack MyPlugin.props into build folder of nupkg file. Please see this document ,

Build\\MyPlugin.props means the file physcial path of MyPlugin.props in your MyPlugin project so that nuget will find the file.

The build folder of nupkg (3.x+) MSBuild .targets and .props files  Automatically inserted into the project.

So it is the function of nupkg.

Anyway , this step can be checked by yourself, please check whether the path of the files are correct and then make sure that the target files exist on the File folder of nupkg.

This is my nupkg structure:

在此处输入图片说明

在此处输入图片说明

在此处输入图片说明

=======================================================================

Also , before you install this new version of nuget package, you should clean nuget caches first to remove the old ones in case you still install the old one.

After that, build your main project first to execute the target and then you will see the effect as I show here.

在此处输入图片说明

在此处输入图片说明

Found an almost fully automated solution to my problem (Special thanks to @Perry-Qian-MSFT for guidance in order to get this right).

Here are the steps to achieve this from a newbie's perspective:

Problem 1: How to include the files into '.nupkg'

To include the 'MyPlugin.config' file to the '.nupkg', I've edited the '.csproj' file and added the following:

<ItemGroup>
  <Content Include="MyPlugin.config">
    <Pack>true</Pack>
    <PackagePath>MyPlugin.config</PackagePath>
  </Content>
</ItemGroup>

This step will add the 'MyPlugin.config' file under the ' content ' folder inside the nuget package. Note that the 'MyPlugin.config' file should be placed at the root level of the NuGet project.

Problem 2: How copy the files to the project that consumes the nuget

This is the step where manual editing is needed. Will try to automate this as well and update the answer.

After the nuget is packed (and before pushing it to the NuGet server), open the 'nupkg' package (using winzip/winrar/7zip etc) and add the following to the '.nuspec' file:

<metadata>
  <contentFiles>
    <files include="MyPlugin.config" copyToOutput="true" />
  </contentFiles>
</metadata>
<files>
  <file src="MyPlugin.config" target=""/>
</files>

The 'MyPlugin.dll' does not need to be added here, because it is a lib file.

Save and push the package to the server. Now when the 'consumer' project installs the NuGet, the config file will be added in the project. The config file will NOT be added in the bin directory when building the project yet.

Problem 3: How to copy the files to the consumer's bin folder, under the 'Plugins' sub-directory

For this step a 'props' file was utilized. The props file is meant to be packed in the NuGet package, copied in the consumer's root directory and executed by the consumer project upon build.

Add the 'Directory.build.props' file in the the NuGet's project and edit the 'csproj' to add the following:

  <Content Include="Directory.build.props">
    <Pack>true</Pack>
    <PackagePath>Directory.build.props</PackagePath>
  </Content>

Edit the contents of the "Directory.build.props" file:

<Project>
  <Target Name="CopyToFolder" AfterTargets="Build">
    <ItemGroup>
      <ConfigFile Include="$(MSBuildThisFileDirectory)MyPlugin.config"></ConfigFile>
    </ItemGroup>
    <ItemGroup>
      <DllFile Include="$(MSBuildThisFileDirectory)bin\MyPlugin.dll"></DllFile>
    </ItemGroup>
    <Copy SourceFiles="@(ConfigFile)" DestinationFolder="$(ProjectDir)bin\Plugins"></Copy>
    <Move SourceFiles="@(DllFile)" DestinationFolder="$(ProjectDir)bin\Plugins" Condition="Exists('%(FullPath)')"></Move>
  </Target>
</Project>

Add a "Directory.build.props" entry to the 'nuspec' file. Hence, step 2 will be enhanced to:

  <metadata>
    <contentFiles>
      <files include="MyPlugin.config" copyToOutput="true" />
    </contentFiles>
    <contentFiles>
      <files include="Directory.build.props" copyToOutput="true" />
    </contentFiles>
  </metadata>
  <files>
    <file src="MyPlugin.config" target="Plugins"/>
    <file src="Directory.build.props" target="Plugins"/>
  </files>

Now, the props file will end-up in the root directory of the consumer project. By convention, "Directory.build.props" files are automatically executed when building the project (MSBuild). Using a 'Copy' and a 'Move' task, both the 'dll' and the 'config' are placed under the 'bin/Plugins' folder.

Starting from square 0, i spent a lot of time to achieve this and hopefully it will help others as well :)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM