Do 'init.ps1' scripts still works when installing a NuGet package? - visual-studio

This question might be a little outdated, but does 'init.ps1' scripts still works when installing a nupkg?
I was trying to use 'install.ps1' and 'uninstall.ps1', but after a little bit of research I've seen that those files stopped working with Visual Studio 2017 (which is the version of Visual I'm currently using), but I have not found any recent information about 'init.ps1' (being the most recent from 2017 or 2018).
My script is working correctly when executed by itself but seems like it's not getting called on the package install.
In the case that 'init.ps1' still works here's my '.nuspec' file, am I doing something wrong?:
<?xml version="1.0" encoding="utf-8"?>
<package xmlns="http://schemas.microsoft.com/packaging/2013/05/nuspec.xsd">
<metadata>
<id>NugetTry</id>
<version>0.0.142</version>
<title>NugetTry</title>
<authors>rwpk9</authors>
<description>Description</description>
<copyright>Copyright © 2023</copyright>
<dependencies>
<group targetFramework=".NETFramework4.7.2">
<dependency id="EntityFramework" version="6.4.4" />
<dependency id="Microsoft.AspNet.Mvc.es" version="5.2.9" />
<dependency id="Newtonsoft.Json" version="13.0.2" />
</group>
</dependencies>
</metadata>
<files xmlns="">
<file src="init.ps1" target="." />
</files>
<powershell xmlns="">
<scripts>
<base><![CDATA[init.ps1]]></base>
</scripts>
</powershell>
</package>
My 'init.ps1' is at the same path as the '.nuspec'.

The init.ps1 file needs to be in a tools/ directory, not the package root. So, the zip file's central directory record has a path of tools/init.ps1

I think this no longer works.
I already put the init.ps1 to the tools directory and then configured the .nuspec, after that, package the package.
But if I install the package at the first time in the solution, I didn't see my powershell script run.
From the Nuget Product Team member:
https://github.com/NuGet/Home/issues/4318#issuecomment-343255043
powershel script is deprecated for package reference, we don't
recommend people to use script in their packages.
I think this is deprecated.

Related

Creating multitarget nuget package with .nuspec

I have specified multitargeting in my .csproj
<TargetFrameworks>netstandard2.0;net472</TargetFrameworks>
When I am using below script, then my package has dependencies and it is expected result:
dotnet pack --output nupkgs $ProjectPath -c:Release
The problem is when I also want to use .nuspec file with some information about package:
dotnet pack --output nupkgs $ProjectPath -c:Release -p:NuspecFile=$NuspecFile
With .nuspec file the package has no dependencies and I can install it only in netstandard2.0...
<?xml version="1.0"?>
<package xmlns="http://schemas.microsoft.com/packaging/2013/05/nuspec.xsd">
<metadata>
<id>xyz</id>
<version>1.2011.4</version>
<title>xyz</title>
<authors>xyz</authors>
<projectUrl>xyz</projectUrl>
<requireLicenseAcceptance>false</requireLicenseAcceptance>
<description>xyz</description>
<copyright>xyz</copyright>
</metadata>
</package>
Should I add something to this .nuspec to have a package with target dependencies? I have read about tag, but to be honest I cannot find example how to configure it.
Given that you are using an SDK based projects, I'd strongly discourage using a nuspec unless your scenario cannot be satisfied because of it's complexity.
The automatic package generation with project file through dotnet.exe pack does much of the compatibility work for you.
If you really need to go with a nuspec, you should add dependency groups like defined here:
https://learn.microsoft.com/en-us/nuget/reference/nuspec#dependency-groups.
Make sure you add the relevant framework.
Example
<group targetFramework=".NETFramework4.7.2">
<dependency id="PackageA" version="1.2.3" />
</group>
<group targetFramework=".NETStandard2.0">
<dependency id="PackageB" version="4.5.6" />
</group>
Note that you need to add a dependency group for the specific frameworks you support.

Prevent content files to be added on Nuget restore

