Technical support is provided through Support Forums below. Anybody can view them; you need to Register/Login to our site (see links in upper right corner) in order to Post questions. You do not have to be a licensed user of our product.
Please read Rules for forum posts before reporting your issue or asking a question. OPC Labs team is actively monitoring the forums, and replies as soon as possible. Various technical information can also be found in our Knowledge Base. For your convenience, we have also assembled a Frequently Asked Questions page.
Do not use the Contact page for technical issues.
- Feature Requests & Product Improvement Ideas
- Please support PackageReference for NuGet packages
Please support PackageReference for NuGet packages
thanks for pointing me to github.com/NuGet/Home/issues/7276#issuecomment-486779786 . Did you mean the workaround suggested there by 'zivkan' on Apr 25 (2019)?
If so, I am afraid going that way, because by investigating further, it looks like the workaround itself is not working as intended. See github.com/NuGet/Home/issues/3830 , the comment from 'zivkan' from Oct 10 (2019). In this post, 'zivkan' (who suggested the workaround on Apr 25) confirms that it does not work - referring to an example made by 'louistio' on Oct 8, which uses precisely the workaround's technique (with "ref\<tfm>") .
Any updates on this issue?
I got the same problem recently and looks like there is a workaround described under related Nuget issue:
They require actions from your side. I can only manually reference these dlls but as you stated below it's not preferable solution.
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.
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!
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).
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>
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.
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!
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.
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?
- Feature Requests & Product Improvement Ideas
- Please support PackageReference for NuGet packages