How to provide a fallback assembly instead of the one that can't be loaded?
Asked Answered
M

4

7

At runtime, if a referenced assembly fails to load with e.g. "Strong name validation failed" (because it's test-signed), is there a way to provide a substitution assembly from another path that is real-signed?

I tried subscribing to AppDomain.CurrentDomain.AssemblyResolve, but it doesn't get fired, because the "bad" assembly technically exists, it just can't be loaded.

Is there a generic way to provide a fallback assembly when an assembly can't be loaded?

Malathion answered 2/10, 2009 at 3:9 Comment(5)
Can you try catching SecurityException when attempting to load the assembly?Christenson
I tried that, but I don't know what to do next... I still need to somehow tell the CLR assembly loader to pick the right dependency when loading my assembly...Malathion
What about trying to load the assembly explicitly on application startup and handle the exception. I somehow assume, that your assembly is loaded automatically.Exemplificative
Yes, but even after I've handled the exception - how do I still get the right version to load? It's linked statically. Hmm, maybe I should call Assembly.Load on the right version??Malathion
You might have to mess with publisher policy files ... I never have, so I am not putting this as an answer.Iago
H
1

I think you can just call assembly.LoadFrom to load the assembly of your choice with practically no security checks. We us this a lot at the start of our app so we can better deal with other assemblies version change.

Also look at Assembly.LoadFrom Method (String, Evidence, Byte[], AssemblyHashAlgorithm) looks like you can control passing in the hash as well as the hash algorithm.

Helfand answered 2/10, 2009 at 19:34 Comment(3)
Thanks. I just tried that and it gives me the same "Strong name validation failed" although I point it to the correct assembly: var assemblyName = AssemblyName.GetAssemblyName(correctFileName); var assembly = Assembly.Load(assemblyName); I'm thinking this is because the correctFileName is outside the app CodeBase folder. I guess I'll just leave it and go a different route...Malathion
with loadfrom you pass a file path and you can load the assembly from any where(pretty much).Helfand
Yup, LoadFrom seemed to get me past this. I've hit other problems later, so I've scrapped the whole approach, but yes, this problem is solved. Preload the assemblies instead of responding to load failures. Thanks!Malathion
B
1

What triggers the load attempt? IOW do you call Assembly.Load or this is a result of type resolution attempt? If it is the latter you can try to play with the AppDomain TypeResolve event, if the former - you can add additional logic to your call to the Assembly.Load.

If you load the Assembly manually though make sure you load it with Assembly.Load - not Assembly.LoadFrom. There are subtle differences in type resolution depending on what context assembly is loaded into

Brittnybritton answered 2/10, 2009 at 12:42 Comment(1)
I don't use Assembly.Load - the assembly in question is linked by the compiler. Whenever I start using the assembly - I call typeof(TypeInAssembly).GetTypes() - this loads the first assembly and recursively its unsigned referenced assembly. TypeResolve doesn't get raised either :( Thanks anyway.Malathion
H
1

I think you can just call assembly.LoadFrom to load the assembly of your choice with practically no security checks. We us this a lot at the start of our app so we can better deal with other assemblies version change.

Also look at Assembly.LoadFrom Method (String, Evidence, Byte[], AssemblyHashAlgorithm) looks like you can control passing in the hash as well as the hash algorithm.

Helfand answered 2/10, 2009 at 19:34 Comment(3)
Thanks. I just tried that and it gives me the same "Strong name validation failed" although I point it to the correct assembly: var assemblyName = AssemblyName.GetAssemblyName(correctFileName); var assembly = Assembly.Load(assemblyName); I'm thinking this is because the correctFileName is outside the app CodeBase folder. I guess I'll just leave it and go a different route...Malathion
with loadfrom you pass a file path and you can load the assembly from any where(pretty much).Helfand
Yup, LoadFrom seemed to get me past this. I've hit other problems later, so I've scrapped the whole approach, but yes, this problem is solved. Preload the assemblies instead of responding to load failures. Thanks!Malathion
D
1

there is a standard way to find an assembly in case the application fails to do so:

// register on assembly resolve exception
AppDomain.CurrentDomain.AssemblyResolve += ResolveEventHandler;

// try to load the assembly yourself
private static Assembly ResolveEventHandler(object sender, ResolveEventArgs args)
{
    return Assembly.Load(some_location);
}
Danikadanila answered 19/10, 2009 at 17:1 Comment(0)
M
0

Looks like what I want is impossible. I decided to go another route. We'll have to modify the build system to conditionally link to signed binaries instead of test-signed binaries at compile time.

Thanks everyone for the suggestions though!

Malathion answered 2/10, 2009 at 20:45 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.