Unity Internal TargetInvocationExceptions while using Portable Class Library

TL;DR
I’m getting some errors with a PCL assembly (managed) that I built on Mac OSX using MDK version 4.2.1 (mcs command-line compiler). The Windows Phone 8 and Windows Store - Universal 10 build targets produce no errors during builds with this library.

The two errors [exception reports] that I receive are extremely similar. Here’s the portion that’s the same:

System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. ---> Mono.Cecil.AssemblyResolutionException: Failed to resolve assembly: 'System.Collections, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'
  at Mono.Cecil.BaseAssemblyResolver.Resolve (Mono.Cecil.AssemblyNameReference name, Mono.Cecil.ReaderParameters parameters) [0x00000] in <filename unknown>:0
  at Mono.Cecil.BaseAssemblyResolver.Resolve (Mono.Cecil.AssemblyNameReference name) [0x00000] in <filename unknown>:0
  at Mono.Cecil.DefaultAssemblyResolver.Resolve (Mono.Cecil.AssemblyNameReference name) [0x00000] in <filename unknown>:0
  at Mono.Cecil.MetadataResolver.Resolve (Mono.Cecil.TypeReference type) [0x00000] in <filename unknown>:0
  at Mono.Cecil.ModuleDefinition.Resolve (Mono.Cecil.TypeReference type) [0x00000] in <filename unknown>:0
  at Mono.Cecil.TypeReference.Resolve () [0x00000] in <filename unknown>:0

I’ve attached the complete output as two separate files to this post. We build the DLL with Unity 5.1.4f1 (build scripts, packaging) on Mac OSX and use the DLL with Unity 5.2.2f1 on Windows 10. Both produce the same errors.

TL;DR Question
Why would a Portable Class Library build cause this kind of output? How do I fix it?

Detailed Version
I’m creating a package for the Unity Asset Store that does not reference any platform-specific functionality. Our build system is currently running on Mac OSX. One of our assemblies uses some C# APIs that certain Windows platforms don’t play nicely with (Phone/Store). To support those Windows platforms we build multiple versions of the Assembly:

  • LibForEditor: A version that is only used while running in the Unity Editor. This enables extra GUI-related features that runtimes can’t link against.
  • LibForWinRT: A version that can link against all WinRT platforms (WinPhone/WinStore).
  • Core: Used for all other platforms in Unity (as they all use Unity’s Mono).

To build the WinRT version, we link against the following during compile time:

We pass the -noconfig and -nostdlib flags to the compiler to ensure that we aren’t targeting a specific .NET Framework as well as the profile.

We place this generated assembly in a separate folder, next to the Core version. We use the Plugin Inspector to instruct Unity to use that version for Windows Phone 8 and Windows Store builds. Builds using this assembly complete without issue when targeting Windows Phone 8 and Windows Store - Universal 10 (we’re setting up an environment to test the rest, of course).

The Problem
Something in Unity is unhappy with this Assembly. We’ve found two scenarios that produce errors:

In both of these cases, the call stack eventually leads to the stack portion I wrote above. I have included the actual output of both errors as files attached to this post. As I mentioned above, we build the DLL with Unity 5.1.4f1 (build scripts, packaging) on Mac OSX and use the DLL with Unity 5.2.2f1 on Windows 10. Both produce the same errors.

Note that this does not appear to cause any issues at runtime. The SetExecutionOrder error only occurs during our build process (as that’s where we’re setting the Execution Order) and the CheckForObsoleteAPIUsage error appears to only occur during initial import of the assembly. Once its in the AssetDatabase, everything seems fine.

Ideally, I would have an assembly that worked as intended and did not produce any error output. One workaround for users would be to package the assembly as a .unitypackage that developers could unpack to gain support for those platforms - an opt-in solution. We’d have to tell the users that the error is expected and harmless, of course.

As for the issue at hand, my guess is that the versions of the Frameworks that our assembly can reference aren’t in Unity’s lookup paths while attempting to resolve the assembly references during these processes. Is there a way to work around this issue? Or any way to compile a PCL that doesn’t cause this error?

2372716–161247–SetExecutionOrder.txt (5.03 KB)
2372716–161248–CheckForObsoleteAPIUsage.txt (4.18 KB)

While building with non-Unity C# Projects it appears that the resulting project has the same problem: open it up and it appears to have problems resolving the Assembly references in our PCL Assembly.

Anyone have any ideas what’s going on?

That’s strange. I’ve not seen this issue before.

