6

I have a solution that I'm trying to convert to .NET 4 from .NET 2. There are multiple projects in this solution, some of which are in C# and some of which are in VB. Most of them use system.xml for XML creation and parsing.

I've re-targeted all of the projects to .NET 4, and it compiles. When I try to run, though, I almost immediately get a System.FieldAccessException, saying "If the access level of a field in a class library has changed, recompile any assemblies that reference that library.". I did recompile the entire solution before this (and tried again after, which no change).

I then used the Assembly Binding Log Viewer to see if any bindings were failing, since this was happening when it referenced a different dll in the project. And sure enough, there are failures in there. They're in two different VB projects, and they both look like this:


The operation failed. 
Bind result: hr = 0x80070002. The system cannot find the file specified.

Assembly manager loaded from:  C:\Windows\Microsoft.NET\Framework64\v4.0.30319\clr.dll 
Running under executable  <path to my exe>
--- A detailed error log follows. 

=== Pre-bind state information === 
LOG: DisplayName = <projname>.XmlSerializers, Version=2013.20.0.0, Culture=neutral, PublicKeyToken=null, processorArchitecture=MSIL  (Fully-specified) 
LOG: Appbase = <projectpath> 
LOG: Initial PrivatePath = NULL 
LOG: Dynamic Base = NULL 
LOG: Cache Base = NULL 
LOG: AppName = <projname>.vshost.exe Calling assembly : System.Xml, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089.
=== LOG: This bind starts in default load context. 
LOG: Using application configuration file: <project path\config file> 
LOG: Using host configuration file:  
LOG: Using machine configuration file from C:\Windows\Microsoft.NET\Framework64\v4.0.30319\config\machine.config. 
LOG: Policy not being applied to reference at this time (private, custom, partial, or location-based assembly bind). 
LOG: Attempting download of new URL file:///<project path>/<projname>.XmlSerializers.DLL. 
LOG: Attempting download of new URL file:///<project path>/<projname>.XmlSerializers/CMG.XmlSerializers.DLL. 
LOG: Attempting download of new URL file:///<project path>/<projname>.XmlSerializers.EXE. 
LOG: Attempting download of new URL file:///<project path>/<projname>.XmlSerializers.EXE. 
LOG: All probing URLs attempted and failed.

Sure enough, there is no such file as any of those in my obj folder. But there wasn't before, either, and it worked fine. (Note: these binding errors are only showing up for the two VB projects that use XML, not the C# ones.) I removed and re-added the reference to system.xml, cleaned the solution, and rebuilt - still nothing.

I checked and system.xml v4 is in the GAC, and the public key is the same as what it's looking for here. I've seen references to a project option called "Generate serialization assembly" on the build tab. In the VB projects it's under Compile > Advanced options. It was set to Auto. I tried turning it on, rebuilt, and no change. I'm not sure where to look next - this was all new territory to me as it is. So where should this file be coming from, and why isn't it there, and why did it work in v2 without it? Or is all this xml stuff a red herring and nothing to do with the original issue? I'm starting to fear that, but can't be sure either way just yet. Any guidance would be highly appreciated.

ETA: If I run this outside of VS, the error log is showing the crash as an event 1000, with "Faulting module name: kernelbase.dll". The searching I've done so far on this indicates an issue with 32-bit apps running on 64-bit OSs, but I already have the entire thing set to compile as Any CPU. Turns out I'm also seeing the same binding errors when I run the .NET 2 version, even though it runs fine there. I'm starting to think more and more that the XML thing is a red herring.

Further ETA: XML thing was indeed a red herring. Added solution as an answer below.

teleute00
  • 561
  • 6
  • 25
  • Also, from http://stackoverflow.com/questions/1127431/xmlserializer-giving-filenotfoundexception-at-constructor - I tried doing the "check Just my Code" suggestion, and it still throws the original exception and won't let me past. – teleute00 Aug 09 '13 at 22:01
  • Have you tried compiling as x86 instead of asAny – Mark Hall Aug 13 '13 at 17:50
  • I actually don't have options under the dropdown. Any CPU is the only thing there to select. – teleute00 Aug 13 '13 at 17:55
  • I am not by a computer with Visual Studio, but I believe if you go to build configuration and select the drop down you can add a new configuration it will then give you option of x86 and x64. You can then clean your solution and rebuild with the new configuration. I have has problems with asAny on a x64 Windows before. – Mark Hall Aug 13 '13 at 17:59
  • Try [this advice](http://blog.gfader.com/2008/01/could-not-load-file-or-assembly.html) and [this advice](http://stackoverflow.com/questions/934411/what-is-myassembly-xmlserializers-dll-generated-for) regarding XmlSerializer weirdness. Not sure if that's the same problems you're seeing, but maybe will point you in the right direction. – Chris O Aug 13 '13 at 18:59
  • @ChrisO - Hmmm...tips from the first one were more or less something I already tried, but tried again just in case. No change. However, the second one mentioned a manual post build event. I checked the previous version of this (in 2008 with .NET 2) and there's no post-build event there either. And the serializer stuff shows in the log viewer there too, but the program works. The more I read, the more I'm wondering if it's basically just a warning that the serializer stuff will have to be generated at runtime. Which would mean it's likely a complete red herring to why I'm crashing...:-( – teleute00 Aug 13 '13 at 21:32
  • @MarkHall - Gotcha - didn't realise I needed to add. Yes, I was able to add. Set everything to x64, cleaned, and rebuilt. Still getting the same error and exception, though. – teleute00 Aug 13 '13 at 21:39
  • Try the x86. Especially if you are using any external resources such as dll's – Mark Hall Aug 13 '13 at 22:31
  • Hmmmm....I'm starting to feel like this is a trust issue. Especially the "Accessing Security-Critical Members" portion of http://msdn.microsoft.com/en-us/library/stfy7tfc.aspx - FieldAccess is one of the listed exceptions, and it does mention that there was a change in how it's handled in .NET 4, which would fit. – teleute00 Aug 13 '13 at 22:33
  • @MarkHall - Same issue with x86, sadly. – teleute00 Aug 13 '13 at 23:11
  • Can you create brand new empty .csproj file(s) and add your existing classes to that? Perhaps there's some project cruft causing you grief with the "upgrade". – Chris O Aug 14 '13 at 00:35

1 Answers1

2

So it was the security after all. As per http://msdn.microsoft.com/en-us/library/stfy7tfc.aspx:

A member is security-critical if it has the SecurityCriticalAttribute, if it belongs to a type that has the SecurityCriticalAttribute, or if it is in a security-critical assembly. Beginning with the .NET Framework 4, the rules for accessing security-critical members are as follows:

Transparent code cannot use reflection to access security-critical members, even if the code is fully trusted. A MethodAccessException, FieldAccessException, or TypeAccessException is thrown.

Code that is running with partial trust is treated as transparent.

Reading further, I found that with this change in .NET 4, they actually introduced 2 levels for these rules - level 2 is these new rules, and level 1 is the .NET 2 rules, for backwards compatibility. I set the assembly that was not accessible to use the level 1 rules, by adding:

<Assembly: System.Security.SecurityRules(System.Security.SecurityRuleSet.Level1)> 

To the AssemblyInfo.vb file (and adding system.security as a reference). Everything now works fine. Obviously, the ideal will be to change it to use level 2 rules, but that's down the road. This at least not only fixes the problem for the time being, but tells me exactly what the problem is. Thanks, everyone!

teleute00
  • 561
  • 6
  • 25