Targeting UWP with csc.exe - c#

I'm trying to get IKVM working for Windows 10 UWP targets. I'm running into problems with the code I'm compiling with csc.exe. If I target .Net 4.0 or higher, then I get runtime errors like:
Method not found: 'Boolean System.Reflection.Assembly.op_Equality(System.Reflection.Assembly, System.Reflection.Assembly)'.
Because the '==' operator overload was supported in 4.0 or higher, but apparently some of the assemblies in UWP don't support this.
If I, instead, target .Net < 4.0 (e.g. 2.0 or 3.5), I get errors like:
Attempt by method 'IKVM.Internal.AssemblyClassLoader+AssemblyLoader..ctor(System.Reflection.Assembly)' to access method 'System.Reflection.Assembly.GetModules(Boolean)'
I think that this is to do with .net security not allowing me to access reflection from "secure" assemblies from my "insecure" assemblies.... and my assemblies are deemed "insecure" because they are compiled for 2.0/3.5 which predates the security model in play here.
Question:
How do I compile my C# files to target exactly the version of .Net that is used in UWP apps? (The build is taking place through a Nant build file via the <csc> tag).
Thanks for any pointers.
UPDATE:
I have found one way to target UWP's .Net libraries, and that is to make Visual Studio projects for each of the IKVM runtime projects - and build using that instead of Nant. I would still like to find a way to use the existing Nant build files, but so far it doesn't look like Nant supports building for UWP.

Related

VS2010 C# not including correct .net framework version in target

I am doing maintenance work on a VS2010 C# project built against .net v3.5.
I recently changed the project Target Framework properties to the latest version listed (v4) - due to an expectation of using a version of .net that is actually included in Win10 by default - and rebuilt without any apparent issues.
Unfortunately the embedded dependency in the generated .exe is still for .net v2.0.50727 (which is what is reported for v3.5 AFAIK) and the target machine (a clean install of Win10) is asking to install .net 3.5.
Using MS VS2010 v10.0.40219.1 SP1Rel.
Unfortunately upgrading the build tools isn't an option (building the program with VS2015 works just fine).
I have gone googling but don't seem to have found any similar reports.
Based on some of the comments already posted, I seem to have not made myself entirely clear - hopefully the following will help.
1) the intention/requirement is to be able to install this app on a clean install of Win10 without needing any further downloads. (installing .net 3.5 is easy to do, just not what is wanted)
2) the ultimate build environment for this is automated, visualized and not in my control and therefore upgrading the tool chain is a major pain that I'd like to avoid if possible.
3) AFAIK there are no third party libraries involved. All of the listed references (dll's) are v4.0.30319.
4) this is a XAML-based development, one part of three projects in the solution - the other entries are the installer and a C# custom installation library. As far as I can tell everything is set for .net v4.
Unfortunately the embedded dependency in the generated .exe is still for .net v2.0.50727 (which is what is reported for v3.5 AFAIK) and the target machine (a clean install of Win10) is asking to install .net 3.5
So there is some dependency in your project that targets that version of .NET. It could just be that you need to Build > Clean Solution and with a Build > Rebuild Solution the problem is solved.
Otherwise, assuming some library does require some .NET 3.x library, the installation request is entirely correct. Windows 10 does not have an option for installing .NET 2.0 and another for installing .NET 3.5. If you search for Turn Windows features on or off you will see this:
Any dependency on a .NET 2.x-3.x library will trigger the activation/installation of the first feature in the dialog.
As far as I can see, you have 2 options:
Move everything to a framework supported by Microsoft, most preferably .NET 4.7.2 given support and security.
Deal with the installation process and understand that Microsoft does not install these versions of .NET in purpose. You can, however, add these installers as a prerequisite and even bundle them with your installation, but that won't help much.
Thanks to all who have tried to help me!
The issue has been resolved.
There appear to have been two causes for this issue and my confusion:
it turns out that the blank install of Win10 that the testing was being performed on was not entirely clean - the pre-installed network drivers/utilities from intel also had a .Net v3.5 dependency...
one of the embedded resources in the project was effectively a uncompressed tar-ball containing a number of files; including an executable that had the dependency on .net v3.5 - this was a binary blob stored in svn so the content was had not been updated for several years (ie well before my involvement) ...
With both of these issues addressed it would appear that my problem is solved, so once again thank you for your feedback, suggestions and patience,
PeterT :->

.NET 4.0 assembly built on windows 8.1 does not work on lower windows versions

