Shutdown Addin

Latest post 04-02-2008 2:23 PM by Gary. 6 replies.
  • 03-21-2008 5:38 PM

    Shutdown Addin

    I would like to gracefully unload my VSTA addin. I have tried something as simple as below, but an assembly reference still exists until I close the application. How can I achieve this result?

     

    foreach (IEntryPoint entry in this.addInList)

    {

          entry.OnShutdown();

    }

    this.addInList.Clear();

     

  • 03-24-2008 10:38 AM In reply to

    • Gary
    • Top 10 Contributor
    • Joined on 07-13-2006
    • Posts 320

    Re: Shutdown Addin

    Try something like this snippet.  (probably 'controller.Shutdown();' is the bit you need)

     

     

            internal void UnloadAddIn(String name, bool skipOnShutdown)

            {

                System.Diagnostics.Debug.WriteLine("==================>Unload Addin: " + name + (skipOnShutdown ? "  [skip OnShutdown]" : ""));

     

                int index = 0;

                for(index = 0; index < this.addInInfoList.Count; index++)

                {

                    if (name.Equals(addInInfoList[index].token.AssemblyName.Name, StringComparison.CurrentCultureIgnoreCase))

                    {

                        if (!skipOnShutdown)

                        {

                            try

                            {

                                addInInfoList[index].entryPoint.OnShutdown();

                            }

                            catch (Exception ex)

                            {

                                System.Diagnostics.Debug.WriteLine(ex.ToString());

                            }

                        }

                        //Deterministic AddIn shutdown/release

                        AddInController controller = AddInController.GetAddInController(addInInfoList[index].entryPoint);

                        controller.Shutdown();

     

                        //release addin

                        AddInInfo ai = addInInfoList[index];

                        this.addInInfoList.RemoveAt(index);

                        ai.entryPoint = null;

                        ai.token = null;

     

                        break;

                    }

                }

                  

            }

     

    where struct looks like this

            //private List<IEntryPoint> addInList;

            public struct AddInInfo

            {

                public IEntryPoint entryPoint;

                public AddInToken token;

                public AddInInfo(IEntryPoint entryPt, AddInToken tok)

                {

                    entryPoint = entryPt;

                    token = tok;

                }

            }

            private List<AddInInfo> addInInfoList;

     

  • 03-24-2008 11:07 AM In reply to

    • Gary
    • Top 10 Contributor
    • Joined on 07-13-2006
    • Posts 320

    Re: Shutdown Addin

    Also, if you include loading the addin project and supporting out-of process debugging, there are some more issues with add-in loading and unloading.
  • 03-28-2008 6:33 PM In reply to

    Re: Shutdown Addin

    After unloading the AddIn (similar to above), reloading, and attempting to call a method in the AddIn I receive the following the exception:

     

    Server Error in '/ddmwinfx20' Application.

    Attempted to access an unloaded AppDomain.

    Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.

    Exception Details: System.AppDomainUnloadedException: Attempted to access an unloaded AppDomain.

    Source Error:

    Line 97:         {
    Line 98:             DocumentManager.PDF.VSTAAddInCreateFDF vstaScript = new DocumentManager.PDF.VSTAAddInCreateFDF(this._doc, draw, ScriptBase.Mode.BuildPDF, readOnly);
    Line 99:             entry.CreateFDFEvent(vstaScript);
    Line 100:            vstaScript.Close();
    Line 101:            vstaScript.WriteHttpResponse(response);

    Source File: D:\development projects\ddm-winfx-3.5\src\DocumentManager\VSTA\VSTADocumentFieldMapper.cs    Line: 99

    Stack Trace:

    [AppDomainUnloadedException: Attempted to access an unloaded AppDomain.]
       Microsoft.VisualStudio.Tools.Applications.ExceptionFilterHelper.DynamicInvoke(IExceptionManager mgr, IExceptionNotificationObject exceptionNotificationObject, IRemoteDelegateContract delegateContract, IRemoteArgumentArrayContract remoteArgs, TypeInfrastructureManager typeInfrastructureManager) +119
       Microsoft.VisualStudio.Tools.Applications.DelegateProxy.InvokeDelegate_V_Return(A0 a0) +592
       Microsoft.VisualStudio.Tools.Applications.DelegateProxy.InvokeDelegate_V_NoReturn(A0 a0) +47
       DocumentManager.VSTA.VSTADocumentFieldMapper.ExecuteReadMappingScript(Draw draw, Boolean readOnly, HttpResponse response) in D:\development projects\ddm-winfx-3.5\src\DocumentManager\VSTA\VSTADocumentFieldMapper.cs:99
       DocumentManager.PDF.ManageFDF.BuildFDF(HttpResponse response) in D:\development projects\ddm-winfx-3.5\src\DocumentManager\PDF\CreateDocumentFDF.cs:61
       Trade.docs.FDF.Page_Load(Object sender, EventArgs e) in D:\development projects\ddm-winfx-3.5\src\TradeWeb\docs\FDF.aspx.cs:76
       System.Web.UI.Control.OnLoad(EventArgs e) +99
       System.Web.UI.Control.LoadRecursive() +47
       System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint) +1436
    

  • 03-31-2008 11:27 AM In reply to

    • Gary
    • Top 10 Contributor
    • Joined on 07-13-2006
    • Posts 320

    Re: Shutdown Addin

    Would providing simple C# sample loop that [loads, calls macro,  unloads] be helpful?

    Or can you provide a similar repro sample for us?

  • 04-01-2008 11:26 AM In reply to

    Re: Shutdown Addin

    I would like to provide a code example, but creating the sample will take some time.

     

    Any pointers on where to look to solve this problem?

  • 04-02-2008 2:23 PM In reply to

    • Gary
    • Top 10 Contributor
    • Joined on 07-13-2006
    • Posts 320

    ANS Re: Shutdown Addin

    Here is the Unload and Load code for single assembly -- adapted for ShapeApp basic integration sample.

     

            internal void UnloadAddIn(String name, bool skipOnShutdown)

            {

                System.Diagnostics.Debug.WriteLine("==================>Unload Addin: " + name + (skipOnShutdown ? "  [skip OnShutdown]" : ""));

     

                int index = 0;

                for(index = 0; index < this.addInInfoList.Count; index++)

                {

                    if (name.Equals(addInInfoList[index].token.AssemblyName.Name, StringComparison.CurrentCultureIgnoreCase))

                    {

                        if (!skipOnShutdown)

                        {

                            try

                            {

                                addInInfoList[index].entryPoint.OnShutdown();

                            }

                            catch (Exception ex)

                            {

                                System.Diagnostics.Debug.WriteLine(ex.ToString());

                            }

                        }

                        //Deterministic AddIn shutdown/release

                        AddInController controller = AddInController.GetAddInController(addInInfoList[index].entryPoint);

                        controller.Shutdown();

     

                        //release addin

                        AddInInfo ai = addInInfoList[index];

                        this.addInInfoList.RemoveAt(index);

                        ai.entryPoint = null;

                        ai.token = null;

     

                        break;

                    }

                }

                  

            }

     

            /// <summary>

            /// Loads the add in.

            /// </summary>

            /// <param name="name">The name of the AddIn to load.</param>

            /// <param name="container">The <see cref="ServiceContainer"/> to load the AddIn with.</param>

            /// <returns><c>true</c> if the AddIn is loaded successfully; <c>false</c> otherwise.</returns>

            internal bool LoadAddIn(String name, AddInProcess addInProcess)

            {

                //The AddIn should be in a .dll file having the same short

                //name as the directory it's in.

                String dllPath = System.IO.Path.Combine(System.IO.Path.Combine(CorelApplicationIntegration.AddInPath, name), name + ".dll");

     

                //If the directory does not contain that file, skip it.

                if (!System.IO.File.Exists(dllPath))

                    return false;

     

                //Create the AddInToken.

                Collection<AddInToken> addinToken = AddInStore.FindAddIn(typeof(IEntryPoint), AddInStoreExtensions.DefaultPipelinePath, dllPath, name + "." + StartUpClass);

     

                //Assert the AddIn is valid.

                System.Diagnostics.Debug.Assert(addinToken.Count >= 1);

     

                //If the AddIn is not valid return false.

                if (addinToken.Count == 0)

                    return false;

     

                // Using the Token returned above, load the AddIn. This will create an

                // instance of AddIn EntryPoint class to activate the AddIn.

                IEntryPoint addIn;

                if (addInProcess == null)

                {

                    System.Diagnostics.Debug.WriteLine("LoadAddIn In-Process");

     

                    // Load the AddIn in the same process as the host.

                    addIn = addinToken[0].Activate<IEntryPoint>(AddInSecurityLevel.FullTrust);

                }

                else

                {

                    System.Diagnostics.Debug.WriteLine("==================>LoadAddIn Ex-Process<=================");

                    // Load the AddIn in external process.

                    addIn = addinToken[0].Activate<IEntryPoint>(addInProcess, AddInSecurityLevel.FullTrust);

                }

     

                // Initialize AddIn by calling into functions of the AddIn EntryPoint instance.

                addIn.Initialize(this.serviceContainer);

                addIn.InitializeDataBindings();

                addIn.FinishInitialization();

     

                //Store that AddIn to stop it later.

                AddInInfo ai = new AddInInfo(addIn, addinToken[0]);

                this.addInInfoList.Add(ai);

     

     

                //The AddIn was loaded so return true.

                return true;

            }

     

            public struct AddInInfo

            {

                public IEntryPoint entryPoint;

                public AddInToken token;

                public AddInInfo(IEntryPoint entryPt, AddInToken tok)

                {

                    entryPoint = entryPt;

                    token = tok;

                }

            }

            private List<AddInInfo> addInInfoList;

     

     

Page 1 of 1 (7 items) | RSS
Copyright Summit Software Company, 2008. All rights reserved.