We have some executables which we need to create our setups. So we have packed
the external dependencies which are some .exe files into a nuget package. But on NuGet restore they are added to project root.
How can we achieve this ?
Have searched around but haven't found any solution so far.
Since we use nuspec file, this is what i have it as:
<?xml version="1.0" encoding="utf-8"?>
<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
<metadata>
<id>VCRedistributable</id>
<version>$version$</version>
<title>VCRedistributable</title>
<authors>--</authors>
<owners>--</owners>
<requireLicenseAcceptance>false</requireLicenseAcceptance>
<description>InstallVCRedistributable assemblies</description>
<contentFiles>
<files include="**" exclude="**" buildAction="None" copyToOutput="false"
/>
</contentFiles>
</metadata>
<files>
<file src="VC\x86\*.*" target="content\x86" />
<file src="VC\x64\*.*" target="content\x64" />
</files>
Any ideas ?
Prevent content files to be added on Nuget restore
You should target to the tools folder instead of content folder.
So, your .nupsec file should be:
<?xml version="1.0" encoding="utf-8"?>
<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
<metadata>
<id>VCRedistributable</id>
<version>$version$</version>
<title>VCRedistributable</title>
<authors>--</authors>
<owners>--</owners>
<requireLicenseAcceptance>false</requireLicenseAcceptance>
<description>InstallVCRedistributable assemblies</description>
</metadata>
<files>
<file src="VC\x86\*.*" target="tools\x86" />
<file src="VC\x64\*.*" target="tools\x64" />
</files>
</package>
That because the content directory is a convention-based working directory, which contents are copied to the project root:
Convention-based working directory:
Besides, if you nuget package just include external some .exe files, you do not have to add the contentFiles label, this label is used for the content file for packagereference.
<contentFiles>
<files include="**" exclude="**" buildAction="None" copyToOutput="false"
/>
</contentFiles>
If you are interested in, you can check this document for some more details.
Update:
Is it good convention to create our own folder structure other than
NuGet defined since based on the tools folder description from above
it seems they will be accessible via Package Manager Console.
Of course, you can use your own folder structure other than NuGet defined. But you need to notice that there will be a limit to do this. You can NOT just include your own folder structure, you need also need add a NuGet defined folder structure in your .nuspec, otherwise, nuget will install failed with the error like:
Could not install package 'MyCustomPackage 1.0.0'. You are trying to
install this package into a project that targets
'.NETFramework,Version=v4.6.1', but the package does not contain any
assembly references or content files that are compatible with that
framework.
Because nuget did not detect that you added assembly references or content files to the project.
Hope this helps.

Manage Nuget Packages Outside Visual Studio

My organization wants to segregate all the development machines on a network without internet access.
I found this article that gives that gives some nuget host product, so that the packages are available offline.
My problem is that I can't find a way to manage the package update, because the machines that have and internet access won't have Visual studio installed.
I was looking if there is a tool that reads a folder where all nupkg files are stored and check if a newer version is available and downloads it, or otherwise reads a manually created packages.config file checks for newer version and download them on a folder.
Does anyone have an idea how to manage nuget packages in this way? I spent the last week trying to find a way but I had no look.
Does anyone have an idea how to manage nuget packages in this way?
According to the NuGet CLI reference:
The update command also updates assembly references in the project
file, provided those references already exist.
So when we use NuGet.exe update the package, we are not only need the packages.config but also need the solution/project, otherwise, you will get the error:
"Unable to locate project file for 'D:\NuGetServer\packages.config'
You can copy a simple project from the machine, which have Visual Studio installed, then use below command line to update the nuget package in the package.config file:
nuget update "YourProjectPath\packages.config"
But NuGet will update the packages into the packages folder under the solution folder by default, so we need change the packages folder to the folder where all nupkg files are stored before update packages.
Detail steps:
Download the nuget.exe from nuget.org, set it to your local machines.
Create a NuGet folder under the path %appdata%, add the NuGet.Config file and change the packages folder by repositoryPath, just set it "D:\NuGetServer":
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<packageSources>
<add key="nuget.org" value="https://api.nuget.org/v3/index.json" protocolVersion="3" />
</packageSources>
<config>
<add key="repositoryPath" value="D:\NuGetServer" />
</config>
</configuration>
Copy a solution from other machine, add the packages in to the package.config file:
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="EntityFramework" version="6.1.0" targetFramework="net45" />
<package id="Newtonsoft.Json" version="8.0.3" targetFramework="net45" />
<package id="NUnit" version="3.7.0" targetFramework="net45" />
</packages>
Open a CMD file, switch to the path where NuGet is stored in step 1, then use the update command:
You will find packages in the packages.config are updated to the latest version.

nuspec contentFiles not added to a project