Could you go into more details of “we build the DLL with Unity 5.1.4f1” - how exactly do you build a DLL with Unity?

Did you uncheck the “compatible with editor” checkbox for the WinRT plugin?

Can you paste visual studio output when you attempt to build the project?

Sure. We split the system into two types of Unity projects:

  • Source Project: Development cycle happens here and source code releases are generated by packaging up its contents.
  • Build Projects: A single project for each version of Unity that we support, plus one “common” build that contains the source code for project building.

Essentially, a simple command line script sequentially starts up each supported Unity version in batchmode and instructs it to run a build script command using executeMethod. That method does the following:

  • Compile each Assembly in the project. This differs depending on the target but at the core we run a process that calls the compiler with a set of arguments. The source is found in the Source Project and the output assembly has a location in the “current” Build Project.

  • For universal or Editor assemblies, we use the Mono compiler that ships with each version of Unity to do the actual compilation. Flags sent include:

  • -target:library

  • -nowarn:0169

  • -out:[ASSEMBLY_OUTPUT_PATH]

  • -define:[UNITY_EDITOR, UNITY_4_5, etc.]

  • -r:[PATHS_TO_LINKED_ASSEMBLIES]

  • For the WinRT assembly, we use a modern Mono compiler to gain access to PCL Profiles on Mac. In theory, these are the official Profiles provided by Microsoft. Flags are the same as above, with the following additions:

  • -noconfig

  • -nostdlib

  • -r:[PATHS_TO_PROFILE_ASSEMBLIES]

  • We use assemblies found in: /Library/Frameworks/Mono.framework/Versions/Current/lib/mono/xbuild-frameworks/.NETPortable/v4.5/Profile/Profile78

  • We reference a WinRTLegacy.dll that was copied from a Windows installation of the Unity Editor (5.2.2). This pulled from the Windows Phone 8 support directory.

  • Perform an Asset Copy. This pulls all assets (Textures, Scenes, etc.) into the build project. If any files are marked for exclusion, they are removed from the build at this step.

  • Refresh the AssetDatabase to ensure Assets import cleanly.

  • If we delete the Assembly from the build project prior to building, we would get the CheckForObsoleteAPIUsage error here. We don’t delete the Assembly because we want to maintain Asset GUIDs across builds.

  • Run through all script files in the source directory, inspecting their meta files looking for scripts with specially set Script Execution Order. When found, use MonoImporter.SetExecutionOrder to set the order of the scripts. Whens a script is found within several assemblies (as is the case with our core library which is compiled for Mono platforms, Editor, and WinRT), we actually go through and make sure each version is added.

  • This is where we get our errors during a build.

  • Save the assets using AssetDatabase.SaveAssets.

  • Export the final built package using AssetDatabase.ExportPackage.

So we don’t use the Unity runtime to do build the library, but we do issue the compilation command from within Unity.

As an aside, we also noticed that there’s a bunch of bugs inside Unity’s compilers related to spaces in paths. During our compilation passes outlined in 1.1 above we actually issue a command to a little helper script that manages to set things up to properly handle command lines with spaces in them.

One last comment on our build process. We have the following in our AssemblyInfo.cs for the core library:

