Professional OPC
Development Tools

logos

Please support PackageReference for NuGet packages

More
20 Sep 2018 19:32 - 20 Sep 2018 19:35 #6700 by support
Hi.

Either way of addressing this from our side, it is a kind of change that will not go to the new build of the same version (which is reserved for isolated bug fixes); it would have to be a change that accompanies a fully new version. QuickOPC 2018.3 should go out in November or December this year. So, we will check the status of the issue on the NuGet side before releasing QuickOPC 2018.3, and address it if necessary - either in the way I suggested, or the way suggested by you.

As I wrote, the explanations related to why our assemblies are made up the way they are would be quite long. It's difficult to put it into a short form. To answer, in simplified form, part of your question: We do not want to the assemblies in question (App_Web_*) be actually referenced from user's project because 1) they only contain types for internal use that the developer does not need and would only pollute the namespaces available to him with stuff he should *not* use, and 2) one of them is for 32-bit and the other for 64-bit architecture, and when they are both referenced, some tools and some hosting environments have problems with it.

Best regards
Last edit: 20 Sep 2018 19:35 by support.
The following user(s) said Thank You: binki

Please Log in or Create an account to join the conversation.

More
20 Sep 2018 18:29 - 20 Sep 2018 19:59 #6699 by binki
Hi,

I agree with your decision of how to handle this issue. The issue on Github is young (15 days) and acknowledged as a bug by the nuget team member. There is a chance that it will be fixed soon, though I don’t have much hope, personally ;-).

I am wondering why the ugly hack you mention would require the files to also be embedded instead of just copied to the output directory. Is putting the native assemblies as <reference/> elements in the .nuspec impossible/wrong/broken for some reason? If that is the case, you can always target PackageReference users directly with a .targets file in the build/ folder of the .nupkg and basically put my workaround in or even use the MSBuild Copy Task: docs.microsoft.com/en-us/nuget/create-packages/creating-a-pa...props-and-targets-in-a-package . While referencing a .targets file for packages.config users requires writing install.ps1/uninstall.ps1 and is rather ugly, the automatic <Import/> that PackageReference uses works quite well and cleanly. Also, you can simply omit the install.ps1/uninstall.ps1 to avoid targeting packages.config users (who don’t even need it) IIRC.

I personally will use my workaround for the time being. I am only concerned that I will forget my workaroudn is in place when I go to update the NuGet package or VisualStudio in the future. In that case, if you fixed the issue from your end or VisualStudio fixed the NuGet bug, my workaround has a change (EDIT: chance) of behaving strangely.

Thanks for the help and insight!
Last edit: 20 Sep 2018 19:59 by binki. Reason: typo

Please Log in or Create an account to join the conversation.

More
20 Sep 2018 17:05 #6698 by support
Thanks for this as well. I noticed you have contributed to the NuGet issue list on GitHub as well.

And, I started debugging the problem, and I realized that I have been wrong. In the recent versions, we do NOT embed the App_Web_* assemblies inside EasyOpcClassic. I confused it, because it was the way it worked in the past. So yes, they *are* needed in the Output directory. And you are exactly right in identifying this as an issue with PackageReference on the NuGet client side.

We now need to think what to do about it. Ideally, if the PackageReference problem is fixed soon, I would prefer to do nothing on our side (and you/others can use the workaround you have kindly provided, in the meantime).

But, if it's not fixed soon, we will need to do something about it. That "something" is probably going to be an ugly hack with having these files separately and ALSO embedded (both of these are needed for reasons that are quite complicated and convoluted; I can explain if you are really interested).

Best regards
The following user(s) said Thank You: binki

Please Log in or Create an account to join the conversation.

More
20 Sep 2018 16:28 #6697 by binki
I would like to share the code I am using to work around the issue in my .targets files. I put this in a shared targets file in our buildsystem. You could put it in Directory.Build.targets in the folder where your .sln file is or directly into your .csproj. This target automatically detects a reference to OpcLabs.BaseLib and adds additional references to the App_Web_OpcLabs* based on the path of OpcLabs.BaseLib.

This is somewhat of a hack and only meant for people using PackageReference who are experiencing the same issue I am. It also should be removed from your project once PackageReference changes its behavior to copy all files from the lib/net452 directory ( github.com/NuGet/Home/issues/7276 ) or once OpcLabs releases an updated nupkg which provides an alternative workaround:
<?xml version="1.0"?>
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <!--
      Special hack for OpcLabs.QuickOpc to work around https://github.com/NuGet/Home/issues/7276 and http://www.opclabs.com/forum/feature-requests-product-improvement-ideas/2523-please-support-packagereference-for-nuget-packages for it.
  -->
  <Target BeforeTargets="ResolveAssemblyReferences" Name="HackAddQuickOpcNativeReferences">
    <ItemGroup>
      <Reference Condition="'%(Filename)' == 'OpcLabs.BaseLib'" Include="%(RelativeDir)App_Web_OpcLabs.EasyOpcClassicRaw.amd64.dll"/>
      <Reference Condition="'%(Filename)' == 'OpcLabs.BaseLib'" Include="%(RelativeDir)App_Web_OpcLabs.EasyOpcClassicRaw.x86.dll"/>
    </ItemGroup>
  </Target>
