Nuspec for NuGet package with UWP project - c#

I wont to package one of my DLL in a NuGet package.
This DLL uses Xamarin Forms and will target Android, iOS and UWP (Universal Windows) projects
Here is the section of nuspec file:
<files>
<!--Core-->
<file src="Polux\CBS_CBT.Polux\bin\Release\CBS_CBT.Polux.dll" target="lib\portable-net45+wp8+wpa81+win8+MonoAndroid10+MonoTouch10+Xamarin.iOS10+UAP10\CBS_CBT.Polux.dll" />
<file src="Polux\CBS_CBT.Polux\bin\Release\CBS_CBT.Polux.pdb" target="lib\portable-net45+wp8+wpa81+win8+MonoAndroid10+MonoTouch10+Xamarin.iOS10+UAP10\CBS_CBT.Polux.pdb" />
<file src="Polux\CBS_CBT.Polux\bin\Release\CBS_CBT.Polux.xml" target="lib\portable-net45+wp8+wpa81+win8+MonoAndroid10+MonoTouch10+Xamarin.iOS10+UAP10\CBS_CBT.Polux.xml" />
<!--Xamarin.Android-->
<file src="Polux\CBS_CBT.Polux.Droid\bin\Release\CBS_CBT.Polux.dll" target="lib\MonoAndroid10\CBS_CBT.Polux.dll" />
<file src="Polux\CBS_CBT.Polux.Droid\bin\Release\CBS_CBT.Polux.pdb" target="lib\MonoAndroid10\CBS_CBT.Polux.pdb" />
<file src="Polux\CBS_CBT.Polux.Droid\bin\Release\CBS_CBT.Polux.xml" target="lib\MonoAndroid10\CBS_CBT.Polux.xml" />
<file src="Polux\CBS_CBT.Polux.Droid\bin\Release\CBS_CBT.Polux.Droid.dll" target="lib\MonoAndroid10\CBS_CBT.Polux.Droid.dll" />
<file src="Polux\CBS_CBT.Polux.Droid\bin\Release\CBS_CBT.Polux.Droid.pdb" target="lib\MonoAndroid10\CBS_CBT.Polux.Droid.pdb" />
<file src="Polux\CBS_CBT.Polux.Droid\bin\Release\CBS_CBT.Polux.Droid.xml" target="lib\MonoAndroid10\CBS_CBT.Polux.Droid.xml" />
<!--Xamarin.iOS-->
<file src="Polux\CBS_CBT.Polux.iOS\bin\iPhone\Release\CBS_CBT.Polux.dll" target="lib\Xamarin.iOS10\CBS_CBT.Polux.dll" />
<file src="Polux\CBS_CBT.Polux.iOS\bin\iPhone\Release\CBS_CBT.Polux.pdb" target="lib\Xamarin.iOS10\CBS_CBT.Polux.pdb" />
<file src="Polux\CBS_CBT.Polux.iOS\bin\iPhone\Release\CBS_CBT.Polux.xml" target="lib\Xamarin.iOS10\CBS_CBT.Polux.xml" />
<file src="Polux\CBS_CBT.Polux.iOS\bin\iPhone\Release\CBS_CBT.Polux.iOS.dll" target="lib\Xamarin.iOS10\CBS_CBT.Polux.iOS.dll" />
<file src="Polux\CBS_CBT.Polux.iOS\bin\iPhone\Release\CBS_CBT.Polux.iOS.xml" target="lib\Xamarin.iOS10\CBS_CBT.Polux.iOS.xml" />
<!--uap-->
<file src="Polux\CBS_CBT.Polux.UWP\bin\Release\CBS_CBT.Polux.dll" target="lib\UAP10\CBS_CBT.Polux.dll" />
<file src="Polux\CBS_CBT.Polux.UWP\bin\Release\CBS_CBT.Polux.pdb" target="lib\UAP10\CBS_CBT.Polux.pri" />
<file src="Polux\CBS_CBT.Polux.UWP\bin\Release\CBS_CBT.Polux.xml" target="lib\UAP10\CBS_CBT.Polux.xml" />
<file src="Polux\CBS_CBT.Polux.UWP\bin\Release\CBS_CBT.Polux.UWP.dll" target="lib\UAP10\CBS_CBT.Polux.UWP.dll" />
<file src="Polux\CBS_CBT.Polux.UWP\bin\Release\CBS_CBT.Polux.UWP.pdb" target="lib\UAP10\CBS_CBT.Polux.UWP.pdb" />
<file src="Polux\CBS_CBT.Polux.UWP\bin\Release\CBS_CBT.Polux.UWP.pri" target="lib\UAP10\CBS_CBT.Polux.UWP.pri" />
<file src="Polux\CBS_CBT.Polux.UWP\bin\Release\CBS_CBT.Polux.UWP.xml" target="lib\UAP10\CBS_CBT.Polux.UWP.xml" />
The problem:
When I run the application, only the CBS_CBT.Polux.UWP.dll is copied in the \Debug directory, none of the other files (mainly CBS_CBT.Polx.dll) are copied in the output (\Debug for example) directory. The software then throw:
An exception of type 'System.IO.FileNotFoundException' occurred in
mscorlib.ni.dll but was not handled in user code
Additional information: Could not load file or assembly
'CBS_CBT.Polux, Version=0.3.0.0, Culture=neutral, PublicKeyToken=null'
or one of its dependencies.
When I manually add only "CBS_CBT.Polux.dll" and "CBS_CBT.Polux.UWP.dll" to the references of the UWP project, the software can run without any issue.

