UWP Class Library NuGet package XamlParseException error - c#

Currently I'm working on an UWP NuGet package for making it easier to create great popups and dialogs.
Currently the project is newborn and doesn't have so much controls but I tried to create a NuGet package for it to be a test for making sure it is all good.
Unless I'm using app with the class library referenced to the sample project all things working well but after downloading the library from NuGet I'm getting XamlParseException error.
I searched a bit and find it out that I should add some xaml, xbf or somethings in the output so I tried to add the following lines to my nuspec.
<files>
<!-- XAML controls -->
<file src="Controls\MessageBoxControls\MessageBoxControl.xaml" target="lib\netcore50\Controls\MessageBoxControls"/>
<file src="bin\Debug\UWPPopupToolkit\Controls\MessageBoxControls\MessageBoxControl.xbf" target="lib\netcore50\Controls\MessageBoxControls"/>
<file src="Controls\PopupControlControls\PopupControl.xaml" target="lib\netcore50\Controls\PopupControlControls"/>
<file src="bin\Debug\UWPPopupToolkit\Controls\PopupControlControls\PopupControl.xbf" target="lib\netcore50\Controls\PopupControlControls"/>
<file src="Controls\SlideupPopupControls\SlideupPopup.xaml" target="lib\netcore50\Controls\SlideupPopupControls"/>
<file src="bin\Debug\UWPPopupToolkit\Controls\SlideupPopupControls\SlideupPopup.xbf" target="lib\netcore50\Controls\SlideupPopupControls"/>
</files>
But still I'm getting same error any idea how to solve it?
I should mention that the project is currently available on Github on the following link
https://github.com/NGame1/UWPPopupToolkit
and the NuGet package also is available here
https://www.nuget.org/packages/UWPPopupToolkit

Simply placing the content files in the lib folder of the nuget package will not automatically copy it into the build output folder, only the dll, pdb and xml files will be added into the output projects automatically.
Since your additional files are not the same type, so you cannot get what you want by your method. So I suggest you could try this:
Solution
1) create a folder called build on your root directory of your project and then add a file called <package_id>.props file.
Note: the file must be named the same as your nuget package so that it will work. For an example, if your nuget project named as UWPPopupToolkit.0.0.1-rc.nupkg, the file must be named as UWPPopupToolkit.props.
2) add these content into the UWPPopupToolkit.props file:
<Project>
<Target Name="OutputExtraFiles" BeforeTargets="Build">
<ItemGroup>
<File Include="$(MSBuildThisFileDirectory)..\File\**\*.*"></File>
</ItemGroup>
<Copy SourceFiles="#(File)" DestinationFiles="$(TargetDir)\%(RecursiveDir)%(Filename)%(Extension)"></Copy>
</Target>
</Project>
3) modify your UWPPopupToolkitSDK.nuspec file like this:
<files>
<!-- XAML controls -->
<file src="Controls\MessageBoxControls\MessageBoxControl.xaml" target="File\Controls\MessageBoxControls"/>
<file src="bin\Debug\UWPPopupToolkit\Controls\MessageBoxControls\MessageBoxControl.xbf" target="File\Controls\MessageBoxControls"/>
<file src="Controls\PopupControlControls\PopupControl.xaml" target="File\Controls\PopupControlControls"/>
<file src="bin\Debug\UWPPopupToolkit\Controls\PopupControlControls\PopupControl.xbf" target="File\Controls\PopupControlControls"/>
<file src="Controls\SlideupPopupControls\SlideupPopup.xaml" target="File\Controls\SlideupPopupControls"/>
<file src="bin\Debug\UWPPopupToolkit\Controls\SlideupPopupControls\SlideupPopup.xbf" target="File\Controls\SlideupPopupControls"/>
<file src="build\UWPPopupToolkit.props" target="build" />
</files>
4) then repack your nuget project, before you install the new version of the nuget package, please clean the nuget caches first and also delete the bin, obj or any output folders of your main project.
=================================
Update 1
In my side, clean all nuget caches or delete all cache files under C:\Users\xxx(current user)\.nuget\packages and then install the new version of the nuget package, the target files are output to bin\x86\Debug\Controls,
If I install the new version 0.0.1.5-rc,everything works well. See this:
Not sure if your problem is that the files are missing or you want to put them into bin\x86\Debug\netcore50\Controls.
If your issue is the second, you should modify your UWPPopupToolkit.props,
use this:
<Copy SourceFiles="#(File)" DestinationFiles="$(TargetDir)netcore50\%(RecursiveDir)%(Filename)%(Extension)"></Copy>
After that, delete bin and obj folder and then rebuild your main project again.