#if NETFX_CORE
// Not sure if this is necessary - Xamarin Studio produces it automatically with Portable Code Libraries (at least).
[assembly: System.Runtime.Versioning.TargetFrameworkAttribute(".NETPortable,Version=v4.5,Profile=Profile78", FrameworkDisplayName = ".NET Portable Subset")]
[assembly: AssemblyFlags(AssemblyNameFlags.Retargetable)]
#else
[assembly: Guid(###)]
#endif

Yes. The only two platforms that are marked as compatible are:

  • WSAPlayer
  • WP8Player

EDIT: Everything from this point on holds true for an empty project with a single sphere in it on my machine
Windows Environment Details:

  • Windows 10 Pro N

  • Unity 5.2.2f1

  • Visual Studio Community 2015 - 14.0.23107.0 D14REL

  • Windows 8.1 and Windows Phone 8.0/8.1 Tools installed

  • Installed Platform SDKs:

  • Windows Phone SDK 8.0 - 11.0.50727.61

  • Windows Software Development Kit - Windows 10.0.26624

  • Virtualized on VirtualBox 5.0.8

In terms of the build not running, perhaps I’m missing some necessary component? Otherwise, I don’t think the issue with the build not running and the Error I get on Assembly Import are related.

Continuing with original content:
There are two ways to build it - using Unity C# Projects and using VS Projects. I thought I was having different situations occur with each but that turns out to not be the case. With either project set I get a similar experience.

Upon first opening the solution, I see 375 Errors (missing types: “are you missing an assembly reference?”) and 4 Warnings.

If I hit Rebuild, a status window that makes mention of NuGet pops up and starts working. Shortly after it disappears, the errors go away and the build completes. At that point, the output contains the following:

Restoring NuGet packages...
To prevent NuGet from restoring packages during build, open the Visual Studio Options dialog, click on the Package Manager node and uncheck 'Allow NuGet to download missing packages during build.'
1>------ Build started: Project: Install Test Project, Configuration: Debug x64 ------
1>  UnityInstallationDir "C:\Program Files\Unity\Editor".
1>  UnityWSAPlayerDir "C:\Program Files\Unity\Editor\Data\PlaybackEngines\metrosupport".
1>  UnityProjectDir "C:\Users\Eric\Documents\Development\Install Test Project".
1>  Copying unprocessed assemblies...
1>  Running AssemblyConverter...
1>  AssemblyConverter done.
1>  Install Test Project -> C:\Users\Eric\Desktop\Builds\WinUniversal10\Install Test Project\bin\x64\Debug\Install Test Project.exe
========== Build: 1 succeeded, 0 failed, 0 up-to-date, 0 skipped ==========

The build doesn’t run, however (Debug, x64, Local Machine). I’m not entirely sure what’s going on here but I don’t doubt that it could be related the other issues I’m having here. I get the following when I attempt to run it (Development Build flag had not been set for this output):

'Install Test Project.exe' (CoreCLR: DefaultDomain): Loaded 'C:\Program Files\WindowsApps\Microsoft.NET.CoreRuntime.1.0_1.0.23302.0_x64__8wekyb3d8bbwe\mscorlib.ni.dll'. Cannot find or open the PDB file.
'Install Test Project.exe' (CoreCLR: CoreCLR_UWP_Domain): Loaded 'C:\Users\Eric\Desktop\Builds\WinUniversal10\Install Test Project\bin\x64\Debug\AppX\entrypoint\Install Test Project.exe'. Symbols loaded.
'Install Test Project.exe' (CoreCLR: CoreCLR_UWP_Domain): Loaded 'C:\Users\Eric\Desktop\Builds\WinUniversal10\Install Test Project\bin\x64\Debug\AppX\System.Runtime.dll'. Cannot find or open the PDB file.
'Install Test Project.exe' (CoreCLR: CoreCLR_UWP_Domain): Loaded 'C:\Users\Eric\Desktop\Builds\WinUniversal10\Install Test Project\bin\x64\Debug\AppX\WinMetadata\Windows.winmd'. Module was built without symbols.
'Install Test Project.exe' (CoreCLR: CoreCLR_UWP_Domain): Loaded 'C:\Users\Eric\Desktop\Builds\WinUniversal10\Install Test Project\bin\x64\Debug\AppX\System.Runtime.InteropServices.WindowsRuntime.dll'. Cannot find or open the PDB file.
'Install Test Project.exe' (CoreCLR: CoreCLR_UWP_Domain): Loaded 'C:\Users\Eric\Desktop\Builds\WinUniversal10\Install Test Project\bin\x64\Debug\AppX\UnityPlayer.winmd'. Module was built without symbols.
Exception thrown: 'System.IO.FileNotFoundException' in Install Test Project.exe
Activation of the Windows Store app 'InstallTestProject_pzq3xp76mxafg!App' failed with error 'Windows was unable to communicate with the target application.  This usually indicates that the target application's process aborted. More information may be available in the Debug pane of the Output window (Debug->Windows->Output)'.
The program '[6688] Install Test Project.exe' has exited with code -1073741189 (0xc000027b).

Checking the Development Build option in Unity’s Build Settings and setting the Visual Studio Debugger to stop on System.IO.FileNotFoundException, I can see the following details:

It dies with the following callstack:

Install Test Project.exe!Install_Test_Project.App.App() Line 39
Install_Test_Project.Program.Main.AnonymousMethod__0_0(Windows.UI.Xaml.ApplicationInitializationCallbackParams p) Line 24

Once or twice during this process I noticed this following Warning appear in the Error List.

Does any of this spark anything?

File not found exception at that clalstack usually means that Unity depends on a DLL that isn’t present on your system. Could you use dependency walker to figure out which one it is? It’s pretty strange, built games shouldn’t depend on anything that isn’t part of Windows.

I opened up Dependency Walker and tried a bunch of the .exe’s in the resultant project. Here’s what I’ve found for my Empty Project project (the one with just a sphere in an otherwise empty scene):

  • bin/x64/Debug/Empty Project.exe: Shows absolutely nothing.
  • bin/x64/Debug**/AppX/Empty Project.exe:** See the image below.
  • bin/x64/Debug**/Core/Empty Project.exe:** See the image below.

Both the AppX and Core generated the same output:

2373869--161349--Screen Shot 2015-11-08 at 3.49.33 PM.png

I also received an error that said the following:

Some searching online seemed to indicate that I needed to reinstall the Visual C++ Redistributable, which I did: no change.

For the record, I created an entirely new test Application from within Visual Studio and that seemed to run just fine.

Sorry, I didn’t tell you which file you needed to look at. It seems it cannot load UnityPlayer.dll, so look at that in dependency walker.

Okay, I recalled reading that Windows 8 N users needed to install some extra components in order for things to work. In looking for that reference, here’s what I dug up:

  • FAQ entry about “even the project doesn’t compile”
  • Requirements when targeting Windows SDK 8.0 and 8.1

I had seen the first but wasn’t sure that it applied as I have Windows 10 N and the solution appeared to compile.

Regardless, I went ahead and downloaded the Media Features for Windows 10 N, rebooted, and things started to appear to link correctly.

That said, it still crashes but I now get the following output:

As the output hints, I am currently running this in VirtualBox which, according to DxDiag supports Feature Levels 9.3, 9.2, and 9.1.

Any thoughts?

Error 0x887a0005 means the graphics driver crashed… Since you’re running it in virtual box, I’d guess virtual box driver isn’t up to snuff.

Try adding this in App.xaml.cs after “appCallbacks = new AppCallbacks();”:

appCallbacks.AddCommandLineArg("-force-driver-type-warp")

This will force CPU rendering, so you’ll see whether it’s indeed the driver to blame. Just don’t ship the game with that flag :).

Awesome, that did it. VirtualBox driver is not up to snuff.

I was able to run both the Empty Project and the simple test project that makes use of our PCL library to verify that they build and run. I’m now able to actually test and debug some of the changes that I had to make to the script for the PCL compliance. Getting the FieldInfo of a type by strings is kind of a pain when you can’t use BindingFlags…

That said, any idea on the importation issue I mentioned in the very first post?

Unfortunately, I have no idea why that happens… That does sound a lot like a bug, though. Could you submit a report?

Sure. Would simply including the system as a unitypackage in an empty project suffice? (That way you can verify by simply unpacking the unitypackage.)

Aside: For whatever reason, starting up Windows 10 today to test our source code release showed that the Application was able to run using VirtualBox’s driver without the WARP flag. I then went back and retested the assembly version and even that worked today.

And here I thought we were beyond the days of “Did you try turning it off and turning it on again?” ;p

Yup that would do.

Okay, bug filed as 743463. Let me know if there’s anything else I can provide to assist.

One quick note: the error that shows up has an empty line at the top. This means that you might see a little red (!) error indicator icon in the bottom left corner while in Project view. If you check your console view, though, you will see the error.

It seems as though the Editor on OSX may not show that error icon, however. From my experience, the Windows Editor did properly show the icon. Sorry if this is confusing: it’s a bit tough to describe.

TL;DR: Be sure to check the console when you import the included sample dll.

Is there any word on this? I’m starting to see similar TargetInvocationExceptions in Unity 5.3 with our non-PCL assemblies… (unless Unity 5.3 snoops into internal unitypackages during the import process…).

The bug 743463 was resolved by design, you were trying to use an assembly compiled againt .NET 4 in Editor, this is not allowed, in Editor you can only use assemblies compiled against .NET 3.5 or lower.

I don’t believe we were trying to use that assembly in the Editor - in fact, I think it was marked as not for Editor. It is a DLL that is to be used by .NET platforms (WinRT) which actually do use .NET.

How are we supposed to include assemblies that we know will work for those platforms, marked as such in the Plugin Inspector, and sidestep the error? Perhaps a more informative warning? Or a way to tell the user about the issue so they can understand what’s going on?

You’re right, what is failing, is AssemblyUpdater which tries to update any imported assembly no matter what plugin settings are set, but that only means your assembly won’t be patched for deprectated API, that shouldn’t be a blocker for you.

In any case, I forwarded the bug to developer who’s responsible for AssemblyUpdater.

Sorry for mixup.

Cool, thanks. I completely understand that this is a hairy situation. Glad to hear that it’s on track to the right person’s eyes!