</Project>

Please Log in or Create an account to join the conversation.

More
20 Sep 2018 14:50 #6696 by support
Hello,

many thanks for the detailed report. No, you are not expected to do anything special to enable the assembly unpacking.

I will try to reproduce the problem with the project you provided on GitHub, and let you know then.

From our point of view, the problem is not in the fact that these App_Web_* assemblies are not present in the output. That should be OK by itself. We see the problem in the fact that you get an exception in that case.

Best regards
The following user(s) said Thank You: binki

Please Log in or Create an account to join the conversation.

More
20 Sep 2018 14:41 #6695 by binki
Hi,

If I make a very simple project which calls EasyDAClient.Create() and simply add OpcLabs.QuickOpc using PackageReference, then I get a stacktrace when running. But if I use packages.config, I don’t. The only difference I can tell is that packages.config results in the App_Web_OpcLabs.EasyOpcClassicRaw.*.dll files being copied. Otherwise, it might actually be a bug in NuGet/VisualStudio. If the latter, I will try to find a workaround.

Here is a side-by-side screenshot: i.imgur.com/xKUmX4b.png . The project on the left is at github.com/binki/QuickOpcPackagesConfig . The project on the right is at github.com/binki/QuickOpcPackageReference .

Here is my stacktrace from the PackageReference project:
Unhandled Exception: System.TypeInitializationException: The type initializer for 'OpcLabs.EasyOpc.DataAccess.EasyDAClient' threw an exception. ---> System.IO.FileNotFoundException: Could not load file or assembly 'App_Web_OpcLabs.EasyOpcClassicRaw.x86, Version=5.53.315.1, Culture=neutral, PublicKeyToken=6faddca41dacb409' or one of its dependencies. The system cannot find the file specified.
+ It is possible that Microsoft Visual C++ Redistributable Package is not installed.
   at System.Reflection.RuntimeAssembly._nLoad(AssemblyName fileName, String codeBase, Evidence assemblySecurity, RuntimeAssembly locationHint, StackCrawlMark& stackMark, IntPtr pPrivHostBinder, Boolean throwOnFileNotFound, Boolean forIntrospection, Boolean suppressSecurityChecks)
   at System.Reflection.RuntimeAssembly.nLoad(AssemblyName fileName, String codeBase, Evidence assemblySecurity, RuntimeAssembly locationHint, StackCrawlMark& stackMark, IntPtr pPrivHostBinder, Boolean throwOnFileNotFound, Boolean forIntrospection, Boolean suppressSecurityChecks)
   at System.Reflection.RuntimeAssembly.InternalLoadAssemblyName(AssemblyName assemblyRef, Evidence assemblySecurity, RuntimeAssembly reqAssembly, StackCrawlMark& stackMark, IntPtr pPrivHostBinder, Boolean throwOnFileNotFound, Boolean forIntrospection, Boolean suppressSecurityChecks)
   at System.Reflection.RuntimeAssembly.InternalLoad(String assemblyString, Evidence assemblySecurity, StackCrawlMark& stackMark, IntPtr pPrivHostBinder, Boolean forIntrospection)
   at System.Reflection.RuntimeAssembly.InternalLoad(String assemblyString, Evidence assemblySecurity, StackCrawlMark& stackMark, Boolean forIntrospection)
   at System.Reflection.Assembly.Load(String assemblyString)
   at OpcLabs.EasyOpc.Implementations.Native.Assemblies.LoadRawAssembly(String name)
   at OpcLabs.EasyOpc.Implementations.Native.Assemblies.get_EasyOpcClassicRaw()
   at OpcLabs.EasyOpc.Implementations.Native.Assemblies.GetRawType(String name)
   at OpcLabs.EasyOpc.Implementations.Native.DataAccess.NativeEasyDAClient.get_RawType()
   at OpcLabs.EasyOpc.Implementations.Native.DataAccess.NativeEasyDAClient.set_AdaptableParameters(EasyDAAdaptableParameters value)
   at OpcLabs.EasyOpc.DataAccess.EasyDAClient..cctor()
   --- End of inner exception stack trace ---
   at OpcLabs.EasyOpc.DataAccess.EasyDAClient.Create()
   at QuickOpcPackageReference.Program.Main(String[] args) in C:\Users\binki\source\repos\QuickOpcPackageReference\QuickOpcPackageReference\Program.cs:line 9

Here is the directory listing of the packages.config’s bin/Debug:
C:\Users\binki\source\repos\QuickOpcPackagesConfig\QuickOpcPackagesConfig\bin\Debug>DIR
 Volume in drive C has no label.
 Volume Serial Number is D220-7412
 
 Directory of C:\Users\binki\source\repos\QuickOpcPackagesConfig\QuickOpcPackagesConfig\bin\Debug
 