Thanks to #Perry Qian-MSFT
Finally, I got able to fix the issue.
adding files like this
<files>
<!-- Dll -->
<file src="bin\Release\UWPPopupToolkit.dll" target="lib\netcore50" />
<!-- Resources -->
<file src="bin\Release\UWPPopupToolkit.pdb" target="lib\netcore50" />
<file src="bin\Release\UWPPopupToolkit.pri" target="lib\netcore50" />
<!-- IntelliSense -->
<file src="bin\Release\UWPPopupToolkit.XML" target="lib\netcore50" />
<!-- XAML control -->
<file src="bin\Release\UWPPopupToolkit\**\*.*" target="lib\netcore50\UWPPopupToolkit" />
<!-- Icon -->
<!--<file src="..\icon.png" target="images\" />-->
</files>
solved the problem.
You can find the result files here: UWPPopupToolkitSDK.nuspec | UWPPopupToolkit.props | UWP Popup Toolkit Github

Related

Nuget package to copy exe content file to project output directory

I'm attempting to create a Nuget package that will copy an executable file to the output directory of a .Net framework library.
Here is my nuspec file:
<?xml version="1.0"?>
<package xmlns="http://schemas.microsoft.com/packaging/2013/05/nuspec.xsd">
<metadata>
<id>CopyExeToOutputNugetPackage</id>
<version>1.0.0</version>
<authors>Some Dude</authors>
<owners>Some Owner</owners>
<requireLicenseAcceptance>false</requireLicenseAcceptance>
<description>A package to copy an exe to the output directory.</description>
<tags>CopyExeToOuput</tags>
<contentFiles>
<files include=".\content\test.exe" buildAction="None" copyToOutput="true" />
</contentFiles>
</metadata>
</package>
The "nuget pack" command works fine and builds my .nupkg file. I can then add the nuget project to my .Net Framework project and the test.exe file is added to my project:
<ItemGroup>
<Content Include="test.exe" />
</ItemGroup>
I can then use Visual Studio to edit the file properties to copy to the output directory and my project file is updated:
<ItemGroup>
<Content Include="test.exe">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
</ItemGroup>
I would prefer that this last manual step is no required.
I've attempted to use a .targets file but that's either the wrong path or I never got the configuration correct.
I've also tried using the nuspec files element (instead of ):
<files>
<file src="test.exe" target="lib\net462" />
</files>
With this last configuration, I get the following exception when attempting to add the nuget package to my .Net Framework v4.6.2 project:
Failed to add reference to 'test'. Please make sure that the file is accessible, and that it is a valid assembly or COM component.
I got a working answer that uses a PowerShell script and PowerShell Tools for Visual Studio on a Microsoft forum:
https://social.msdn.microsoft.com/Forums/en-US/cb6236e8-4705-485b-a47c-cc4dc933c92c/nuget-package-to-copy-exe-content-file-to-project-output-directory?forum=visualstudiogeneral

dotnet pack command along with nuspec file not including project's DLL