We have a project consisting of c++ core library and .NET wrappers (2.0 and 4.0) using Marshall. Build machine has Windows 8.1 OS.
C++ core and .NET 2.0 wrapper are built using MSVC 2005 and works perfect on other machines with lower windows versions.
.NET 4.0 wrapper is built using Microsoft SDK 7.1. Library works fine on build machine, but crashes on other machines (with .NET 4.0 installed) with following error:
Exception: System.MissingMethodException: Method not found: 'IntPtr System.Runtime.InteropServices.Marshal.GetFunctionPointerForDelegate(!!0)'.
It seems like wrapper was built using higher version of .NET and i have no idea how to solve this. As far as i understood there is no way to force using specific version of .NET 4.x while building though they are not backwards compatible.
You can specify the version of the .Net framework you want your app to use in the project properties window. Under the Application tab, select your preferred version under the Target framework dropdown. You can see more about targeting specific framework version on MSDN.
I managed to solve the problem. Somehow MSbuild used the best avilable toolset, though environment was configured to Windows SDK 7.1
While investigating the problem i finally found this article. So in order to build project i must configure environment to SDK and tell MSbuild to use toolset from this SDK.
So the solution is to call MSbuild with flag /p:PlatformToolset=Windows7.1SDK.
Thanks to everybody who was helping!
Because I don't use Visual Studio projects or MSBuild, I had to find out how to deal with this at the C# compiler's command line. It isn't that complicated, but there are some new concepts. The .NET assemblies in the same directory as csc.exe are "implementation assemblies". When you want to compile for a particular .NET version, you should use "reference assemblies", which are explained here: ILDasm, mscorlib and System.Runtime decompilation differences depending on the directory
You find reference assemblies under c:\program files (x86)\Reference Assemblies\Microsoft\Framework\.NET Framework. In there are directories for 3.5, 4.0, 4.5 and 4.5.1, on a machine with VS.2008 to VS.2013 installed. To make use of them, you need a command line like:
csc /target:library /noconfig /nostdlib+ /reference:"C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NET Framework\v4.5\mscorlib.dll" MyLibSrc.cs
/noconfig tells the C# compiler to ignore csc.rsp, which provides it with a default list of assemblies to reference, which are the implementation assemblies you don't want.
/nostdlib+ tells the C# compiler not to use its default standard library.
/reference tells the C# compiler that it can use the library whose pathname follows. The one shown here is the standard library for .NET 4.5: the project I built this with only uses the standard library, so that was all I needed.

Understanding .NET Assembly Reference Differences

I have two nearly identical DLLS (for the same open source project) - one was pre-compiled, and one was compiled locally by my own compiler (Xamarin Studio/Mono).
The DLL I compiled isn't working with the application that's supposed to be using it (while the pre-built one does), so I grabbed a decompiler to see if I can track down any differences (file sizes were slightly different):
I suspect the reference differences might be the problem. The TOP one is the manually compiled dll. How can I resolve this and make the references identical to the bottom dll's? I've tried using the Mono/.NET 3.5 option in the settings, but it resulted in errors complaining about default parameter specifiers in a bunch of places, so it seems as if it's meant to be compiled w/4.0. Here's a cap of the build settings options (only the Mono/.NET 4.0 option works):
What's causing the differences in assembly references?
Microsoft introduces the multi-targeting feature in its C# compiler, so that C# 4/5 compiler (csc.exe) can generate .NET 2.0/3.0/3.5 compatible assemblies. That's how the pre-compiled assembly comes from.
Unfortunately it is a long time issue for MonoDevelop, that it does not support such multi-targeting. For example, you cannot choose Mono/.NET 3.5 and expect Xamarin Studio/MonoDevelop to use the latest mcs compiler. It always uses the one for .NET 3.5 profile, and fails to compile if you use any C# 4/5 syntax.
You might try to use xbuild at terminal to compile, as xbuild does support multi-targeting. However, you might come across xbuild issues, as it is not yet as capable as MSBuild.

Getting c# and c++ to play nice together

