Change button/Group caption in all supported applications

Add-in Express™ Support Service
That's what is more important than anything else

Change button/Group caption in all supported applications
When caption changes in active application, i'd like it to also change in the other supported application 
Androulla Pavlou




Posts: 21
Joined: 2016-05-25
My apologies if this is a repeated question.

Some background, but perhaps not relevant: I have previously created a VB app using ADX. It runs well and my client has been happy for two years. I am now attempting to fix another client's application. It was originally C# written in VSTO. To ease my deployment dilemma, I am moving the original code to ADX and learning as I go. It is still in c#.

But the basic issue is this: The add-in runs for Excel, Word and Outlook. After the user clicks the ribbon Login button and is successfully logged in, the caption should change to "Logout". And because they are logged in for all applications, ideally I'd like the caption to change in all three applications (if they are running).

I've written to code to change the caption in the active application, but it does not change the caption in the other applications.

As I write it I do wonder if I'm missing a basic concept? That you cannot access the other hosted applications from within one of the applications? And as I think on it further, it's not just the caption I need changed in all applications, but I want them all to be "aware" that the user is logged in.

So, to distill this down into a more fundamental question: when multiple applications are using the same ADX add-in, can they manipulate each other? Or is it really that each is working with its own instance of the add-in and therefore they are unaware of each other? If that is the case, is there a way around this? Again, ideally, if the user logs in using one application, I'd like them to be logged in for all supported applications. The login process is authenticating on a web server.

Thanks in advance.

Tim Jeffryes
TJs Tools LLC
Posted 26 Jan, 2021 08:21:29 Top
Andrei Smolin


Add-in Express team


Posts: 18821
Joined: 2006-05-11
Hello Tim,

You can access your COM add-in via the following code path:

ExcelApp.COMAddins.Item(strMyComAddinProgId).Object.MyPublicPropertyOrMethod.

1. strMyComAddinProgId - see the ProgId attribute of your add-in module.
2. MyPublicPropertyOrMethod is called via late binding (see System.Type.InvokeMember in MSDN or search through our forums)

See also http://www.add-in-express.com/creating-addins-blog/2010/07/02/standalone-application-addin-communicate/.

That is, if another host application(s) is running, your add-in can get the corresponding Application object and invoke a public method or property declared on the add-in module.


Andrei Smolin
Add-in Express Team Leader
Posted 27 Jan, 2021 04:19:11 Top
Androulla Pavlou




Posts: 21
Joined: 2016-05-25
Thank you very much! You have set me on the right path!

Tim Jeffryes
TJs Tools LLC
Posted 27 Jan, 2021 20:09:27 Top
Andrei Smolin


Add-in Express team


Posts: 18821
Joined: 2006-05-11
Welcome!


Andrei Smolin
Add-in Express Team Leader
Posted 28 Jan, 2021 02:20:07 Top
Androulla Pavlou




Posts: 21
Joined: 2016-05-25
Andrei:

I just want to double check:

This line:
ExcelApp.COMAddins.Item(strMyComAddinProgId).Object.MyPublicPropertyOrMethod


Should it perhaps be:

ExcelApp.COMAddins.Item(strMyComAddinProgId).Object("MyPublicPropertyOrMethod")???

Tim Jeffryes
Posted 28 Jan, 2021 16:10:08 Top
Andrei Smolin


Add-in Express team


Posts: 18821
Joined: 2006-05-11
Hello Tim,

No.

MyPublicPropertyOrMethod is called via late binding (see System.Type.InvokeMember in MSDN or search through our forums).

VB.NET
COMAddins.Item(strMyComAddinProgId)

C#
COMAddins[strMyComAddinProgId]

This one returns an Office.COMAddin object representing your COM add-in. You use it e.g. to check whether your add-in is connected or not.

Office.COMAddin.Object returns an object allowing accessing the public properties/methods of your add-in module.


Andrei Smolin
Add-in Express Team Leader
Posted 29 Jan, 2021 02:21:18 Top
Androulla Pavlou




Posts: 21
Joined: 2016-05-25
Andrei:

Thanks for your response. Before I heard back from you, I did review the article you referenced and I tried it. I am pretty much a newbie at C#, so it took me a while to translate. From that article, here is my translated version of GetAddinObject:

private Object GetAddinObject()
        {
            Excel._Application app = null;
            try
            { app = (Excel._Application)(Marshal.GetActiveObject("Excel.Application")); }
            catch (Exception ex)
            {
                MessageBox.Show("Excel is not running.");
                return ex.Message;
            }

            if (!(app is null))
            {
                try
                {
                    Office.COMAddIns addins = app.COMAddIns;
                    if (!(addins is null))
                    {
                        try
                        {
                            //                    ' ProgID of our add-in
                            Object index = "EdgeOfficeAddin.AddinModule";
                            Office.COMAddIn addin = null;
                            try
                            {
                                addin = addins.Item(index);
                            }
                            catch
                            {
                                MessageBox.Show("COM add-in is not registered.");
                            }
                            if (!(addin is null))
                            {
                                try
                                {
                                    if (addin.Connect)
                                    { return addin.Object; }
                                    else
                                    { MessageBox.Show("COM add-in is not enabled."); }
                                }
                                finally
                                {
                                    Marshal.ReleaseComObject(addin);
                                }

                            }
                        }
                        finally
                        {
                            Marshal.ReleaseComObject(addins);
                        }
                    }
                }
                finally
                {
                    Marshal.ReleaseComObject(app);
                }

            }
            return app;
        }


Then the other routine from the article I translated as such:

        public void SetButtonLabel()
        {
            Object addinInstance = GetAddinObject();
            if (!(addinInstance is null))
            {
                try
                {
                    Object value = addinInstance.GetType().InvokeMember("chicken", BindingFlags.InvokeMethod,null,addinInstance,new Object [44]);
                    addinInstance.GetType().InvokeMember("chicken", BindingFlags.InvokeMethod, null, addinInstance, new Object[1]);
                }
                catch (Exception ex)
                {
                    MessageBox.Show(ex.Message);
                }
            }
        }

Note that I have two lines using InvokeMember: one returns a value and the other does not.

Thankfully up to this point I get NO ERRORS, so much of it is working. The problem now is that chicken() doesn't run.

public void chicken()
        {
            MessageBox.Show("chicken");
        }


chicken() is in AddInModule.cs

I wasn't sure how to pass the new Object parameter.

Thank you.

Tim
Posted 29 Jan, 2021 20:10:34 Top
Andrei Smolin


Add-in Express team


Posts: 18821
Joined: 2006-05-11
Hello Tim,

You can use a free VB.NET to C# translator available online.

if (!(app is null)) --> if (app != null)

The last parameter of the InvokeMember() method allows supplying parameters to the callee:
- if the callee has no parameters, you pass null (Nothing in VB.NET)
- if the callee has several parameters, the last parameter of the InvokeMember() call is an array of an object type which you initialize as described in https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/arrays/single-dimensional-arrays#array-initialization.

In your case the callee has no parameters.


Andrei Smolin
Add-in Express Team Leader
Posted 01 Feb, 2021 04:23:07 Top
Androulla Pavlou




Posts: 21
Joined: 2016-05-25
Andrei:

That worked! Thank you so much!

Tim
Posted 01 Feb, 2021 08:17:03 Top
Androulla Pavlou




Posts: 21
Joined: 2016-05-25
Andrei:

Are the values in the array in the last parameter of InvokeMember() passed by reference? Can I get their return values?

Tim Jeffryes
TJs Tools LLC
Posted 01 Feb, 2021 08:32:37 Top