I have a .NET Standard 2.0 project called ProjectName.Logging with a ProjectName.Logging.nuspec file.
This file file is referenced in the .csproj of my project
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<RestoreProjectStyle>PackageReference</RestoreProjectStyle>
<NuspecFile>ProjectName.Logging.nuspec</NuspecFile>
</PropertyGroup>
Here is my .nuspec
<?xml version="1.0"?>
<package >
<metadata>
<id>ProjectName.Logging</id>
<version>1.2.1</version>
<authors>Jérôme MEVEL</authors>
<description>Just a logging component</description>
<dependencies>
<dependency id="Dapper" version="1.50.5" />
<dependency id="Another.Project" version="1.1.1" />
<dependency id="Microsoft.Extensions.DependencyInjection" version="2.1.1" />
<dependency id="Microsoft.Extensions.Logging" version="2.1.1" />
<dependency id="Microsoft.Extensions.Logging.Abstractions" version="2.1.1" />
<dependency id="NLog" version="4.5.8" />
<dependency id="NLog.Extensions.Logging" version="1.2.1" />
<dependency id="NLog.Web.AspNetCore" version="4.6.0" />
<dependency id="System.Data.SqlClient" version="4.5.1" />
</dependencies>
</metadata>
<files>
<file src="bin\Release\netstandard2.0\ProjectName.Logging.dll" target="lib/netstandard2.0/ESHCloud.Logging.dll" />
<file src="ProjectName.Logging.targets" target="build/ProjectName.Logging.targets" />
<file src="NLog/Nlog.config" target="content/Nlog.config" />
</files>
</package>
As you can see I manually include the ProjectName.Logging.dll file and I even have to include Release because the usage of the MsBuild variable $(Configuration) doesn't work in my .nuspec file.
I pack the project by executing this command in my project's directory
dotnet pack --output C:/Nuget --force
and if I remove the <files> element from my .nuspec when I run the dotnet pack command, my generated Nuget package is completely empty.
On the other hand if I run the dotnet pack command without a .nuspec file, absolutely everything in my project is included in the Nuget package.
So what's the deal with the dotnet pack command? I don't understand what am I doing wrong.
How to include my project's DLL in the Nuget package without having to specify the configuration (Debug or Release)?
One last thing: I don't want to use the nuget pack command.
I played enough with Nuget on our VSTS servers (recently renamed Azure DevOps) and I don't have full control over these build servers (my manager has but he seems too busy to care about it).
So to sum up, nuget pack is not an option for me. I want to use dotnet pack along with a .nuspec file.
Thank you
To add your DLL without specifying the configuration use a glob pattern:
<file src="runtimes\**" target="runtimes/"/>
If you use nuget.exe you could use a replacement token:
<file src="bin\$configuration$\netstandard2.0\*.dll" target="lib\netstandard2.0\"/>
If you really need to use the nuspec file you're better off using nuget.exe. If you don't want to use nuget.exe drop the nuspec. I've done a fair amount of work with dotnet and nupkgs the last few weeks and mixing nuspec with project files is fiddly.
You can put the majority of the nupkg meta-data directly in the csproj:
<PropertyGroup>
<PackageId>Subor.nng.NETCore</PackageId>
<PackageVersion>0.0.2</PackageVersion>
<Authors>Subor</Authors>
...
</PropertyGroup>
This is the recommended approach when using the dotnet CLI. Likewise for msbuild with the PackageReference format.
Here's an example of a project I've been working on. dotnet pack builds a package bin/Debug/ and dotnet pack --configuration Release builds this nuget.org package.
Everything in the project should not get copied into the nupkg. In Visual Studio check the Properties of the files and make sure everything isn't flagged as "Content", etc.. Also check the project files to see if files are getting added that shouldn't be. Look for (miss-)use of <PackagePath> and <IsPackable>.
Without knowing the particulars of your project, I'll mention trying some of the arguments to dotnet pack.

Nuget: Including an exe as a Run-time dependency

