internal System.AddIn.Contract.IContract CreateAddInAdapter(Object addIn, Assembly addinAdapterAssembly) { System.Diagnostics.Contracts.Contract.Ensures(System.Diagnostics.Contracts.Contract.Result <System.AddIn.Contract.IContract>() != null); // Create the AddIn Adapter System.AddIn.Contract.IContract addInAdapter = null; _currentComponentType = PipelineComponentType.AddInAdapter; Type adapterType = addinAdapterAssembly.GetType(_pipeline._addinAdapter.TypeInfo.FullName, true); Type addInBaseType = Type.GetType(_pipeline._addinBase.TypeInfo.AssemblyQualifiedName, true); AddInActivator.InvokerDelegate myInvokerDelegate = AddInActivator.CreateConsInvoker(adapterType, addIn.GetType()); addInAdapter = (System.AddIn.Contract.IContract)myInvokerDelegate(addIn); System.Diagnostics.Contracts.Contract.Assert(addInAdapter != null, "CreateInstance didn't create the add-in adapter"); return(addInAdapter); }
internal System.AddIn.Contract.IContract Activate() { // Assert permission to the contracts, AddInSideAdapters, AddInViews and specific Addin directories only. PermissionSet permissionSet = new PermissionSet(PermissionState.None); permissionSet.AddPermission(new FileIOPermission(FileIOPermissionAccess.Read | FileIOPermissionAccess.PathDiscovery, Path.Combine(_pipeline.PipelineRootDirectory, AddInStore.ContractsDirName))); permissionSet.AddPermission(new FileIOPermission(FileIOPermissionAccess.Read | FileIOPermissionAccess.PathDiscovery, Path.Combine(_pipeline.PipelineRootDirectory, AddInStore.AddInAdaptersDirName))); permissionSet.AddPermission(new FileIOPermission(FileIOPermissionAccess.Read | FileIOPermissionAccess.PathDiscovery, Path.Combine(_pipeline.PipelineRootDirectory, AddInStore.AddInBasesDirName))); permissionSet.AddPermission(new FileIOPermission(FileIOPermissionAccess.Read | FileIOPermissionAccess.PathDiscovery, Path.GetDirectoryName(_pipeline._addin.Location))); permissionSet.Assert(); // Let's be very deliberate about loading precisely the components we want, // instead of relying on an assembly resolve event. We may still need the // resolve event, but let's ensure we load the right files from the right // places in the right loader contexts. Assembly.LoadFrom(_pipeline._contract.Location); // only load the AddInBase in the LoadFrom context if there is no copy // of the assembly loaded already in the Load context. Otherwise there would be an InvalidCastException // when returning it to the host in the single appdomain, non direct-connect scenario, when // the HVA assembly is also used as the AddInBase assembly. // Since the reflection call to determine whether the assembly is loaded is expensive, only // do it when we are in the single-appdomain scenario. bool alreadyPresent = false; if (_usingHostAppDomain) { alreadyPresent = IsAssemblyLoaded(_pipeline._addinBase._assemblyName); } if (!alreadyPresent) { Assembly.LoadFrom(_pipeline._addinBase.Location); } Assembly addInAssembly = Assembly.LoadFrom(_pipeline._addin.Location); Assembly addinAdapterAssembly = Assembly.LoadFrom(_pipeline._addinAdapter.Location); CodeAccessPermission.RevertAssert(); // Create instances of all the interesting objects. // Either we don't need this here, or it may need to exist for the duration of // the add-in's lifetime. // // The assembly resolve event will be removed when the addin // controller's Shutdown method is run. _assemblyResolver = new ResolveEventHandler(ResolveAssembly); AppDomain.CurrentDomain.AssemblyResolve += _assemblyResolver; // Create the AddIn _currentComponentType = PipelineComponentType.AddIn; Type addinType = addInAssembly.GetType(_pipeline._addin.TypeInfo.FullName, true); Object addIn = addinType.GetConstructor(new Type[0]).Invoke(new Object[0]); System.Diagnostics.Contracts.Contract.Assert(addIn != null, "CreateInstance didn't create the add-in"); return(CreateAddInAdapter(addIn, addinAdapterAssembly)); }
internal System.AddIn.Contract.IContract Activate() { // Assert permission to the contracts, AddInSideAdapters, AddInViews and specific Addin directories only. PermissionSet permissionSet = new PermissionSet(PermissionState.None); permissionSet.AddPermission(new FileIOPermission(FileIOPermissionAccess.Read | FileIOPermissionAccess.PathDiscovery, Path.Combine(_pipeline.PipelineRootDirectory, AddInStore.ContractsDirName))); permissionSet.AddPermission(new FileIOPermission(FileIOPermissionAccess.Read | FileIOPermissionAccess.PathDiscovery, Path.Combine(_pipeline.PipelineRootDirectory, AddInStore.AddInAdaptersDirName))); permissionSet.AddPermission(new FileIOPermission(FileIOPermissionAccess.Read | FileIOPermissionAccess.PathDiscovery, Path.Combine(_pipeline.PipelineRootDirectory, AddInStore.AddInBasesDirName))); permissionSet.AddPermission(new FileIOPermission(FileIOPermissionAccess.Read | FileIOPermissionAccess.PathDiscovery, Path.GetDirectoryName(_pipeline._addin.Location))); permissionSet.Assert(); // Let's be very deliberate about loading precisely the components we want, // instead of relying on an assembly resolve event. We may still need the // resolve event, but let's ensure we load the right files from the right // places in the right loader contexts. Assembly.LoadFrom(_pipeline._contract.Location); // only load the AddInBase in the LoadFrom context if there is no copy // of the assembly loaded already in the Load context. Otherwise there would be an InvalidCastException // when returning it to the host in the single appdomain, non direct-connect scenario, when // the HVA assembly is also used as the AddInBase assembly. // Since the reflection call to determine whether the assembly is loaded is expensive, only // do it when we are in the single-appdomain scenario. bool alreadyPresent = false; if (_usingHostAppDomain) alreadyPresent = IsAssemblyLoaded(_pipeline._addinBase._assemblyName); if (!alreadyPresent) Assembly.LoadFrom(_pipeline._addinBase.Location); Assembly addInAssembly = Assembly.LoadFrom(_pipeline._addin.Location); Assembly addinAdapterAssembly = Assembly.LoadFrom(_pipeline._addinAdapter.Location); CodeAccessPermission.RevertAssert(); // Create instances of all the interesting objects. // Either we don't need this here, or it may need to exist for the duration of // the add-in's lifetime. // // The assembly resolve event will be removed when the addin // controller's Shutdown method is run. _assemblyResolver = new ResolveEventHandler(ResolveAssembly); AppDomain.CurrentDomain.AssemblyResolve += _assemblyResolver; // Create the AddIn _currentComponentType = PipelineComponentType.AddIn; Type addinType = addInAssembly.GetType(_pipeline._addin.TypeInfo.FullName, true); Object addIn = addinType.GetConstructor(new Type[0]).Invoke(new Object[0]); System.Diagnostics.Contracts.Contract.Assert(addIn != null, "CreateInstance didn't create the add-in"); return CreateAddInAdapter(addIn, addinAdapterAssembly); }
internal System.AddIn.Contract.IContract CreateAddInAdapter(Object addIn, Assembly addinAdapterAssembly) { System.Diagnostics.Contracts.Contract.Ensures(System.Diagnostics.Contracts.Contract.Result<System.AddIn.Contract.IContract>() != null); // Create the AddIn Adapter System.AddIn.Contract.IContract addInAdapter = null; _currentComponentType = PipelineComponentType.AddInAdapter; Type adapterType = addinAdapterAssembly.GetType(_pipeline._addinAdapter.TypeInfo.FullName, true); Type addInBaseType = Type.GetType(_pipeline._addinBase.TypeInfo.AssemblyQualifiedName, true); AddInActivator.InvokerDelegate myInvokerDelegate = AddInActivator.CreateConsInvoker(adapterType, addIn.GetType()); addInAdapter = (System.AddIn.Contract.IContract)myInvokerDelegate(addIn); System.Diagnostics.Contracts.Contract.Assert(addInAdapter != null, "CreateInstance didn't create the add-in adapter"); return addInAdapter; }
internal InspectionResults Inspect(PipelineComponentType componentType, string assemblyFileName, string pipelineRootDirectory) { System.Diagnostics.Contracts.Contract.Requires(assemblyFileName != null); System.Diagnostics.Contracts.Contract.Requires(pipelineRootDirectory != null); _assemblyFileName = assemblyFileName; _pipelineRootDirectory = pipelineRootDirectory; // Set up the assembly resolve event. _currentComponentType = componentType; ResolveEventHandler assemblyResolver = new ResolveEventHandler(ResolveAssembly); AppDomain.CurrentDomain.ReflectionOnlyAssemblyResolve += assemblyResolver; InspectionResults retval = new InspectionResults(); retval.Components = new List<PipelineComponent>(); retval.Warnings = new Collection<String>(); Type[] publicTypes; String assemblyName = null; // Need to assert again here because we are in a new appdomain FileIOPermission permission = new FileIOPermission(FileIOPermissionAccess.PathDiscovery | FileIOPermissionAccess.Read, _pipelineRootDirectory); permission.Assert(); try { // We want to load the assembly WITHOUT REGARD OF PUBLISHER POLICY. // If the directory structure contains v1.0 of a component and v1.1 // exists in the GAC and is a security fix to v1.0, we still want to // inspect v1.0. (The reason is we have other parts of the // pipeline that were likely compiled against v1.0, not v1.1, and // we do type comparisons by comparing the fully qualified assembly // name.) LoadFrom unfortunately respects policy. Assembly's // ReflectionOnlyLoad(byte[]) doesn't. ReflectionOnlyLoadFrom(String) // does respect policy if you've set DEVPATH, but only as a bug. // We don't think setting DEVPATH is interesting. Assembly a = Assembly.ReflectionOnlyLoadFrom(_assemblyFileName); publicTypes = a.GetTypes(); assemblyName = a.FullName; } catch (FileNotFoundException fnf) { retval.Warnings.Add(String.Format(CultureInfo.CurrentCulture, Res.AssemblyLoadFileNotFound, fnf.Message, fnf.FileName)); return retval; } catch (Exception e) { retval.Warnings.Add(String.Format(CultureInfo.CurrentCulture, Res.AssemblyLoadThrew, e.GetType().Name, e.Message, _assemblyFileName)); return retval; } PipelineComponent component = null; String relativeFileName = Utils.MakeRelativePath(_assemblyFileName, _pipelineRootDirectory); Type lastType = null; try { // Iterate over public types, looking for the appropriate custom attributes. foreach (Type type in publicTypes) { component = null; lastType = type; switch (componentType) { case PipelineComponentType.Contract: if (!Utils.HasCustomAttribute(PipelineComponent.ContractAttributeInReflectionLoaderContext, type)) continue; component = new ContractComponent(new TypeInfo(type), relativeFileName); break; case PipelineComponentType.AddInAdapter: if (!Utils.HasCustomAttribute(PipelineComponent.AddInAdapterAttributeInReflectionLoaderContext, type)) continue; component = new AddInAdapter(new TypeInfo(type), relativeFileName); break; case PipelineComponentType.AddInBase: if (Utils.HasCustomAttribute(PipelineComponent.AddInAttributeInReflectionLoaderContext, type)) retval.Warnings.Add(String.Format(CultureInfo.CurrentCulture, Res.AddInInAddInViewFolder, type.Name, _assemblyFileName)); if (!Utils.HasCustomAttribute(PipelineComponent.AddInBaseAttributeInReflectionLoaderContext, type)) continue; TypeInfo[] activatableAs = null; CustomAttributeData cad = Utils.GetCustomAttributeData(PipelineComponent.AddInBaseAttributeInReflectionLoaderContext, type); foreach(CustomAttributeNamedArgument cana in cad.NamedArguments) { if (cana.MemberInfo.Name == "ActivatableAs") { CustomAttributeTypedArgument arg = cana.TypedValue; ReadOnlyCollection<CustomAttributeTypedArgument> types = (ReadOnlyCollection<CustomAttributeTypedArgument>)arg.Value; activatableAs = new TypeInfo[types.Count]; int i = 0; foreach (CustomAttributeTypedArgument subArg in types) { activatableAs[i++] = new TypeInfo((Type)subArg.Value); } } } component = new AddInBase(new TypeInfo(type), activatableAs, relativeFileName, assemblyName); break; default: System.Diagnostics.Contracts.Contract.Assert(false, "Fell through switch - unrecognized componentType in InspectionWorker.Inspect"); break; } // switch // If we found a component, make sure it satisfies all of its constraints, and give our // PipelineComponents a chance to initialize state. if (component != null) { if (component.Validate(type, retval.Warnings)) retval.Components.Add(component); } } // foreach type in the assembly } // try catch (FileNotFoundException fnf) { retval.Warnings.Add(String.Format(CultureInfo.CurrentCulture, Res.AssemblyLoadFileNotFound, fnf.Message, fnf.FileName)); return retval; } catch (NotImplementedException) { retval.Warnings.Add(String.Format(CultureInfo.CurrentCulture, Res.NotImplementedFeatureBadCtorParamOrAssembly, _assemblyFileName, (lastType == null) ? "" : lastType.FullName)); return retval; } catch (Exception e) { retval.Warnings.Add(String.Format(CultureInfo.CurrentCulture, Res.InspectingAssemblyThrew, e.GetType().Name, e.Message, _assemblyFileName)); return retval; } AppDomain.CurrentDomain.ReflectionOnlyAssemblyResolve -= assemblyResolver; if (retval.Components.Count == 0 && _currentComponentType != PipelineComponentType.AddIn && _currentComponentType != PipelineComponentType.AddInBase) { retval.Warnings.Add(String.Format(CultureInfo.CurrentCulture, Res.NoAddInModelPartsFound, componentType, _assemblyFileName)); } #if ADDIN_VERBOSE_WARNINGS foreach (PipelineComponent c in retval.Components) retval.Warnings.Add(String.Format(CultureInfo.CurrentCulture, "Found a {0}. Name: {1} Assembly: {2}", componentType, c.SimpleName, c.AssemblySimpleName)); #endif return retval; }
internal InspectionResults Inspect(PipelineComponentType componentType, string assemblyFileName, string pipelineRootDirectory) { System.Diagnostics.Contracts.Contract.Requires(assemblyFileName != null); System.Diagnostics.Contracts.Contract.Requires(pipelineRootDirectory != null); _assemblyFileName = assemblyFileName; _pipelineRootDirectory = pipelineRootDirectory; // Set up the assembly resolve event. _currentComponentType = componentType; ResolveEventHandler assemblyResolver = new ResolveEventHandler(ResolveAssembly); AppDomain.CurrentDomain.ReflectionOnlyAssemblyResolve += assemblyResolver; InspectionResults retval = new InspectionResults(); retval.Components = new List <PipelineComponent>(); retval.Warnings = new Collection <String>(); Type[] publicTypes; String assemblyName = null; // Need to assert again here because we are in a new appdomain FileIOPermission permission = new FileIOPermission(FileIOPermissionAccess.PathDiscovery | FileIOPermissionAccess.Read, _pipelineRootDirectory); permission.Assert(); try { // We want to load the assembly WITHOUT REGARD OF PUBLISHER POLICY. // If the directory structure contains v1.0 of a component and v1.1 // exists in the GAC and is a security fix to v1.0, we still want to // inspect v1.0. (The reason is we have other parts of the // pipeline that were likely compiled against v1.0, not v1.1, and // we do type comparisons by comparing the fully qualified assembly // name.) LoadFrom unfortunately respects policy. Assembly's // ReflectionOnlyLoad(byte[]) doesn't. ReflectionOnlyLoadFrom(String) // does respect policy if you've set DEVPATH, but only as a bug. // We don't think setting DEVPATH is interesting. Assembly a = Assembly.ReflectionOnlyLoadFrom(_assemblyFileName); publicTypes = a.GetTypes(); assemblyName = a.FullName; } catch (FileNotFoundException fnf) { retval.Warnings.Add(String.Format(CultureInfo.CurrentCulture, Res.AssemblyLoadFileNotFound, fnf.Message, fnf.FileName)); return(retval); } catch (Exception e) { retval.Warnings.Add(String.Format(CultureInfo.CurrentCulture, Res.AssemblyLoadThrew, e.GetType().Name, e.Message, _assemblyFileName)); return(retval); } PipelineComponent component = null; String relativeFileName = Utils.MakeRelativePath(_assemblyFileName, _pipelineRootDirectory); Type lastType = null; try { // Iterate over public types, looking for the appropriate custom attributes. foreach (Type type in publicTypes) { component = null; lastType = type; switch (componentType) { case PipelineComponentType.Contract: if (!Utils.HasCustomAttribute(PipelineComponent.ContractAttributeInReflectionLoaderContext, type)) { continue; } component = new ContractComponent(new TypeInfo(type), relativeFileName); break; case PipelineComponentType.AddInAdapter: if (!Utils.HasCustomAttribute(PipelineComponent.AddInAdapterAttributeInReflectionLoaderContext, type)) { continue; } component = new AddInAdapter(new TypeInfo(type), relativeFileName); break; case PipelineComponentType.AddInBase: if (Utils.HasCustomAttribute(PipelineComponent.AddInAttributeInReflectionLoaderContext, type)) { retval.Warnings.Add(String.Format(CultureInfo.CurrentCulture, Res.AddInInAddInViewFolder, type.Name, _assemblyFileName)); } if (!Utils.HasCustomAttribute(PipelineComponent.AddInBaseAttributeInReflectionLoaderContext, type)) { continue; } TypeInfo[] activatableAs = null; CustomAttributeData cad = Utils.GetCustomAttributeData(PipelineComponent.AddInBaseAttributeInReflectionLoaderContext, type); foreach (CustomAttributeNamedArgument cana in cad.NamedArguments) { if (cana.MemberInfo.Name == "ActivatableAs") { CustomAttributeTypedArgument arg = cana.TypedValue; ReadOnlyCollection <CustomAttributeTypedArgument> types = (ReadOnlyCollection <CustomAttributeTypedArgument>)arg.Value; activatableAs = new TypeInfo[types.Count]; int i = 0; foreach (CustomAttributeTypedArgument subArg in types) { activatableAs[i++] = new TypeInfo((Type)subArg.Value); } } } component = new AddInBase(new TypeInfo(type), activatableAs, relativeFileName, assemblyName); break; default: System.Diagnostics.Contracts.Contract.Assert(false, "Fell through switch - unrecognized componentType in InspectionWorker.Inspect"); break; } // switch // If we found a component, make sure it satisfies all of its constraints, and give our // PipelineComponents a chance to initialize state. if (component != null) { if (component.Validate(type, retval.Warnings)) { retval.Components.Add(component); } } } // foreach type in the assembly } // try catch (FileNotFoundException fnf) { retval.Warnings.Add(String.Format(CultureInfo.CurrentCulture, Res.AssemblyLoadFileNotFound, fnf.Message, fnf.FileName)); return(retval); } catch (NotImplementedException) { retval.Warnings.Add(String.Format(CultureInfo.CurrentCulture, Res.NotImplementedFeatureBadCtorParamOrAssembly, _assemblyFileName, (lastType == null) ? "" : lastType.FullName)); return(retval); } catch (Exception e) { retval.Warnings.Add(String.Format(CultureInfo.CurrentCulture, Res.InspectingAssemblyThrew, e.GetType().Name, e.Message, _assemblyFileName)); return(retval); } AppDomain.CurrentDomain.ReflectionOnlyAssemblyResolve -= assemblyResolver; if (retval.Components.Count == 0 && _currentComponentType != PipelineComponentType.AddIn && _currentComponentType != PipelineComponentType.AddInBase) { retval.Warnings.Add(String.Format(CultureInfo.CurrentCulture, Res.NoAddInModelPartsFound, componentType, _assemblyFileName)); } #if ADDIN_VERBOSE_WARNINGS foreach (PipelineComponent c in retval.Components) { retval.Warnings.Add(String.Format(CultureInfo.CurrentCulture, "Found a {0}. Name: {1} Assembly: {2}", componentType, c.SimpleName, c.AssemblySimpleName)); } #endif return(retval); }