9
votes

I am trying to develop a VSTO 2010 Word Addin. It has a custom task pane with a countdown timer (user control) in it. Idea is that when a word document is opened total time (in hours and minutes) is passed to the Addin which in turn passes it to the countdown timer control. When i run the addin in VS2010 and pass the user control two integers values i.e. hours and minutes in the Addin_Startup it works fine.

Now i am trying to open a word document on button click from an asp.net page. When i click the button a word document should open and time in hours and minutes should be passed to the addin which will then give it to the user control and the timer should run for the given time.

Problem is i cant figure out how to pass two integers to the addin and where to pass them. Following is my code which sometimes give "Catastrophic failure error" and other times it gives me "Unable to cast COM object of type 'System.__ComObject' to interface type 'MyWordAddin.IAddInUtilities'"

ThisAddin Class

namespace MyWordAddin
{
    public partial class ThisAddIn
    {
        private ctlClock myUserControl;
        private Microsoft.Office.Tools.CustomTaskPane myCustomTaskPane;
        private int hour, min;
        private AddInUtilities utilities;

        protected override object RequestComAddInAutomationService()
        {
            if (utilities == null)
            {
                utilities = new AddInUtilities();
            }
            return utilities;
        }

        public int Min
        {
            get { return min; }
            set { min = value; }
        }

        public int Hour
        {
            get { return hour; }
            set { hour = value; }
        }


        public Microsoft.Office.Tools.CustomTaskPane MyCustomTaskPane
        {
            get { return myCustomTaskPane; }
            set { myCustomTaskPane = value; }
        }

        public void ThisAddIn_Startup(object sender, System.EventArgs e)
        {
            //MessageBox.Show("Start Up Called");
            myCustomTaskPane.VisibleChanged += new EventHandler(myCustomTaskPane_VisibleChanged);

        }
        public void setTime(int h, int m)
        {
            Hour = h;
            Min = m;
            myUserControl = new ctlClock(Hour, Min);
            //myUserControl = new ctlClock(0, 1);
            myCustomTaskPane = this.CustomTaskPanes.Add(myUserControl, "Remaining Time");
            myCustomTaskPane.Visible = true;
        }

        private void yCustomTaskPane_VisibleChanged(object sender, System.EventArgs e)
        {
            Globals.Ribbons.ManageTaskPaneRibbon.toggleButton1.Checked = myCustomTaskPane.Visible;
        }

        private void ThisAddIn_Shutdown(object sender, System.EventArgs e)
        {
        }

AddinUtilities class

namespace MyWordAddin
{
    [ComVisible(true)]
    [InterfaceType(ComInterfaceType.InterfaceIsDual)]
    public interface IAddInUtilities
    {
        void setAddinTime(int h, int min);
    }

    [ComVisible(true)]
    //[Serializable()]
    [ClassInterface(ClassInterfaceType.None)]
    public class AddInUtilities : StandardOleMarshalObject,IAddInUtilities
    {
        public void setAddinTime(int hour, int min)
        {
            Globals.ThisAddIn.setTime(hour, min);          

        }

   }


}

Controller Application which tries to open word document and send two integers to the addin

namespace ControllerApplication
{
    public class CCWordApp
    {
        private Word._Application oWordApp; // a reference to Word application

        public Word._Application OWordApp
        {
            get { return oWordApp; }
            set { oWordApp = value; }
        }
        private Word.Document oWordDoc;     // a reference to the document

        public Word.Document OWordDoc
        {
            get { return oWordDoc; }
            set { oWordDoc = value; }
        }

        public CCWordApp()
        {
            // activate the interface with the COM object of Microsoft Word
            oWordApp = new Word.Application();
            oWordDoc = new Word.Document();


        }

        // Open a new document
        public void Open()
        {
                object addinName = "MyWordAddIn";
                Microsoft.Office.Core.COMAddIn addin = oWordApp.COMAddIns.Item(addinName);
                IAddInUtilities utils = null;
                    utils = (IAddInUtilities)addin.Object;
                    utils.setAddinTime(0, 8);


            Object oMissing = System.Reflection.Missing.Value;
            oWordApp.Visible = true;
            oWordDoc = oWordApp.Documents.Add(ref oMissing, ref oMissing, ref oMissing, ref oMissing);
            oWordDoc.Activate();
        }

When i run the controller application, upon click event of start button it some times give me "Catastrophic failure" other times it gives me "Unable to cast COM object of type 'System.__ComObject' to interface type 'MyWordAddin.IAddInUtilities'" and sometimes it stucks on the last line of code saying "An object instance not passed to and object". I have bold selected the code where error arises. I cant figure out what really is the problem here and why i cant pass two simple integers to my addin. There sure be something i am doing in a very wrong manner. Please guide me.

1
...bold selected the code where error arises Where is the error? I don't see the bold selection.SliverNinja - MSFT
Error arises in controller application's open function @ the following lines utils = (IAddInUtilities)addin.Object; utils.setAddinTime(0, 8);user1770669
What type of object is addin.Object? Try using GetCOMObjectType using the IDispatch interface to reflect on the COM instance. Can you set a breakpoint to see if RequestComAddInAutomationService is ever hit?SliverNinja - MSFT
Have you tried declaring IAddInUtilities with ComInterfaceType.InterfaceIsIUnknown?Richard Cook

1 Answers

0
votes

I think you need to override the RequestCOMAddInAutomationService because you are using VSTO.

See this article: How to call the Add-In functions from an external application?

Shared Add-In uses the COMAddIn.Object manner to expose its functions to the external applications, so our implementation of OnConnection will roughly look like this:

((COMAddIn)AddInInst).Object = new MyAutomationObject();

However this method cannot be used in VSTO because setting COMAddIn.Object is only permitted during OnConnection function and the OnConnection is not visible in VSTO project.

It gives an example of overriding the RequestCOMAddInAutomationService()

Hope that helps!