I have an .exe app that I need to distribute with my C# app when it builds. I am trying to use Nuget to package it so that it will be included in the build root directory when building but am having trouble getting the behaviour I want.
Here is what I've got in my .nuspec file:
<?xml version="1.0"?>
<package>
<metadata>
<id>my.id</id>
<version>1.0.0</version>
<authors>me</authors>
<owners>me</owners>
<licenseUrl>myurl</licenseUrl>
<projectUrl>myurl</projectUrl>
<requireLicenseAcceptance>false</requireLicenseAcceptance>
<description>A copy of an .exe so we can easily distribute it
with our applications without needing to include it in our VCS repo</description>
<releaseNotes>Initial test version</releaseNotes>
<copyright>Copyright 2018</copyright>
<dependencies>
</dependencies>
<packageTypes>
</packageTypes>
<contentFiles>
<files include="any\any\myexe.exe" buildAction="None" copyToOutput="true" />
</contentFiles>
</metadata>
<files>
<file src="content\myexe.exe" target="content" />
</files>
</package>
This puts the myexe.exe file to my VS project when I install the Nuget Package but it does not copy the file when I build. What I'd like is for the file to by installed with my other app files when building and to keep it out of my VS project.
I've been reading docs here but am not sure how to make the nuspec file.
More Details:
Nuget 4.5.1
Visual Studio 2015
Note: the <files> and <contentFiles> might seem to be duplicating functionality. I'd like to employ both as I understand this will future-proof it for VS2017
Nuget: Including an exe as a Run-time dependency
First, I know you want to use some technologies for the future, but we have to know that these future-oriented technologies often have certain constraints and conditions.
For example, <contentFiles> is used for NuGet 4.0+ with PackageReference, neither of them is supported by Visual Studio 2015. See Using the contentFiles element for content files for some details.
If you are interested in the <contentFiles>, you can read the blog NuGet is now fully integrated into MSBuild.
Go back to our question now, according to above info, we should not use <contentFiles> when we use Visual Studio 2015. To resole this issue, we need to add a .targets file in the nuget package when you build the project:
The content of .targets file:
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<None Include="$(ProjectDir)myexe.exe">
<Link>myexe.exe</Link>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
<CustomToolNamespace></CustomToolNamespace>
</None>
</ItemGroup>
</Project>
The .nuspec file like following:
<files>
<file src="build\YouNuGetPackageName.targets" target="build\YouNuGetPackageName.targets" />
<file src="content\myexe.exe" target="content\myexe.exe" />
</files>
Note: The name of the .targets file should be same as your nuget package name.
With this way, when you build your project, MSBuild/VS would copy the file myexe.exe to the output folder.
Besides, if you want to copy the file myexe.exe to other destination, you can replace the content of .targets file with a copy task, like:
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Target Name="CopyMyexe" BeforeTargets="Build">
<Message Text="Copy CopyMyexe to the folder."></Message>
<Copy
SourceFiles="$(ProjectDir)myexe.exe"
DestinationFolder="xxx\xxx\xx\myexe.exe"
/>
</Target>
</Project>
See Creating native packages and similar issue for some helps.
Hope this helps.

unwanted culture specific dlls copied to bin directory

I am using visual studio 2013 & Fluent Validation 5.6.2
I see that after build in the bin folder it copies all the culture specific FluentValidation.resources.dll which seems to be mentioned it in .nuspec file
> <file src="lib\NET35\de\FluentValidation.resources.dll"
> target="lib\NET35\de\FluentValidation.resources.dll" />
> <file src="lib\NET35\es\FluentValidation.resources.dll" target="lib\NET35\es\FluentValidation.resources.dll" />
> <file src="lib\NET35\fr\FluentValidation.resources.dll" target="lib\NET35\fr\FluentValidation.resources.dll" />
> <file src="lib\NET35\it\FluentValidation.resources.dll" target="lib\NET35\it\FluentValidation.resources.dll" />
> <file src="lib\NET35\nl\FluentValidation.resources.dll" target="lib\NET35\nl\FluentValidation.resources.dll" />
> <file src="lib\NET35\pt\FluentValidation.resources.dll" target="lib\NET35\pt\FluentValidation.resources.dll" />
> <file src="lib\NET35\sv\FluentValidation.resources.dll" target="lib\NET35\sv\FluentValidation.resources.dll" />
But I do not need these in bin folder, because project does not support any culture specific messages.
So how can I tell vs-build to ignore these culture specific dlls?
My solution was to add this target at the end of the .csproj file before the closing project tag.
<Target Name="AfterPackage" AfterTargets="CopyAllFilesToSingleFolderForPackage" />
<ItemGroup>
<FluentValidationExcludedCultures Include="cs;da;de;es;fa;fi;fr;it;ko;mk;nl;pl;pt;ru;sv;tr;zh-CN">
<InProject>false</InProject>
</FluentValidationExcludedCultures>
</ItemGroup>
<Target Name="RemoveTranslationsAfterBuild" AfterTargets="AfterBuild">
<RemoveDir Directories="#(FluentValidationExcludedCultures->'$(OutputPath)%(Filename)')" />
</Target>
<Target Name="RemoveTranslationsAfterPackage" AfterTargets="AfterPackage">
<RemoveDir Directories="#(FluentValidationExcludedCultures->'$(_PackageTempDir)\$(OutputPath)%(Filename)')" />
</Target>
It's not pretty, but it gets the job done. If you need some culture specific resource, just remove the corresponding line from the list. If a future update adds a new culture that you don't want, add it to the list.
The best option would be ask the developer to separate the resources in multiple nugets, this way you could just add the ones needed. I'll stick with this solution, for now, until someone come up with a better one.
Now you can find my solution at the official project wiki: https://github.com/JeremySkinner/FluentValidation/wiki/f.-Localization (at the bottom of the page)
i had same problem with external library, i'm add post-build script in Visual Studio project properties, which delete all folders (for me it`s okay, otherwise set list of dirs) at output directory:
FOR /D %%d IN ($(TargetDir)*) DO RMDIR /S /Q %%d