I have a c# solution that accesses a c++ project through COM. The project has to be targeted to a specific processor, in this case x64. I am using the Windows installer to install the application.
The first problem I ran into was the c++ dll was not being registered properly when installed, and the program couldn't access it. I solved this by adding the c++ project to the solution.
For a while this worked, and everything installed properly, but then I started getting the following warning when I tried to build:
The target version of the .NET Framework in the project does not match the .NET Framework launch condition version '.NET Framework 3.5'. Update the version of the .NET Framework launch condition to match the target version of the.NET Framework in the Advanced Compile Options Dialog Box (VB) or the Application Page (C#, F#).
The setup would not install if I tried ignoring the warning. After some searching, I found that the c++ project was building in .NET 4.0, while my solution used .NET 3.5. I tried changing my solution to 4.0, but for some reason it stopped working, so I changed the c++ to 3.5.
This worked for a couple of builds, but then I began getting the following errors:
Error: LNK1104 cannot open file 'mfc90.dll'.
I added the file to the Additional Dependencies section, but then another link error occured (mfcs90.dll) and when adding that one, I got an x86 x64 conflict.
I'm not sure why these solutions worked for a while and then stopped, and I can't seem to find a resolution at any step that works. If anyone has seen anything similar to this, the insight would be appreciated.
In order to include the Microsoft runtime dlls, you should not simply include the dll in your application directory. This won't help when the dlls have various dependencies and you might run into different conflicts and versioning issues.
The way I would recommend installing the runtime dlls for you application is to include the official merge module in your MSI.
See the following link for your options to redistribute the runtime library:
http://msdn.microsoft.com/en-us/library/ms235316(v=vs.90).aspx

How to add .Net3.5 dll into .Net2.0 project?

I have a dll which is based on .net 3.5 -- it uses internally for example Linq, but the exposed API is straightforward, no fancy stuff. Since C# generics are resolved at compile time I assume that for calling party all it counts is API (all public parts).
However when I try to use this dll from net2.0 project I get info, that the dll cannot be referenced because the dll or one of its dependencies requires a later version of .net framework.
I can install any .net version I want on target computer (when entire app is installed), but I cannot change .net version for the project itself.
So: how to solve this? When adding a C dll to this project I had no such problems, so are C# dlls self-contained or not?
C# dlls need to have the .Net runtime to run as they are not compiled down to machine code. In this case the dll says it requires Net 3.5 so all your project will have to use 3.5 or higher.
To keep your project as Net 2.0 you would need to build another executable to contain the 3.5 DLL and communicate across separate processes.
The C DLL worked as it is compiled down to native code and does not require the .Net framework. (or at least not version higher than 2.0)
I've been using System.Core and the new System.Web.Extensions (for example) from 3.5 in an ASP.NET 2.0 app (using VS2005) for a while now with no problems. Similar to what Scott Hanselman blogged about here. So yes, it's possible.
.NET 3.5 still runs on the same CLR as .NET 2.0. So at runtime it's all the same. (Assuming you've tracked down any dependencies and copied those 3.5 DLLs to your bin folder as well.)
The only real limitation is what C# language features you can use at development time. Such as 'var', extension methods, or LINQ query syntax.
If you are using linq to objects, then you can use Linq Bridge:
http://www.albahari.com/nutshell/linqbridge.aspx
this is a Linq to objects implementation for .net 2.0.
You will still have to compile using vs2008 but you can compile with .net 2.0 as a target platform in that case.
(This is because the C# 3 compiler understands linq clauses even if you target .net 2.0, it will simply resolve the calls to linqbridge instead of the .NET 3.5 libraries in this case)
If you're using .NET 3.5 libraries then your application's requirements should be such that any consumer of it's API's should also be using .NET 3.5.
The only way you can bypass this is if you package all the dependencies of your application along with it. This means libraries your application uses which depend on the .NET 3.0 and 3.5 frameworks.
However, I'm not sure of the legality of ripping out chunks of the .NET frameworks and packaging them with an app. I'd read the EULA before doing anything like this. IMO, it's not worth the hassle; just install 3.5, ask your users to install 3.5 and be done with it or use only 2.0 features and libraries. At the very least, hacking around like this will only cause you more pain with deployment if there are framework updates in the future.
In either case, your app will work on .NET 2.0 as 3.0 and 3.5 are just extra libraries on top of the 2.0 runtime and libraries (as Craig mentioned) as long as all your dependencies are there.
C# DLLs are not self-contained. If your 3.5 DLL needs LINQ, it depends on system assemblies from the 3.5 (3.0 to be exact) framework, therefore the entire application depends on this version.
You could load the 3.5 assembly dynamically and use reflection to get access to the functions you need. This requires some overhead, of course.
Nothing pretty but there are ways to get the code happily working together (in the order of preference):
1) Upgrade both projects to 3.5
If I understand you correctly then your .net FW 2.0 Program will have dependency on 3.5 Library, which means for every functionality of the Program to work, it now requires FW 3.5. Since you state to have the code and authority to recompile the the Program AND install whatever FW on deployment, then you can upgrade it to 3.5. Sounds simple, but since you did not do this, then I guess you have good reasons (like other programs being higher up the call chain which you cannot upgrade to 3.5/recompile.)
2) Go around the FW2.0 compiler
Build the Program when referencing the 2.0 version of Library (or dummy, just providing the public API).
Build the 3.5 version of Library separately without Program (hence removing the need to reference the wrong FW assembly) and deploy the 3.5 version instead of the 2.0 version.
Since 2.0 and 3.5 use the same CLR runtime then fooling the compiler is enough. As long as the deployment maching has FW 3.5 installed, everything should be fine.
Note: everything is fine even if you have just .net 2.0 present on deployment machine and the user does not call .net 3.5 classes. If he does, there will be crash ;)
3) downgrade Library to 2.0
if you use only some classes of the .net FW then you could remain using the 2.0 compiler by adding those missing future assemblies to project. (this is the solution from Hanselman link shared by Craig). As already noted, you'll lose 3.5 compiler's syntactic sugar like vars.
Choose whichever suits your situation best.

Categories