NuGet package for C++/CLI library for use in C# libraries - nuget

What is the right way to construct a NuGet package for a mixed-mode C++/CLI library?
I have 32-bit and 64-bit builds of the dll, and an ASP.NET Core app (targeting full .NET framework only) using it that will be built for both platforms. The app's solution platform is "AnyCPU".
I have tried using the /runtimes/ folders, but then Visual Studio can't find the managed code to compile against.
Currently I have 2 packages, like "MyLibrary" and "MyLibrary64", with the dll in the /lib/ folder and conditional PackageReference in my csproj, but this doesn't feel right. Additionally, when I compile in VS, I get:
warning MSB3270: There was a mismatch between the processor architecture of the project
being built "MSIL" and the processor architecture of the reference "MyLibrary.dll", "x86".
This mismatch may cause runtime failures. Please consider changing the targeted processor
architecture of your project through the Configuration Manager so as to align the
processor architectures between your project and references, or take a dependency on
references with a processor architecture that matches the targeted processor architecture
of your project.
This questions is similar, but has no answers:
Create NuGet package for C++/CLI (mixed) assembly
Update/Clarification:
the app can run either hosted in IIS (64-bit) or as a standalone self-hosted installed application (32-bit), so both are unfortunately necessary.

As Hans already pointed out, the platform of the C++/CLI project must match the mode in which the managed code runs. Hence, an assembly set to AnyCPU that references a (mixed-mode) assembly set to x86 may always fail to load if it is loaded in a 64 bit process.
There are three ways I know of to fix this issue:
First, live with the warning and make sure that the process in which the assemblies are loaded is always a 32-bit process. I wouldn't recommend this.
Second, switch your application to x86 which guarantees that it always runs in a 32-bit process. This is the easiest and cleanest way, but it pins you to 32 bit.
Third, make a NuGet package that contains both, 32- and 64-bit builds of your mixed assembly together with an automatic loader switch. To this end, you need to make sure that the mixed assembly is not found (i.e. by renaming it in the NuGet package) and that there is a AnyCPU assembly that registers AppDomain.AssemblyResolve with an event handler that loads the 32- or 64-bit version of your mixed assembly, depending on the current process.
The third approach allows to provide a NuGet package with mixed-mode assemblies that can be referenced from AnyCPU assemblies. Note, however, that AppDomain.AssemblyResolve is a global concept and may interfere with other components in your application, which may lead to non-trivial bugs.

Related

Why does NuGet package reference incorrect .NET framework/standard?

tl;dr:
I have a .NET Framework 4.7.2 project consuming a NuGet package which supports .NET Standard 2.0. That package, in turn, requires another package which supports .NET Standard 2.0. However, when run, the latter package uses net461 binaries rather than netstandard2.0.
How do I force a NuGet package & its dependencies to use .NET Standard 2.0?
Are there special steps required to consume a .NET Standard package from a .NET Framework 4.7.2 project?
Specifics:
I am trying to get the NuGet package for SparkplugNet (which uses the MQTTNet package) working in a .NET Framework 4.7.2 project - just the basic "How to use" SparkplugB example. Both projects support .NET Standard 2.0. After some debugging (details below), it appears MQTTNet is trying to use code paths specific to .NET Framework 4.6.1, rather than .NET Standard 2.0, and crashing with no feedback whatsoever.
To troubleshoot, I built SparkplugNet and MQTTNet from source. As far as I can tell, the crash comes from hitting .NET 4.5/4.6.1-specific code in CrossPlatformSocket.ConnectAsync(), specifically this line (in context):
await Task.Factory.FromAsync(_socket.BeginConnect, _socket.EndConnect, host, port, null).ConfigureAwait(false)
When I debug, _socket is a System.Net.Sockets.Socket which doesn't appears to have a BeginConnect() method, at least in the source file my debugger pulled. I am not sure why it branches to that code when .NET Standard 2.0 would be a better fit.
Back to a 4.7.2 project consuming SparkplugNet & MQTTNet via NuGet package.... If I look at the reference paths, SparkplugNet is properly pointed at the netstandard2.0 folder, but MQTTNet points to packages\MQTTnet.4.1.3.436\lib\net461\MQTTnet.dll. If I change the hint path manually in the project file, MSBuild appears to pull from the netstandard2.0 folder, but it still crashes. I assume it is the same cause, though I'm having trouble debugging using NuGet packages. Also, I'm hoping for a better solution than hacking hint paths.

nuget - Reference specific framework version from installed package?

This scenario goes a bit against the whole way nuget works so what i might be asking for is a hack...
My problem:
I need to have Restsharp and Protobuf-net referred to in a .net assembly that going into SQL-CLR for Server 2008 (so max .net 3.5, framework 2.0).
Restsharp goes back to 3.5 as the lowest supported fwk version.
Protobuf-net 3.5 onwards has a lot of gunk referring to system.servicemodel (and WCF) which i don't need and use and actively want to remove because it causes issues with installing on SQL-CLR. Protobuf-net 2.0 doesn't have this :)
So i've built and tested my code with an assembly targeting .net 3.5 and i installed the restsharp nuget - which gave me the correct reference and i manually added a reference to the protobuf-net 2.0 distro.
This is where i'd like to know - can i (in any way) install the protobuf-net nuget package but still have it reference the .net20 DLL in my assembly which targets 3.5?
The static reference is not a huge deal since protobuf-net has been pretty stable, but i'd like to get the whole setup via nuget if possible.
In the end, this is a workaround as solution to:
protobuf-net version without system.servicemodel dependency?
If there's a better answer to that, i'd be very grateful :)
As far as I know, that is not possible. You could of course create your own custom build and host it on a local nuget drop, or as your own nuget package on the public feed. AFAIK, there's no way to do what you want inside a new nuget folder in the existing package.