Trying to add non-.NET libraries to NuGet package

I have a .NET DLL that is using non-.NET DLLs. I'm trying to create a NuGet package out of this, but I don't seem to be penetrating the magic behind this. I read the NuGet reference about the <files> and <references> but that didn't really work out for me - VS kept on refusing to install the package on the grounds that "...Failed to add reference to NonNETLib1". I tried a different variant where non-.NET libs were bundled together with the .NET library in net40 folder and the nusepc file having no <files> section, but in this case even though the package installed OK, the code threw an exception in runtime, because it could not find the DLLs.
Here's the .nuspec I have:
<?xml version="1.0"?>
<package >
<metadata>
<id>PackageName</id>
<version>1.0.3</version>
<authors>me</authors>
<owners>some guys</owners>
<requireLicenseAcceptance>false</requireLicenseAcceptance>
<description>description</description>
<references>
<reference file="NonNETLib1.dll" />
<reference file="NonNETLib2.dll" />
<reference file="NonNETLib3.dll" />
</references>
</metadata>
<files>
<file src="lib\NonNETLib1.dll" />
<file src="lib\NonNETLib2.dll" />
<file src="lib\NonNETLib3.dll" />
</files>
</package>
The folder structure is as follows:
[lib]
\- NonNETLib1.dll
\- NonNETLib2.dll
\- NonNETLib3.dll
\- [net40]
\- Net40Lib.dll
What am I missing here?
P.S. I know this is somewhat similar to this question, but the accepted answer to it didn't help much.
even though the package installed OK, the code threw an exception in runtime, because it could not find the DLLs
When you add a reference to a .Net DLL in your project, it's automatically copied to the output folder. But since your DLL is not .Net, you can't add a reference to it directly in the project, so it's not copied at all.
I would add a pre-build or post-build step in your project, like xcopy /y /f "$(ProjectDir)..\packages\NonNet.dll" "$(TargetDir)" but I suspect there is a better and cleaner way to do it.
In any case, it's not a nuget-related problem, but a more general Visual Studio project problem.
Update
It seems the consensus is to add the native DLL as an existing item (as a link) to the project, set it to content/copy if newer: Are there any better ways to copy a native dll to the bin folder?
There is a powershell-based toolset for packaging native code for NuGet consumption. It primarily deals with issues around integrating into native projects but it should provide the tooling you need to plug native dlls into .NET projects as well.
http://coapp.org/news/2013-04-26-Announcing-CoApp-Tools-For-NuGet.html
I had exactly the same problem and i found a good solution for me with nuget 3.3. This way only the .net-lib will be referenced to the project and the non-.Net lib is only copied to bin folder.
<references>
<reference file="Net.dll">
<references>
<files>
<file src="..\bin\NonNet.dll" target="lib/452">
<file src="..\bin\Net.dll" target="lib/452">
<files>

Categories