380 likes | 698 Views
Loading Assemblies in Extensible Applications. By Avinash R. Prasad. What are extensible applications?. Provide the ability to change the basic features of a program or add new features without recompiling
E N D
Loading Assemblies in Extensible Applications By Avinash R. Prasad
What are extensible applications? • Provide the ability to change the basic features of a program or add new features without recompiling • Provide the ability to load in and execute new code, including code written after program is shipped • Built using reflection, interfaces & dynamically loaded assemblies • Examples: IE 6, Visual Studio .Net 2003, SQL Server
Concepts and Terminology • Assembly names: Strong & Weak (used for locating assemblies) • Binding references: Early Vs Late • Specifying references: Fully Vs Partially • Version policy
Strong & Weak Names • Assembly’s identity consists of 4 parts: • Friendly name : File name without the extension • Version: String with 4 dot-limited numbers, major version, minor version, build number & revision number • Public key: Unique value to map a company or developer, occupies 128 bytes • Culture: Two letter code indicating localization for a particular language, can carry country code
Strong & Weak Assembly Names (Contd.) • Strong name when assigned cryptographic key pair, else weak name (done with compiler or sn.exe) to ensure security • Strong names used when intended to share among several applications • Strong name files have digital signatures embedded in the file containing the manifest • Strong name contains public key used to generate signature • For more info. lookup Applied Microsoft Framework Programming by Jeffrey Richter
Early Vs Late Binding • Early bound references recorded in metadata when assembly is compiled • Late bound references specified on the fly using APIs on System classes • Extensible applications to use both • .assembly extern statement represents early bound reference to an assembly • We shall focus on late binding
Fully and Partially specified references • When all four fields are specified, assembly reference is said to be Fully specified • If any field missing, it is Partially specified, results in looser binding semantics • ASP.NET uses partial binding and weakly named assemblies
Version Policy • CLR uses strict version checking to minimize conflicts between different versions, loads exact version by default • However can be overridden by series of statements called version policy. • Set in XML files • Has 3 levels: • Author of application • Publisher of shared assembly • Machine administrator
Extensible Application’s use of App Domains • Multiple app domains used to isolate add-ins • App domain manager (Ch. 5) created for each app domain to call assembly loading APIs • Add-in assemblies not loaded in default app domain • Communication between app domains limited to app domain managers
Key design issues • Limit volume of communication in terms of number of calls and data passed • Limit number of assemblies involved in calls across app domains (as an assembly must be loaded in both app domains) • Both app domains must be unloaded to completely remove assembly from process
System.Reflection.Assembly • Recall that calling a method on a type in another app domain is a remote call • Types used are marshaled by value and marshaled by reference (derive from System.MarshalByRefObject) • Type used to represent assemblies in .Net is marshaled by value, not by reference!! • So, instance of assembly must be loaded into the app domain where instance resides
Effects of marshal by value • Add-in assembly must be loaded into our default app domain, so can’t unload without terminating entire process • Can also lead to security breaches if policy in that domain is not configured correctly • Complication in deployment when specifying ApplicationBase • CLR tries to load assemblies into app domain never intended
Steps followed when loading a new add-in • Extensible apps made aware of new add-in (thro’ user interface or config file) • App domain is chosen in which to load (eg. all apps from same site in same app domain) • App domain manager in target domain is called to load add-in • App domain manager in target domain loads the add-in
.Net provided methods to load assemblies • AppDomain.Load - load into other app domains • AppDomain.ExecuteAssemblyByName – executes code when called • AppDomain.CreateInstance • AppDomain.CreateInstanceAndUnwrap • Assembly.Load – static method, so can load only in current app-domain • Assembly.LoadWithPartialName – deprecated in 2.0 and will be removed in future versions • Activator.CreateInstance
Ways to specify assembly identities • Specifying assembly identities with strings • Specifying assembly identities with System.Reflection.AssemblyName
Specifying Identities as Strings • “[friendlyName], Version=[number], PublicKeyToken=[token], Culture=[culture]” • friendlyName must come first while others can be in any order • Incorrect assembly names result in FileLoadException • If any of them not specified, then we have Partially Specified Assembly Reference
Specifying Identities using System.Reflection.AssemblyName • Has properties and methods to identify assembly to load • Property Name • Property Version • Property CultureInfo • Method SetPublicKey (byte[]) • Method SetPublicKeyToken (byte[])
How CLR locates assemblies • ApplicationBase – root directory, intended to be private for that domain • Global Assembly Cache (GAC) – CLR looks here first to resolve reference to strongly names assembly • Version Policy – XML configuration file • Codebases – Same config file with <codebase> XML element
Locating assemblies with weak names • Looks for codebase in app config file • Add-in comes with own application configuration file • Not likely to be used often as user will have to modify ConfigurationFile property in own application to use it • Probe for assembly in ApplicationBase or its subdirectories – loaded by name only
Locating assemblies with strong names • Steps to resolve reference • Determine version of assembly to load from the 3 version policy files • Look in GAC for assembly • Look in configuration files for any codebase locations • Probe in ApplicationBase and its sub-directories
Advantages of loading assembly from GAC • Better overall system performance • Loading from same location on disk uses less memory • OS loads DLL’s read-only pages once and shares them among all instances • Efficient verification of strong name • Verification process long and tedious • Only verified when installed into the GAC
Fuslogvw.exe • Logs each step CLR completes when resolving reference to a library • Useful for diagnosing errors and understanding loading process • Has two modes of running • Log every attempt to load an assembly • Log only those attempts that fail
Assembly loading exceptions • System.IO.FileNotFoundException – not found by CLR • System.IO.FileLoadException – when CLR encounters an error when parsing assembly name string passed to one of the APIs • System.BadImageFormatException – when file is not managed code
How CLR resolves partially specified assembly references • Looks in ApplicationBase – if strongly names found in ApplicationBase, then looks in GAC, searches version policy etc. • Public key token checked against assemblies in ApplicationBase, if not then FileLoadException is thrown • If version is specified with friendly name and assembly has weak identity, assembly is loaded nonetheless
Critical issues related to Assembly.LoadFrom • CLR must ensure that assemblies loaded dynamically by filename do not conflict with statically referenced assemblies • So, CLR isolates assemblies loaded statically from those loaded dynamically using binding contexts • Binding contexts are Load Context and LoadFrom Context
Other scenarios • CLR must make sure that types of the same name from different binding contexts are not mistaken for each other as problems occur during typecasting • If two assemblies from different locations but same weak name are attempted to be loaded, only one is loaded
Versioning considerations • Add-in could be built with different version of .Net, so version conflict • All versions of .Net are compatible with previously released versions i.e. backward compatible • Do not load add-ins from newer versions into applications written in previous versions • Loading add-in built in previous version into application in newer version OK
Versioning considerations (Contd.) • Application designer can pick which version of CLR to load into his process • Once CLR selected, consistent set of assemblies will be loaded into process (Unification) • If unification causes problems, override in application config file the choice of CLR to load • ImageRuntimeVersion used to determine version of CLR and .Net used
Unification (Contd.) • Two possible solutions • Load multiple versions of .Net framework libraries into same process • Redirect various references to single version of .Net Framework assemblies • Insufficient testing carried out my Microsoft to support these scenarios • So, CLR redirects all references to assemblies matching the CLR loaded into the process
Summary • All add-in assemblies to be loaded in a late-bound fashion • Use .Net’s API methods for loading • Implement version policy where appropriate • Use provided tools such as fuslogvw.exe for debugging
What’s coming in Version 2.0 • ReflectionOnly APIs - load exact file, no policy, no second-bind • Assembly.ReflectionOnly • Assembly.ReflectionOnlyLoad • Assembly.ReflectionOnlyLoadFrom • AppDomain.ReflectionOnlyGetAssemblies • AppDomain.ApplyPolicy • Type.ReflectionOnlyGetType
References • Customizing The Microsoft .Net Common Language Runtime – Steven Pratschner • Extensible Applications: New features without recompiling – Joe Wirtley http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnhcvs04/html/vs04f1.asp