Code:
/ 4.0 / 4.0 / untmp / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / fx / src / AddIn / AddIn / System / Addin / Hosting / AddInControllerImpl.cs / 1305376 / AddInControllerImpl.cs
// ==++== // // Copyright (c) Microsoft Corporation. All rights reserved. // // ==--== /*============================================================ ** ** Class: AddInController ** ** Purpose: Allows you to shut down an add-in, which may unload ** an AppDomain or kill an out-of-process add-in. ** ===========================================================*/ using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.IO; using System.Reflection; using System.Runtime.ConstrainedExecution; using System.Runtime.Remoting; using System.Runtime.Remoting.Lifetime; using System.Runtime.Serialization; using System.Security.Permissions; using System.Security; using System.Diagnostics; using System.AddIn.Contract; using System.AddIn.Pipeline; using System.Diagnostics.Contracts; namespace System.AddIn.Hosting { // The lifetime of an add-in is controlled by remoting's leases, and users // who do essentially ref counting by obtaining a lease. No one has solved // the distributed (cross-machine) garbage collector problem yet, but leases // appear to be the best approximation we currently have. internal sealed class AddInControllerImpl { // Maps host add-in views (precisely, instances of host adapters typed // as their base type) to the associated add-in controllers. private static HAVControllerPair _havList; private static readonly Object _havLock = new Object(); //private AppDomain _appDomain; private bool _unloadDomainOnExit; private AddInToken _token; private AddInEnvironment _addInEnvironment; private static int _addInCountSinceLastPrune; private const int AddInCountSinceLastPruneLimit = 25; // Note that keeping this reference to the transparentProxy // prevents it from being GC'd in the same sweep as the HAV. Indeed, it cannot // be GC'd until we remove its HAVController pair. This is good, // since it allows us to call into the TransparentProxy from the finalize method // of LifetimeTokenHandle internal IContract _contract; // Contract or a Transparent Proxy to the contract private ActivationWorker _activationWorker; private WeakReference _havReference; internal AddInControllerImpl(AddInEnvironment environment, bool unloadDomainOnExit, AddInToken token) { System.Diagnostics.Contracts.Contract.Requires(environment != null); System.Diagnostics.Contracts.Contract.Requires(token != null); _unloadDomainOnExit = unloadDomainOnExit; _token = token; _addInEnvironment = environment; } // Takes a host add-in view (HAV) and maps that to an add-in controller. [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes")] internal static AddInController GetAddInController(Object addIn) { if (addIn == null) throw new ArgumentNullException("addIn"); System.Diagnostics.Contracts.Contract.EndContractBlock(); AddInControllerImpl controllerImpl = FindController(addIn, false); //return new wrapper if (controllerImpl != null) { // Try and increase the ref count on the addin. If we fail, perhaps // because the user already called Dispose() on the HVA, that's OK. Still allow // them to use the AddInController to examine the AddInToken ContractHandle handle = null; try { handle = new ContractHandle(controllerImpl._contract); } catch (Exception) {} return new AddInController(controllerImpl, addIn, handle); } throw new ArgumentException(Res.ControllerNotFound); } // Find the controller given the HAV (addIn), optionally also removing it. // This code also removes any stale HAVControllerPairs that it finds, as // may happen when a HAV is garbage collected. private static AddInControllerImpl FindController(Object addIn, bool remove) { System.Diagnostics.Contracts.Contract.Requires(addIn != null); lock (_havLock) { HAVControllerPair current = _havList; HAVControllerPair last = null; while(current != null) { Object o = current._HAV.Target; if (o == null) { // this one has been GC'd. Clean up the WR if (last == null) { _havList = current._next; break; } else { last._next = current._next; current = current._next; continue; } } else { if (addIn.Equals(o)) { AddInControllerImpl value = current._controller; if (remove) { if (last == null) _havList = current._next; else last._next = current._next; } return value; } } last = current; current = current._next; } } return null; } // Requires the HAV and the transparent proxy to the add-in adapter, // which implements System.AddIn.Contract.IContract. internal void AssociateWithHostAddinView(Object hostAddinView, IContract contract) { System.Diagnostics.Contracts.Contract.Requires(hostAddinView != null); _contract = contract; // add weak reference on the HAV to our list _havReference = new WeakReference(hostAddinView); lock (_havLock) { HAVControllerPair havRef = new HAVControllerPair(hostAddinView, this); havRef._next = _havList; _havList = havRef; // clean up the list every so often _addInCountSinceLastPrune++; if (_addInCountSinceLastPrune == AddInCountSinceLastPruneLimit) { // searching for a non-exiting addin will have the desired effect // of pruning the list of any stale references. FindController(new Object(), false); _addInCountSinceLastPrune = 0; } } } internal ActivationWorker ActivationWorker { set { System.Diagnostics.Contracts.Contract.Requires(value != null); _activationWorker = value; } } //// [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2103:ReviewImperativeSecurity", Justification = "Reviewed"), System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Reliability", "CA2001:AvoidCallingProblematicMethods", MessageId = "System.Reflection.Assembly.LoadFrom", Justification = "LoadFrom was designed for addins")] [System.Security.SecuritySafeCritical] [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2128:SecurityTransparentCodeShouldNotAssert", Justification = "This is a SecurityRules.Level1 assembly, in which this rule is being incorrectly applied")] internal IContract GetContract() { if (_contract != null) return _contract; // in direct connect, the contract has not been created. Create it now. Object hav = _havReference.Target; if (hav == null) throw new InvalidOperationException(Res.AddInNoLongerAvailable); // 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(_token.PipelineRootDirectory, AddInStore.ContractsDirName))); permissionSet.AddPermission(new FileIOPermission(FileIOPermissionAccess.Read | FileIOPermissionAccess.PathDiscovery, Path.Combine(_token.PipelineRootDirectory, AddInStore.AddInAdaptersDirName))); permissionSet.Assert(); Assembly.LoadFrom(_token._contract.Location); Assembly addinAdapterAssembly = Assembly.LoadFrom(_token._addinAdapter.Location); CodeAccessPermission.RevertAssert(); // Create the AddIn adapter for the addin ActivationWorker worker = new ActivationWorker(_token); _contract = worker.CreateAddInAdapter(hav, addinAdapterAssembly); return _contract; } //// // // [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Reliability", "CA2001:AvoidCallingProblematicMethods", MessageId = "System.GC.Collect", Justification = "Recommended by GC team")] [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)] public void Shutdown() { // Disables usage of the add-in, by breaking the pipeline. // Also, if we own the appdomain, we unload it. lock (this) // Ensure multiple threads racing on Shutdown don't collide. { AddInEnvironment environment = _addInEnvironment; if (environment != null) { try { if (_contract != null) { Object hav = _havReference.Target; IDisposable disposableHAV = hav as IDisposable; if (disposableHAV != null) { try { disposableHAV.Dispose(); } catch (AppDomainUnloadedException e) { Log(e.ToString()); } catch (RemotingException re) { Log(re.ToString()); } catch (SerializationException se) { Log(se.ToString()); } } IDisposable disposableContract = _contract as IDisposable; if (disposableContract != null) { try { disposableContract.Dispose(); } catch (AppDomainUnloadedException e) { Log(e.ToString()); } catch (RemotingException re) { Log(re.ToString()); } catch (SerializationException se) { Log(se.ToString()); } } _contract = null; } if (_activationWorker != null) { // Unhook an assembly resolve event in the target appdomain. // However, if one of the adapters implemented IDisposable and cleaned // up the appropriate lifetime tokens, this appdomain may be unloading // already (we launch another thread to do this, so we are guaranteed // to have a benign race condition). We should catch an // AppDomainUnloadedException here. try { _activationWorker.Dispose(); } catch (AppDomainUnloadedException) { } catch (RemotingException) { } catch (SerializationException) { } _activationWorker = null; } } finally { if (_unloadDomainOnExit) { // AppDomain.Unload will block until we have finalized all // objects within the appdomain. Also, this may already // have been unloaded. try { environment.UnloadAppDomain(); } catch (AppDomainUnloadedException) { } catch (RemotingException) { } // Using the transparent proxy will now cause exceptions, // as managed threads are not allowed to enter this appdomain. } } _addInEnvironment = null; // eagerly remove from list lock (_havLock) { Object addin = _havReference.Target; if (addin != null) FindController(addin, true); } // The perf team recommends doing a GC after a large amount of memory has // been dereferenced. We wait for the finalizers to complete first // becase some references in the addin are not released until finalization. // Also, if an addin is buggy and causes the finalizer thread to hang, // waiting here makes it fail deterministically. System.GC.WaitForPendingFinalizers(); System.GC.Collect(); } // end if domain != null else { throw new InvalidOperationException(Res.AppDomainNull); } } } // This will not be usable for OOP scenarios. internal AppDomain AppDomain { get { if (_addInEnvironment == null) throw new ObjectDisposedException("appdomain"); return _addInEnvironment.AppDomain; } } internal AddInToken Token { get { return _token; } } internal AddInEnvironment AddInEnvironment { get { return _addInEnvironment; } } private static void Log(String message) { Debugger.Log(0, "AddInController", message); } internal sealed class HAVControllerPair { internal WeakReference _HAV; internal AddInControllerImpl _controller; internal HAVControllerPair _next; public HAVControllerPair(Object hav, AddInControllerImpl controller) { _HAV = new WeakReference(hav); _controller = controller; } } } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007.//
Link Menu
This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- ServiceDescriptionImporter.cs
- StyleXamlParser.cs
- ControlTemplate.cs
- versioninfo.cs
- MsmqInputMessage.cs
- ExeConfigurationFileMap.cs
- DecodeHelper.cs
- TableLayout.cs
- StreamGeometryContext.cs
- InkPresenterAutomationPeer.cs
- DataGridViewSortCompareEventArgs.cs
- ObservableDictionary.cs
- InternalTransaction.cs
- PrefixHandle.cs
- BrushValueSerializer.cs
- ZipIOBlockManager.cs
- ExtensibleClassFactory.cs
- SystemFonts.cs
- TraceFilter.cs
- SynthesizerStateChangedEventArgs.cs
- XmlJsonReader.cs
- WebPartDisplayModeEventArgs.cs
- SmtpFailedRecipientException.cs
- ErrorTableItemStyle.cs
- XPathException.cs
- ScrollPattern.cs
- Setter.cs
- HttpHandlersSection.cs
- DataGridViewColumnConverter.cs
- TypeGenericEnumerableViewSchema.cs
- DataControlImageButton.cs
- ShaderEffect.cs
- SimpleType.cs
- ValidationEventArgs.cs
- SqlSelectClauseBuilder.cs
- CompilerCollection.cs
- ImageList.cs
- CorePropertiesFilter.cs
- UnSafeCharBuffer.cs
- PolygonHotSpot.cs
- ProxyWebPartManager.cs
- XamlVector3DCollectionSerializer.cs
- TemplatedWizardStep.cs
- PropertyIDSet.cs
- HyperLinkColumn.cs
- IWorkflowDebuggerService.cs
- WindowsSysHeader.cs
- OleDbConnection.cs
- TdsParser.cs
- FormViewRow.cs
- MimeTypeMapper.cs
- CheckBoxBaseAdapter.cs
- ZipFileInfo.cs
- HtmlTernaryTree.cs
- ErrorFormatter.cs
- ObjectHelper.cs
- AsymmetricSignatureDeformatter.cs
- ToolStripTextBox.cs
- TextMessageEncoder.cs
- WebPartAuthorizationEventArgs.cs
- sqlpipe.cs
- OutputCacheModule.cs
- dataobject.cs
- EvidenceTypeDescriptor.cs
- RawAppCommandInputReport.cs
- ProvidePropertyAttribute.cs
- FontFamily.cs
- HttpResponseHeader.cs
- Transform3DGroup.cs
- GridViewColumnCollectionChangedEventArgs.cs
- HitTestParameters.cs
- AccessorTable.cs
- DocumentPageHost.cs
- ImageMap.cs
- InfoCardRSAOAEPKeyExchangeFormatter.cs
- Misc.cs
- ScrollPattern.cs
- CollectionsUtil.cs
- FileEnumerator.cs
- AssemblyName.cs
- DropShadowEffect.cs
- MaterialGroup.cs
- AttributeTableBuilder.cs
- XmlSchemaAll.cs
- Resources.Designer.cs
- DataRelationCollection.cs
- TreeViewItem.cs
- Expr.cs
- XmlQueryTypeFactory.cs
- ListControl.cs
- DataGridColumnStyleMappingNameEditor.cs
- InstanceDescriptor.cs
- DataObjectEventArgs.cs
- ToolStripItem.cs
- XmlUtil.cs
- Function.cs
- Utils.cs
- StorageEntityTypeMapping.cs
- SafeReversePInvokeHandle.cs
- FileLogRecordEnumerator.cs