Thank you Unni Ravindranathan, after reading the doc, I could correct my code.
The only section I had to change was the "Core" one.
Here is the woring nuspec code:
<!--Core-->
<file src="Polux\CBS_CBT.Polux\bin\Release\CBS_CBT.Polux.dll" target="lib\portable-net45+win8+wpa81+MonoAndroid10+MonoTouch10+Xamarin.iOS10+UAP10\CBS_CBT.Polux.dll" />
<file src="Polux\CBS_CBT.Polux\bin\Release\CBS_CBT.Polux.pdb" target="lib\portable-net45+win8+wpa81+MonoAndroid10+MonoTouch10+Xamarin.iOS10+UAP10\CBS_CBT.Polux.pdb" />
<file src="Polux\CBS_CBT.Polux\bin\Release\CBS_CBT.Polux.xml" target="lib\portable-net45+win8+wpa81+MonoAndroid10+MonoTouch10+Xamarin.iOS10+UAP10\CBS_CBT.Polux.xml" />

Related

Create Nuget for net461 with content copy to output

I've created a nuget package targeting a .NET Core project.
The idea here is to add xxx.dll as a reference with copy local as false
and copy all DLLs in a subfolder in the output path and all resources files in subfolder\resources
The nuspec targeting NET Core 3 is working fine.
Now I want to do the same to target NET Framework 4.6.1.
But the content files are not added to the project.
This is my nuspec file :
<?xml version="1.0"?>
<package xmlns="http://schemas.microsoft.com/packaging/2013/05/nuspec.xsd">
<metadata>
<id>xxx.Win.x64.ForIPS11</id>
<version>15.5.3.4</version>
<title>xxx toolkit</title>
<authors>xxx Team</authors>
<owners>xxx</owners>
<requireLicenseAcceptance>false</requireLicenseAcceptance>
<description>xxx 15.5.3.4 x64 Windows to .NETFramework 4.6.1 for IPS 11</description>
<releaseNotes></releaseNotes>
<copyright>2020</copyright>
<tags></tags>
<dependencies>
<group targetFramework=".NETFramework4.6.1" />
</dependencies>
<contentFiles>
<files include="**\subfolder\resources\*.*" buildAction="Content" copyToOutput="true" />
<files include="**\subfolder\*.dll" buildAction="Content" copyToOutput="true" />
</contentFiles>
</metadata>
<files>
<file src="bin\xxx.dll" target="lib\net461" />
<file src="resources\*.*" target="contentFiles\any\any\subfolder\resources" />
<file src="bin\*.dll" target="contentFiles\any\any\subfolder" />
</files>
</package>
Did I use an incompatible tag for .NET Framework target?
Any idea how to get this done?
EDIT : I use packages.config file in VS2017 in the target project
contentFiles is not compatible with packages.config way
This is an alternative :
Nuspec file :
<?xml version="1.0"?>
<package xmlns="http://schemas.microsoft.com/packaging/2013/05/nuspec.xsd">
<metadata>
<id>xxx.Win.x64.ForIPS11</id>
<version>0.0.0</version>
<title>xxx toolkit</title>
<authors>xxx Team</authors>
<owners>xxx</owners>
<requireLicenseAcceptance>false</requireLicenseAcceptance>
<description>xxx 0.0.0 x64 Windows to .NETFramework 4.6.1</description>
<releaseNotes></releaseNotes>
<copyright>2020</copyright>
<dependencies>
<group targetFramework=".NETFramework4.6.1" />
</dependencies>
<tags></tags>
</metadata>
<files>
<file src="bin\xxx.dll" target="lib\net461" />
<file src="resources\*.*" target="build\subfolder\resources" />
<file src="bin\*.dll" target="build\subfolder" />
<file src="xxx.Win.x64.targets" target="build" />
<file src="install.ps1" target="tools" />
</files>
</package>
xxx.Win.x64.targets to copy subfolder to output
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<NativeLibs Include="$(MSBuildThisFileDirectory)**\*.*" />
<None Include="#(NativeLibs)">
<Link>%(RecursiveDir)%(FileName)%(Extension)</Link>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
</ItemGroup>
</Project>
and install.ps1 to mark copy local false to the reference
param($installPath, $toolsPath, $package, $project)
$asms = $package.AssemblyReferences | %{$_.Name}
foreach ($reference in $project.Object.References)
{
if ($asms -contains $reference.Name + ".dll")
{
$reference.CopyLocal = $false;
}
}

