Jump to content

TypeLoadException referencing System class


Recommended Posts

I'm trying to use a System.IO.Pipes.NamedPipeServerStream to do some interprocess communication between my KSP plugin and another application running on my box. Doing that, I'm getting this error:

[Exception]: TypeLoadException: Could not load type 'System.IO.Pipes.NamedPipeServerStream' from assembly 'System.Core, Version=3.5.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'.

In Visual Studio, I've tried targeting both versions of .NET Framework 3.5 (vanilla and Client Profile) to no avail. System.IO.Pipes.NamedPipeServerStream was new in .NET 3.5, so it should be supported OK. Am I failing to set up my plugin properly? I can't imagine having to do anything special to include standard System libraries. Could this evidence of more forbidden namespaces? (I know, I know, jumping right to the worst possible conclusion...)

Here's my plugin in its entirety, there's absolutely nothing special going on besides the pipe:


using System;using System.IO;
using System.IO.Pipes;
using UnityEngine;


namespace KSPSBC
{


[KSPAddon(KSPAddon.Startup.MainMenu, false)]
public class KSPSBC : MonoBehaviour
{
public void Awake() { }
public void Start()
{
print("Attempting to create NamedPipeServerStream object...");
using (NamedPipeServerStream pipeServer = new NamedPipeServerStream("testpipe", PipeDirection.Out))
{
print("Success!");
}
}
}
}


- - - Updated - - -

Hmm, this might be a Unity issue... According to this help request, "Unity deliberately removes some of the less commonly-used classes from the Mono library to reduce the memory and storage requirements of the game. In the Player Settings (menu: Edit > Project Settings > Player) you will find a setting called API Compatibility Level in the Other Settings panel. If you set this to .NET 2.0 instead of .NET 2.0 Subset, you will get all the Mono classes that Unity implements. The Pipes class is implemented in Unity, so you should be OK after you change this setting."

Is there any way to figure out what compatibility level KSP was compiled with?

Link to comment
Share on other sites

You mean we should target .NET 2.0 ?!

Every guide I've read so far seems to suggest 3.5.

Unity is using some version (2.xx) of Mono which does not directly correlate to the .NET framework version.

Link to comment
Share on other sites

Sorry, I don't want to confuse the issue, so here's how (I'm pretty sure) everything works. Unity uses Mono, which is a .NET compatible library developed by Xamarin, not strictly tied to Microsoft's .NET framework. Xamarin has chosen what features of .NET to recreate and implement. Any code you write will look and feel like .NET, but under the hood it's Mono. All the library linking happens at runtime, so even if you think you're using Microsoft's libraries, Mono's are being swapped in instead.

Meanwhile, Unity has various compatibility levels. Basically, they decided on a subset of Mono classes that most games will want to use, and made the rest optional. They did this cut down on load time and size. The core functions are (confusingly) called ".NET 2.0 Subset", while the extended functions are called ".NET 2.0". The version numbers don't really mean anything, it's just the name they went with when they built the editor. Games use the core subset by default, unless you specifically configure Unity to use the full suite.

Mono itself implements various different .NET functions, but not all of the features from either .NET 4.0 or .NET 3.5, which is why there's so much confusion about what library version to target. As far as I can tell, it doesn't matter what you choose, so long as you're only using classes that exist in the version of Mono used by KSP. The full list of Mono classes used by Unity, and the API compatibility level that exposes them, can be found here:

http://docs.unity3d.com/410/Documentation/ScriptReference/MonoCompatibility.html

So, my actual problem: I don't know how to tell what compatibility level KSP was compiled with. If it uses the ".NET 2.0 Subset" suite, I'm totally out of luck, because named pipes are not included in that level. There's an ApiCompatibilityLevel enumeration under UnityEditor, but I can't find any reference to the compatibility level that I can query at runtime.

Please correct me if I've made an mistakes, I'd hate to muddy the waters even more, and I've only been at this for two days.

Link to comment
Share on other sites

Close, but nope. PlayerSettings.apiCompatibilityLevel is a component of UnityEditor, which is only accessible in the actual Unity editor mode. You can't access it after compilation.

Edited by uberk
Link to comment
Share on other sites

I used a decompiler to have a look at the contents of the System.Core.dll that comes with KSP and I can confirm that there are no pipes to be found.

The one I found under Unity\Editor\Data\Mono\lib\mono\2.0 does have them.

That means KSP is using the Mono Subset?

Shouldn't it be possible to force loading of the other assembly? (You would have to ship that assembly with your addon then, of course.)

Link to comment
Share on other sites

Replacing Kerbals System.Core.dll with the one I mentioned works. The pipe is successfully opened.

Overwriting Kerbal assemblies is not very nice though, maybe even against the rules, I don't know.

It should be possible to do the same thing with some dynamic assembly loading magic and/or reflection instead of overwriting the original assembly.

Link to comment
Share on other sites

Ok, but the problem is that System.Core.dll is already loaded and it won't be loaded again automatically. Thats what I meant with dynamic assembly loading magic ;-)

I'm fairly sure that KSP will load all .dll's present in the GameData folder

Link to comment
Share on other sites

Yes and no. It doesn't work in this case because the runtime thinks it has already loaded the correct assembly and won't load the same assembly twice. I just tested it that for this case to be sure ;)

Link to comment
Share on other sites

Are you on a non-windows platform? Just dropping the System.Core into the same directory as the assembly with code from the OP worked fine for me on Windows 7 but there might not be an equivalent of named pipes on other platforms

Link to comment
Share on other sites

Huh, interesting, I wouldn't have thought to try that. Still, I'd like this to be easily distributable, so I went with hacky-but-standard file-based IPC instead of named pipes. Thanks for digging into the DLL, it's very helpful to understand how everything works.

Link to comment
Share on other sites

Are you on a non-windows platform? Just dropping the System.Core into the same directory as the assembly with code from the OP worked fine for me on Windows 7 but there might not be an equivalent of named pipes on other platforms

Weird, I'm on Windows 8.1.

Link to comment
Share on other sites

This thread is quite old. Please consider starting a new thread rather than reviving this one.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...