I'm currently chasing an issue (F0066886) with RedGate about a weird error being reported by SA.

As I've been investigating this here I've found a few odd things about SA that I'd like to get clarified.

1. Version Numbers

If assembly AA with v 1.0.0.0 refers to assembly BB with v 1.0.0.0 and we obfuscate AA, then it seems that SA may locate some other version of BB (say v 2.0.0.0) and assume this is the correct referenced assembly.

The obfuscated assembly AA then has a ref to BB v 2.0.0.0 whereas prior to obfuscation AA referred to v 1.0.0.0 of BB.

I've carefully verified this and seen this behaviour and have to say that I'm astonished.

The version numbers of other referenced assemblies stored in an assembly's manifest is sacrosanct and any tool that alters this has to be misbehaving surely?

If during obfuscation the SA tool cannot find a referenced assembly that has the required version then I'd expect an error to be reported not blindly use the assembly and refer to incorrect versions.

It seems that we could obfuscate a set of assemblies and ship them to customers and then risk bizarre runtime issues due to this.

Can someone at SA please explain and justify this behaviour because I am very concerned about this.

2. Referenced Assemblies

The issue I'm still chasing with RedGate is bewildering, but seems to stem from a weak policy for specifying the location of referenced assemblies.

When I start a new obfuscation project I specify the location of the assembly to obfuscate but never get an opportunity to specify the location of any referenced assemblies.

As a result SA relies upon some heuristic to locate these when we run an obfuscation, it does not tell us exactly where it finds referenced assemblies and offers no opportunity to formally specify where.

There is a thing called 'MandatoryPath' but this must be set using a text editor by editing the project settings file and is cumbersome and needs to be tweaked if ever we want to change it, moving a set of SA projects to a different disk causes mayhem for example.

All in all this is bewildering and I think needs to be improved, a straightforwrad GUI enhancement to SA could support a "References" capability where we can explicitly set the path for each referenced assembly - or at least some helpful GUI support, right now its damned confusing and I'm a very experienced .Net developer.

I'm working with you again through email, but I didn't want your forum post to feel neglected

As I've mentioned, the issue with how SmartAssembly handles versioned dependencies is a known bug (SA-31). This bug exists because SmartAssembly unfortunately has no way of knowing what paths were used by the original VS project (as they're not stored in the resulting assembly) and as a result, SA might end up using a different assembly that has a similar name even if it has a different version or is from a different location than the original (in some way though, this is actually a good thing as it would help when users are retargeting assemblies against later .Net versions). Again, I'm very sorry about this and the risk of runtime issues it might cause but at the moment, the only workaround is the MandatoryPath attribute.

However, I have just recalled a bit of a hacky workaround--if SmartAssembly cannot find youre dependencies when it first loads your project, it will prompt you to browse and point to the needed DLL. If you can hide your dependencies (i.e. move them outside of the main assembly's folder), you can then point SmartAssembly to the right DLLs.

Regarding the ability to specify MandatoryPaths from the UI, I'd also created a feature request (with SA-1591), although I do not know any timeline for this at the moment.

I'm working with you again through email, but I didn't want your forum post to feel neglected

As I've mentioned, the issue with how SmartAssembly handles versioned dependencies is a known bug (SA-31). This bug exists because SmartAssembly unfortunately has no way of knowing what paths were used by the original VS project (as they're not stored in the resulting assembly) and as a result, SA might end up using a different assembly that has a similar name even if it has a different version or is from a different location than the original (in some way though, this is actually a good thing as it would help when users are retargeting assemblies against later .Net versions). Again, I'm very sorry about this and the risk of runtime issues it might cause but at the moment, the only workaround is the MandatoryPath attribute.

However, I have just recalled a bit of a hacky workaround--if SmartAssembly cannot find youre dependencies when it first loads your project, it will prompt you to browse and point to the needed DLL. If you can hide your dependencies (i.e. move them outside of the main assembly's folder), you can then point SmartAssembly to the right DLLs.

Regarding the ability to specify MandatoryPaths from the UI, I'd also created a feature request (with SA-1591), although I do not know any timeline for this at the moment.

Hi Jessica - OK thanks for taking the time to explain this, much appreciated.

My main issue has been resolved now - you may recall we found a simple workaround.

However I am still waiting to hear back from you guys about the versioning problem.

In a nutshell I consider it inexcusable for SA to process a user's assembly and then identify dependencies that have different versions to those referenced by the original un-obfuscated assembly.

Doing so will very rarely - if ever - result in anything other than serious and bewildering problems.

If I have an assembly A that depends on X v1.1.1.1, Y v2.2.2.2 and Z v 3.3.3.3 then after obfuscation of A I do not expect the obfuscated assembly to refer to other versions of X, Y and Z - yet SA can and does do this without warning.

I understand that SA can't know the locations of the original assemblies dependencies and that it must use some heuristic, but it should INSIST only on assemblies which have the SAME version numbers as those referenced by the original input assembly - if it can't find any then it should INFORM the user and let them choose whether to use this wrong version or browse for an alternative - not silently settle for any old assembly that hapens to have the same name with no regard to its version.

In my view this is a serious bug because we could obfuscate an assembly and ship it and find that at runtime all hell breaks loose because the wrong versions of other assemblies are being picked up.

Please can someone let me know if this is or is not deemed to be a bug because we entrust a great deal to SA.