I have a web project (mvc5) with a project.json inside.
Also, I have a nuget package. Inside this package (besides the dll reference) I have some Content files (cshtml files, css, javascript etc).
There are 2 goals to achieve:
After installing the package to the project I want to get Content Files included to the project.
After Building the project I want nuget to restore the content files
The nuspec file:
<?xml version="1.0"?>
<package>
<metadata>
/.../
<dependencies>
<group targetFramework="net461">
/.../
</group>
</dependencies>
<contentFiles>
<files include="**/*.*" flatten="false" copyToOutput="false" buildAction="Content" />
</contentFiles>
</metadata>
<files>
/.../
<file src="..\src\Content\**\*.*" target="contentFiles\any\any\Content" />
<file src="..\src\Views\**\*.*" target="contentFiles\any\any\Views" />
</files>
</package>
Well, Visual Studio is adding nuget package with no issues. The reference is also included. But the content is always missing. The content files are not copied from the /packages/ folder and are not included to the project.
The same is when I build the project - it just copies the dll and does not touch content files from the package at all.
It only works if I have copyToOutput="true", but all content goes to bin folder, of course.
The reason why I need to restore the content files is that the files from the nuget package are ignored by a tfs 'ignore file' (.tfignore). I don't want to have these content files to be a part of the web project in TFS. However, of course, TFS build server fails to build the project, because some content files are missing (the files from the package). So I want nuget on the build server to restore the content files before it stats building the project.
Any idea how to get this work if it is possible? Or maybe this is not possible and I must have content files to be included to the project?
you could add a msbuild target to your package. in this target you can execute the nuget restore command...
example:
<?xml version="1.0"?>
<package >
<metadata>
<!-- ... -->
</metadata>
<files>
<!-- Include your MSBuild target to \build -->
<file src="build\myNuGetRestoreTarget.targets" target="build" />
</files>
</package>
see:
https://learn.microsoft.com/en-us/nuget/create-packages/creating-a-package#including-msbuild-props-and-targets-in-a-package
This is by design. NuGet packages are no longer supposed to modify the project's source but only add to its built output or build process (in addition to .NET libraries). The content folder for adding sources to the project is only continued to be supported for packages.config based projects since it would be a breaking change for existing projects, but projects using project.json or PackageReference (VS 2017) get the new behaviour.
I was in the situation. Here's how I handled it.
Don't keep your files as content, content files are added to project files. Rename the target to something else. I kept it as drop. Your nuspec file should be like:
<package xmlns="http://schemas.microsoft.com/packaging/2013/05/nuspec.xsd">
<metadata>
<id>ID</id>
<version>1.0</version>
<title>Title</title>
<authors>J</authors>
<owners>J</owners>
<requireLicenseAcceptance>false</requireLicenseAcceptance>
<description>Binary Files such as images, fonts, icons and svgs</description>
<copyright>J</copyright>
</metadata>
<files>
<file src="..\..\Internal.Resources.targets" target="build" />
<file src="..\..\**\*.*" target="drop" exclude="**\*.targets"/>
</files>
</package>
Keep a target file as one of your drop file. Like following:
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<RequiredFiles Include="$(MSBuildThisFileDirectory)..\drop\**\*.*" />
<None Include="#(RequiredFiles)">
<Link>%(RecursiveDir)%(FileName)%(Extension)</Link>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
</ItemGroup>
</Project>
Now your nuget install will just extract the content in packages folder, add target to your project. When you build, the targets will fetch files from package directory and put in build directory.

Use a .nuspec file/script to automatically install nuget packages into a new project

I am trying to automate the process of installing nuget packages into new visual studio projects. My idea is to reduce the time it takes to source all the packages via the nuget package manager, by specifying the packages in a custom file that can be run to install these packages. Therefore only requiring every new project to include this file and running it each time. I'm very new to nuget and have been assigned this task without much prior knowledge. I was advised that .nuspec route would lead me in the right direction, since it contains the meta data about a package. Although since consumers don't have direct access to the .nuspec file of a package, I am failing to understand how it can be used as part of this automation. I have also heard about automatic package restore, but since that only works for lost reference, I don't see how it will help in new projects that haven't necessarily referenced anything to do with that project.
note that you cannot simply drop a pre-built packages.config file into a new project and expect it to work. When installing, NuGet modifies the project file (.csproj) to include references and uses packages.config for downloading missing files (and update/conflict logic).
Using VS 2017 (released stable versions 15.2 and higher) and the PackageReference style of referencing projects, you can simply drop a Directory.Build.props file into the root of your solution containing all the projects you need:
<Project>
<ItemGroup>
<PackageReference Include="Autofac" Version="3.5.2 />
<PackageReference Include="Topshelf" Version="3.2.0 />
</ItemGroup>
</Project>
This will add these NuGet packages to all new projects in the solution without the need for the .csproj files to be modified. (note that after adding/editing this file, you need to close and re-open the solution. this should be fixed in the upcoming VS 2017 15.3 update for editing the file).
Nuget already supports automation of installation and we can use nuget commandline to achieve this
Everytime you add a nuget package in Visual Studio,it gets add to a file called packages.config file.
E.g. will look like this
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Autofac" version="3.5.2" targetFramework="net451" />
<package id="Microsoft.Owin" version="3.1.0" targetFramework="net452" />
<package id="Microsoft.Owin.Host.HttpListener" version="3.0.1" targetFramework="net451" />
<package id="Microsoft.Owin.Hosting" version="3.1.0" targetFramework="net452" />
<package id="Newtonsoft.Json" version="9.0.1" targetFramework="net451" />
<package id="Owin" version="1.0" targetFramework="net451" />
<package id="Topshelf" version="3.2.0" targetFramework="net451" />
</packages>
Every project you have in your solution will have packages.config file. You can go to the parent folder of all the projects and simply run comand 'nuget restore', it will get all the packages for you.
For this to work, nuget.exe needs to be downloaded separately .More details on the nuget command line can be found here and here's the commandline reference
Edit:
Thanks #Martin Ullrich pointing out.Just to be clear, The above method will not add the references to project file automatically,it will only get the packages to the packages folder.In VS2017,the support is there which #Martin's answer addresses.
Hope this helps!

Resources