How to export file with nuget?

I have a nuget package that uses the Apose.PDF package which I have a license for. The license is put in a separate file called Aspose.Total.lic and is located in the same folder The folder structure is like this.
Project
-PDFReader.cs
-Aspose.Total.lic
The PDFReader.cs has the following code to read the license:
static PDFReader()
{
var license = new License();
license.SetLicense("Aspose.Total.lic");
}
And all this works fine locally. But when I export my code to a Nuget package and use the package from another program, I get exceptions that it cannot find "Aspose.Total.lic" Copying the contents of the file and putting it as argument for SetLicense does not work, it expects a file. Now the question is, how and maybe where do I export the file when packing a nuget package? This is my nuspec file (some code is abbreviated):
<?xml version="1.0" encoding="utf-8"?>
<package xmlns="http://schemas.microsoft.com/packaging/2011/10/nuspec.xsd">
<metadata>
<id>XYZ</id>
<version>1.3.7</version>
<summary />
<dependencies>
<dependency id="Aspose.PDF" version="18.10.0" />
</dependencies>
<frameworkAssemblies>
<frameworkAssembly assemblyName="System" />
<frameworkAssembly assemblyName="System.Data" />
</frameworkAssemblies>
</metadata>
<files>
<file src="XYZ\bin\Release\XYZ.dll" target="lib\net47\XYZ.dll" />
<file src="XYZ\Aspose.Total.lic" target="lib\Aspose.Total.lic" />
</files>
</package>
My guess here is the the target location is wrong for the file.
NuGet exposes 3 folder automatically, lib for dlls, tools for powershell scripts and content for other content. (I think - it's been a while)
Try changing :
<files>
<file src="XYZ\bin\Release\XYZ.dll" target="lib\net47\XYZ.dll" />
<file src="XYZ\Aspose.Total.lic" target="lib\Aspose.Total.lic" />
</files>
To :
<files>
<file src="XYZ\bin\Release\XYZ.dll" target="lib\net47\XYZ.dll" />
<file src="XYZ\Aspose.Total.lic" target="content\Aspose.Total.lic" />
</files>
I think you should package that file as content. You can check the documentation how to achive that.

Log4Net: How to specify FileAppender layout type from a library?

I am using Log4Net's RollingLogFileAppender along with a custom layout class in my console application to print some metadata information in the header. I now want to package this custom layout class in a library and tell log4net to use it.
Previously I was successfully able to use the following appender config:
<appender name="RollingLogFileAppender" type="log4net.Appender.RollingFileAppender">
<threshold value="DEBUG />
<file value="C:\Logs\MyConsoleApp.log"
type="log4net.Util.PatternString" />
<preserveLogFileNameExtension value="true" />
<datePattern value="_yyyyMMdd" />
<rollingStyle value="Date" />
<appendToFile value="true" />
<staticLogFileName value="false" />
<layout type="MyConsoleApp.MyLogLayout">
<conversionPattern value="%date{ISO8601}|%-5level|%message%newline" />
</layout>
</appender>
I then tried moving the MyLogLayout class into a library project "MyLibrary.MyLogLayout", imported it into MyConsoleApp, and tried updating my appender code as follows:
<appender name="RollingLogFileAppender" type="log4net.Appender.RollingFileAppender">
<threshold value="DEBUG />
<file value="C:\Logs\MyConsoleApp.log"
type="log4net.Util.PatternString" />
<preserveLogFileNameExtension value="true" />
<datePattern value="_yyyyMMdd" />
<rollingStyle value="Date" />
<appendToFile value="true" />
<staticLogFileName value="false" />
<layout type="MyLibrary.MyLogLayout">
<conversionPattern value="%date{ISO8601}|%-5level|%message%newline" />
</layout>
</appender>
When trying to run it I get this error:
log4net:ERROR Failed to find type [MyLibrary.MyLogLayout]
System.TypeLoadException: Could not load type [MyLibrary.MyLogLayout]. Tried assembly [log4net, Version=1.2.15.0, Culture=neutral
, PublicKeyToken=669e0ddf0bb1aa2a] and all loaded assemblies
at log4net.Util.SystemInfo.GetTypeFromString(Assembly relativeAssembly, Strin
g typeName, Boolean throwOnError, Boolean ignoreCase)
at log4net.Util.SystemInfo.GetTypeFromString(String typeName, Boolean throwOn
Error, Boolean ignoreCase)
at log4net.Repository.Hierarchy.XmlHierarchyConfigurator.CreateObjectFromXml(
XmlElement element, Type defaultTargetType, Type typeConstraint)
log4net:ERROR Failed to create object to set param: layout
I have double checked to make sure that the dll is in the same folder, and that the reference works as expected. What's weird is that if I create a class MyConsoleApp.MyLogLayoutChild that just inherits everything from MyLibrary.MyLogLayout and reference it everything works, however the main point of pushing this code into a library is so that I don't have to create a new class for every project I make, especially one that doesn't have any logic in it other than to inherit everything from a parent class.
Does log4net support loading custom types from a dll library or am I just doing something wrong?
It does not work because TypeLoader does not know where to find your class. You need to help it by specifying fully qualified name of type.
Like
<layout type="MyLibrary.MyLogLayout, MyLibrary, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null">

Nuget nuspec not working with wildcard

I'm building a nuget package and all is well until I try to use the wildcard to import all dll's in a folder.
This works perfectly
<file src="KL.Ocr.Tesseract/x86/liblept172.dll" target="content\x86"/>
however this does nothing
<file src="KL.Ocr.Tesseract/x86/*.dll" target="content\x86"/>
Any help would be appreciated (and I am intentionally placing the dll's in content instead of lib because thats where they need to be)
<?xml version="1.0"?>
<package >
<metadata>
<id>asdf</id>
<version>1.0.0.0</version>
<title>asdf</title>
<authors>asdf</authors>
<owners>asdf</owners>
<requireLicenseAcceptance>false</requireLicenseAcceptance>
<description>asdf </description>
<copyright>Copyright 2016</copyright>
<tags>asdf</tags>
<frameworkAssemblies>
</frameworkAssemblies>
<dependencies>
</dependencies>
</metadata>
<files>
<file src="KL.Pas.Ocr.targets" target="build"/>
<file src="KL.Ocr.Pas.Host/bin/Debug/KL.Ocr.Pas.Host.dll" target="lib/net45" />
<file src="KL.Ocr.Pas.Host/bin/Debug/KL.Ocr.Pas.Worker.exe" target="lib/net45" />
<file src="KL.Ocr.Pas.Host/bin/Debug/KL.Pas.Ocr.Contracts.dll" target="lib/net45" />
<file src="KL.Ocr.Pas.Host/bin/Debug/KL.Ocr.Tesseract.dll" target="lib/net45" />
<file src="KL.Ocr.Pas.Host/bin/Debug/Tesseract.dll" target="lib/net45" />
<file src="KL.Ocr.Tesseract/x64/*.dll" target="build\x64"/>
<file src="KL.Ocr.Tesseract/x86/*.dll" target="build\x86"/>
<file src="KL.Ocr.Tesseract/tessdata/*.*" target="build\tessdata"/>
</files>
</package>
I am assuming you are generating the NuGet package on Windows.
If you switch to using backslash instead of forward slashes then it will work.
<file src="KL.Ocr.Tesseract\x64\*.dll" target="build\x64"/>
The above works fine. Using forward slashes does not seem to work.

Log4Net Not Logging When Deployed

Using version 1.2.11. Logging works on my dev machine, but won't create the directory or log when deployed.
I tried:
giving full directory access to IUSR, Everyone, local users.
running the app pool as a local admin account.
to use internal debugging as Phil Haack describes here.
Stopped and started the app pool after each change.
Nothing is produced in the output file.
My log4Net config is below. Any thoughts on what to try next?
<?xml version="1.0"?>
<log4net debug="true">
<appender name="file" type="log4net.Appender.RollingFileAppender">
<file value="..\Logging\log.txt" />
<appendToFile value="true" />
<rollingStyle value="Composite" />
<datePattern value="yyyyMMdd" />
<maxSizeRollBackups value="10" />
<maximumFileSize value="1MB" />
<threshold value="DEBUG" />
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%date [%thread] %-5level %logger [%property{NDC}] - %message%newline" />
</layout>
</appender>
<appender name="console" type="log4net.Appender.DebugAppender">
<layout type="log4net.Layout.PatternLayout">
<param name="ConversionPattern" value="%d [%t] %-5p %c [%x] <%X{auth}> - %m%n" />
</layout>
</appender>
<root>
<level value="ALL" />
<appender-ref ref="file" />
<appender-ref ref="console" />
</root>
</log4net>
If the directory and the file is not being created, then most likely, the configuration is not being read (and therefore used) at runtime.
I always forget to add the single line of code for Log4net that hooks up the configuration. This code usually appears in the bootstrap class in the application (e.g. Global.asax for an ASP.NET app).
XmlConfigurator.Configure(new System.IO.FileInfo(configFile)); // configFile being the path to the file.
Instead of the above in-line, you can add this attribute to the AssemblyInfo.cs file:
[assembly: log4net.Config.XmlConfigurator(Watch = true)]
Either way, this will wire up log4net. More information is found in the Manual Configuration section of the log4net docs.
If you're using IIS, make sure the correct group has modify access to the Logs folder (usually IIS_USERS).
Sounds like a permissions issue to me. I almost always use a directory where I don't have to enable any special permissions for the applications to write the log files to.
Here is what I generally use with log4net:
<file type="log4net.Util.PatternString" value="${ALLUSERSPROFILE}/<Company Name>/Logs/<Program Name>/<Log file name>.txt" />
Of cource you'll need to substitute Company Name, Program Name and Log file name in the above with actual values.
This will write to the ProgramData folder where access is typically not restricted. You can navigate to this folder in File Explorer by typing %ProgramData% or %AllUsersProfile%
Another thing I like about this method is that it works on nearly every microsoft O/S. XP, Vista, 7, 8
You probably do not know where you are logging:
<file value="..\Logging\log.txt" />
Will is derived from your running directory, which is iis its directory. You can better use a full path like:
<file value="c:\Logging\log.txt" />
Then you can give the right access rights to the logging directory. Log4net will not create any directories as far as I know. So you have to create the c:\logging directory first.
Non of the answers worked for me until I put these lines to the web.config app settings:
<add key="log4net.Config" value="Log.config" />
<add key="log4net.Config.Watch" value="True" />

Categories

Resources