2018-09-20  09:51    <DIR>          .
2018-09-20  09:51    <DIR>          ..
2018-08-03  19:25         3,942,400 App_Web_OpcLabs.EasyOpcClassicRaw.amd64.dll
2018-08-03  19:25         2,809,856 App_Web_OpcLabs.EasyOpcClassicRaw.x86.dll
2018-08-03  19:25         6,181,888 OpcLabs.BaseLib.dll
2018-08-03  19:25         1,649,784 OpcLabs.BaseLib.xml
2018-08-03  19:25         6,393,856 OpcLabs.BaseLibForms.dll
2018-08-03  19:25         7,349,707 OpcLabs.BaseLibForms.xml
2018-08-03  19:25        18,677,760 OpcLabs.EasyOpcClassic.dll
2018-08-03  19:25         2,508,947 OpcLabs.EasyOpcClassic.xml
2018-08-03  19:25         8,456,704 OpcLabs.EasyOpcUA.dll
2018-08-03  19:25         4,487,926 OpcLabs.EasyOpcUA.xml
2018-09-20  09:51             5,120 QuickOpcPackagesConfig.exe
2018-09-20  09:37               189 QuickOpcPackagesConfig.exe.config
2018-09-20  09:51            15,872 QuickOpcPackagesConfig.pdb
              13 File(s)     62,480,009 bytes
               2 Dir(s)  29,011,046,400 bytes free

Here is the directory listing of the PackageReference’s bin/Debug:
C:\Users\binki\source\repos\QuickOpcPackageReference\QuickOpcPackageReference\bin\Debug>DIR
 Volume in drive C has no label.
 Volume Serial Number is D220-7412
 
 Directory of C:\Users\binki\source\repos\QuickOpcPackageReference\QuickOpcPackageReference\bin\Debug
 
2018-09-20  09:51    <DIR>          .
2018-09-20  09:51    <DIR>          ..
2018-08-03  19:25         6,181,888 OpcLabs.BaseLib.dll
2018-08-03  19:25         6,393,856 OpcLabs.BaseLibForms.dll
2018-08-03  19:25        18,677,760 OpcLabs.EasyOpcClassic.dll
2018-08-03  19:25         8,456,704 OpcLabs.EasyOpcUA.dll
2018-09-20  09:51             5,120 QuickOpcPackageReference.exe
2018-09-20  09:41               189 QuickOpcPackageReference.exe.config
2018-09-20  09:51            15,872 QuickOpcPackageReference.pdb
               7 File(s)     39,731,389 bytes
               2 Dir(s)  29,011,685,376 bytes free

I am still convinced that I get the different behavior because one directory has the App_Web_* assemblies copied to it whereas the other one doesn’t. If I compile the project, then manually copy over App_Web_OpcLabs.EasyOpcClassicRaw.*.dll before trying to run it, then I don’t get the crash.

I’m using OpcLabs.QuickOpc-5.53.315 via nuget.

I found this NuGet bug: github.com/NuGet/Home/issues/7276#issuecomment-423029619 . In this bug, it states that PackageReference *should* behave like packages.config by copying all files from the nuget’s lib/net452 folder to my project’s output directory. If the native code should automatically be unpacked and loaded, then the statement I made in that bug is incorrect. However, unless I’m mistaken, the empirical evidence is otherwise…. Since NuGet says it’s a bug, it’s possible that a future implementation of PackageReference itself will correctly copy all of the files and in the meantime I can try to write up a workaround in my .csproj file.

Am I supposed to somehow initialize the library to trigger the assembly unpacking? If so, I never realized that before. Please let me know.

Thanks for any help!

Please Log in or Create an account to join the conversation.

More
20 Sep 2018 05:14 #6691 by support
There should be no need for the App_Web_* assemblies to be contained in the output folder, in 99% of cases. These assemblies are embedded inside the EasyOpcClassic assembly and loaded in runtime as necessary.

Do you actually have a problem in terms that something does not work as it should? If so, please describe it (guidelines: www.opclabs.com/forum/announcements12/2365-rules-for-forum-posts ). If you just think that these files should be in your output folder, but everything else works, then it is as designed, and there is no problem to speak about, as explained above.

Best regards

Please Log in or Create an account to join the conversation.

More
19 Sep 2018 23:41 #6690 by binki
If I try to use PackageReference to reference packages versions 5.52.184 or 5.53.315, the nuspec only references OpcLabs.BaseLib.dll, OpcLabs.BaseLibForms.dll, OpcLabs.EasyOpcClassic.dll, and OpcLabs.EasyOpcUA.dll.

Please consider testing your packages with a VisualStudio-15.8 .csproj which references the NuGet using PackageReference instead of packages.config and verify that the bin/Debug folder contains the necesary App_Web_OpcLabs.EasyOpcClassicRaw.amd64.dll and App_Web_OpcLabs.EasyOpcClassicRaw.x86.dll files. Maybe these need to be added to as references to the .nuspec and a version bump released to get it to work?

Thanks!

Please Log in or Create an account to join the conversation.

Moderators: support
Time to create page: 0.212 seconds

      

 Recommend this on Google