How to obfuscate class library that references Autofac?

I am using Autofac in a project that is being obfuscated using Dotfuscator. the dotfuscator fails saying it cannot find mscorlib version 2.0.5.0
Is there a way to tell Dotfuscator how to obfuscate Autofac with portable Dll?
Is Autofac team planning releasing autofac with reference to .NET 4.0?
Any other suggestions?
I don't know what version of Dotfuscator you're using, but it does seem that at least as of 4.9.9000 they "know" about Portable Class Libraries. If you aren't at that version and can't upgrade, you might need to contact Dotfuscator support to find out a solution. (Another question of similar nature also pointed to updating Dotfuscator as the answer.)
A similar sort of issue occurs with FxCop analysis and SecAnnotate. To get around those issues with those tools, you need to tell them to ignore version information on certain assemblies (like System.Core and mscorlib). You may need to use an option like that on Dotfuscator if such a thing exists.
PCL can also cause challenges on machines that don't have all the latest .NET patches. Make sure you're patched up.
There is no plan to release an Autofac tailored just to .NET 4.x Autofac is a Portable Class Library so it can support multiple platforms without conditional compilation, making for easier testing and development. It switched away from platform-specific builds as of 3.0 and there's no plan to go back.
If upgrading Dotfuscator and patching your machine doesn't fix the issue, your best bet is to find the Dotfuscator mechanism for ignoring assembly version.

ODP.NET deployment without installation

I want to deploy a client application that uses Oracle's ODP.net but I don't want to install ODP.net on every machine. Rather I'd like to copy the managed dll oracle.dataaccess.dll on every machine and have the native dlls on which it depends available, on a shared disk.
By decompiling the oracle.dataaccess.dll code I have seen that it calls a method that gets the location of the native dlls from the registry. So, in addition to copying the oracle.dataaccess.dll on every machine I would have to add the registry keys that would point to the native dlls on the shared disk.
My question: does one foresee any problem arising from that technique of odp.net deployment?
The only files you need from the latest client are:
Oracle.DataAccess.dll
oci.dll
oraociicus11.dll
OraOps11w.dll
Just make sure they get copied to the output directory and everything will work. Nothing needs to be registered anywhere. You will however need to make separate x86 and x64 builds with the respective architecture's DLLs since an Any CPU .NET application will run in 32-bit mode on a 32-bit OS and in 64-bit mode on a 64-bit OS.
1) ODP.NET is currently a mixture of managed and unmanaged DLL's. It also relies on lower level unmanaged DLLs from the Oracle client - eg for networking, etc.
2) You will need all these required ODP.NET and client DLLs on each machine you deploy to.
3) One potential solution to make this easier on you is to look into the "XCOPY" deployment package. See the ODP.NET download page. This is a smaller install and allows you to write your own custom installer. You can include these XCOPY files as part of your own install.
4) Oracle will be doing a beta of a fully managed provider in 2012 which will make this situation much better (and the total size will be a couple megabytes only).
Christian Shay
Oracle
Since they're unmanaged I'd assume that they'd be ok on a network path, though that should be easy enough to test. However I'd suggest that rather than changing the registry setting, you might be better off changing the DllPath config setting as described here.

How to build software that doesn't require a framework on the user's machine?

I am an ASP.NET developer, but now I want to build a software that can be installed on my PC. Software built in .NET platform only works when the .NET Framework is installed, and software written in Java only works if the JDK is installed. When I install programs like Firefox, uTorrent, etc., I don't need to have any frameworks (.NET, JDK, etc.) installed. How do I write software that doesn't depend on a framework?
You will have to use a language that isn't dependent on a framework or otherwise only target clients that are already have your framework installed.
If you chose C or C++ for example, you would distribute binaries to your client that contained machine code. This code would not be dependent on a runtime environment (like C# or Java) or an interpreter (like Python or Ruby). This is the way that applications like Firefox and uTorrent are written.
"When I install programs like Firefox, uTorrent, etc., I don't need to have any frameworks."
Actually, you do. They just tend to use the C++ frameworks, such as MFC, some of which are already installed. Even then, there are installers for these frameworks that are included with other application installers (usually called Microsoft Visual C++ 2008 SP1 Redistributable Package or something like that. See Also: Visual C++ Deployment).
Now, having said that, they don't require a virtual machine (like a JVM for Java or a CLR for .NET), because C++ compiles down to x86 / x86-64 machine language to be executed directly by the operating system.
Fundamentally you always have a "platform", which is the operating system. Traditionally if you want to write code that will run on multiple operating systems you would use a fairly portable language such as C++ that produces native executables for a target operating system. Still, there are differences between how different operating systems work. There will therefore be parts of the C++ (or other portable language) code that are specific to that OS. You try to isolate those parts as much as possible to minimize the effort to port between OSes. Still, that effort is typically very substantial. You are also limited to the least common denominator of features available on all target operating systems (unless you create a custom version for a given OS that exposes its special features).
This is complex, time consuming and expensive. That's the reason technologies such as Java and .NET were created.
If You want to build really platform independent software You will finally end up with solution like Java Runtime or .NET. What You could do, You could thing about writing application in such way that You are able to compile/run it on most known platform, and of course then You need middleware to translate Your application's objects into platform objects (functions, whatever...).
I have seen solutions made in Pascal for DOS in such layer of abstraction that with little effort it was moved directly to Delphi for Windows without touching application logic.