Archived

This forum has been archived. Please start a new discussion on GitHub.

MS Excel: System.IO.FileNotFoundException & IceInternal.BasicStream.loadObjectFactory

Hi all,

Could I get some information on how ICE (Slice in particular) deserializes/loads types in the .NET ecosystem?

This forum thread is very similar to our situation and a ZeroC developer included an interesting (if not very detailed) code snippet on how ICE resolves an incoming type.

We have C# / .NET 2.0 code that is loaded into Microsoft Excel (via COM, not VSTO) that provides access to our service running on a seperate server. We use ICE 3.3 currently.

The errors we see are:
Error of type System.IO.FileNotFoundException has occured:
	Message: 'Could not load file or assembly '...' or one of its dependencies. The system cannot find the file specified.'
	Target site: _nLoad
	Source: 'mscorlib'
	Stack trace: 
  		 at System.Reflection.Assembly._nLoad(AssemblyName fileName, String codeBase, Evidence assemblySecurity, Assembly locationHint, StackCrawlMark& stackMark, Boolean throwOnFileNotFound, Boolean forIntrospection)
  		 at System.Reflection.Assembly.nLoad(AssemblyName fileName, String codeBase, Evidence assemblySecurity, Assembly locationHint, StackCrawlMark& stackMark, Boolean throwOnFileNotFound, Boolean forIntrospection)
  		 at System.Reflection.Assembly.InternalLoad(AssemblyName assemblyRef, Evidence assemblySecurity, StackCrawlMark& stackMark, Boolean forIntrospection)
  		 at System.Reflection.Assembly.Load(AssemblyName assemblyRef)
  		 at IceInternal.AssemblyUtil.loadReferencedAssemblies(Assembly a)
  		 at IceInternal.AssemblyUtil.loadAssemblies()
  		 at IceInternal.AssemblyUtil.findType(String csharpId)
  		 at IceInternal.BasicStream.loadObjectFactory(String id)

Where the "..." assembly name varies according to end-user. In particular the assemblies are NOT used nor referenced by our code, either at design-time, runtime or early/late binding of any kind.

It is, however, likely that other Excel Addins have (tried to) load these assemblies and thus they're probably registered against the Excel process. The aforementioned ZeroC forum link suggests that the ICE runtime will interrogate these when trying to deserialize an object.

MSDN has an interesting piece of information:
If a previous request for the assembly failed, subsequent requests for the assembly are failed immediately without attempting to load the assembly.

My current hypothesis is that the ICE runtime grabs a list of assemblies (via System.AppDomain.CurrentDomain.GetAssemblies() maybe) and iterates over them until it finds a matching type. Given that Excel.exe is the host for our addin and our users often have 10's of other addins it could be a large list. If any of these other addins failed to load then the aforementioned snippet from MSDN could explain why it blows up.

Does this seem reasonable?


Possible solutions:
  1. It's a bug in ICE, we need to roll in a fix and re-deploy our application. Not ideal.
  2. We can attempt to isolate our code in its own AppDomain to fool ICE into ignoring any assemblies loaded elsewhere. Not ideal.
  3. We can understand the precise semantics of ICE and how it resolves types and advise our end users on how to (re-)configure their environment to get this working. I am cautiously optimistic that ICE (and/or .NET) maintains a first-come-first-served list of assemblies and that if we push our addin to the front of the queue it's assemblies will be searched (and the desired type found) before it even attempts to access 'bad' assemblies and dies. Not ideal, but it shouldn't require a re-deployment of our app and we can work on a strategic fix in the interim.

Any/all information is appreciated - especially if anyone has any experience regarding the use of ICE along with Excel!

Thanks in advance,
Jack

Comments

  • dwayne
    dwayne St. John's, Newfoundland
    Ice 3.3.1 contains a fix so that loading a referenced assembly no longer causes the application to fail if the assembly cannot be found. I would suggest you upgrade to 3.3.1 and see if it resolves the problem. Ice 3.3.1 is binary compatible with 3.3 so upgrading should be easy to do. Please see the " Upgrading your application from Ice 3.3.0" section in the Ice 3.3.1 release notes.
  • dwayne, thanks for the reply. I'll look into your suggestions.

    Could you confirm that my understanding of how ICE resolves types is correct (or close enough)?

    Whilst we test/build/deploy an updated version (assuming your suggestions work out) it would be desirable to have a known work-around such as "Our Addin must always be loaded first to avoid known compatibility issues".


    Thanks again,
    Jack
  • dwayne
    dwayne St. John's, Newfoundland
    jhoxley wrote: »
    dwayne, thanks for the reply. I'll look into your suggestions.

    Could you confirm that my understanding of how ICE resolves types is correct (or close enough)?

    Yes, Ice uses System.AppDomain.CurrentDomain.GetAssemblies() to get the list of assemblies and then recursively loads all referenced assemblies as well. Prior to Ice 3.3.1 if the loading of any of these assemblies would fail, then the application would terminate.
    jhoxley wrote: »
    Whilst we test/build/deploy an updated version (assuming your suggestions work out) it would be desirable to have a known work-around such as "Our Addin must always be loaded first to avoid known compatibility issues".

    I expect that there is no way to work around this issue except to use Ice 3.3.1. But I am also not very familiar with how Addins work with Excel so I could be mistaken and loading your plugin first may work.
  • Thanks again dwayne, your assistance is greatly appreciated.

    I'll see about making the appropriate changes and seeing if re-ordering the addins works as a temporary work-around.


    Best regards,
    Jack