views:

42

answers:

2

I've created a toolbar button in OneNote like Daniel Escapa showed. Usually, it works, but sometimes OneNote decides to grey out the toolbar button, making it impossible to click. I can't figure out what state is causing this. How can I prevent this?

I'm careful to return true from the OnEvent and OnClick handlers, but maybe there's a special case that is causing it to return false? Here is my code:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using OneNoteAddin;
using System.Runtime.InteropServices;
using Microsoft.Win32;
using System.IO;
using OneNote = Microsoft.Office.Interop.OneNote;

namespace NoteTakerPlugin
{

    [Guid("792d0410-d53c-402d-92c9-5db9ea29f644")]
    public class NoteTakerButton : IOneNoteAddIn 
    {
        // for sending messages to window handles
        private struct COPYDATASTRUCT
        {
            public IntPtr dwData;
            public int cbData;
            [MarshalAs(UnmanagedType.LPStr)]
            public string lpData;
        }

        // this should be hardcoded in the note taker application
        private const string NoteTakerAppClassName = "CubicNoteTaker-792d0410-d53c-402d-92c9-5db9ea29f644::EventReceiver";

        private const int WM_COPYDATA = 0x4A;

        [DllImport("user32.dll", EntryPoint = "FindWindow", SetLastError = true)]
        static extern IntPtr FindWindowByCaption(IntPtr ZeroOnly, string lpWindowName);

        [DllImport("User32.dll", EntryPoint = "SendMessage")]
        private static extern int SendMessage(IntPtr hWnd, int Msg, int wParam, ref COPYDATASTRUCT lParam);

        IntPtr app;

        public NoteTakerButton()
        {
            tellAppSomething("{ \"appStart\": true }", false);
        }

        public bool OnClick([In] String strActivePageID)
        {
            // send the click event to the note taker app
            tellAppSomething("{ \"click\": { \"pageId\": \"" + strActivePageID + "\" }}", true);
            return true;
        }

        public bool OnEvent([In] OneNote.OneNoteAddIn_Event evt, [In] String strParameter)
        {
            // send the event to the note taker app
            tellAppSomething("{ \"event\": { \"id\": " + (int)evt + ", \"param\": \"" + strParameter + "\" }}", false);
            return true;
        }

        private void tellAppSomething(String message, bool startProgram)
        {
            // if the process is running
            refreshAppStatus();
            if( app != IntPtr.Zero  )
            {
                // send a window message to the process telling it the message
                sendMessageTo(app, message);
            }
            else if( startProgram )
            {
                // start the process with a command line telling it the message
                startApp(message);
            }
        }

        private void refreshAppStatus()
        {
            app = FindWindowByCaption(IntPtr.Zero, NoteTakerAppClassName);
        }

        private void sendMessageTo(IntPtr hWnd, String msg)
        {
            int wParam = 0;
            int result = 0;

            if (hWnd != IntPtr.Zero )
            {
                byte[] sarr = System.Text.Encoding.Default.GetBytes(msg);
                int len = sarr.Length;
                COPYDATASTRUCT cds;
                cds.dwData = IntPtr.Zero;
                cds.lpData = msg;
                cds.cbData = len + 1;
                result = SendMessage(hWnd, WM_COPYDATA, wParam, ref cds);
            }
        }

        private void startApp(String args)
        {
            string exe = getAppExe();
            if (File.Exists(exe))
            {
                System.Diagnostics.Process.Start(exe, args);
            }
            else
            {
                System.Windows.Forms.MessageBox.Show("You need to reinstall the Note Taker application. The installation is corrupted.");
            }
        }

        private string getAppExe()
        {
            // use the registry to find where the application is installed
            RegistryKey noteTakerKey = Registry.LocalMachine.OpenSubKey("SOFTWARE\\NoteTaker");
            String path = noteTakerKey.GetValue("Path","").ToString();
            String exe = noteTakerKey.GetValue("Exe", "").ToString();

            if (!Directory.Exists(path))
                return "";

            String combo = Path.Combine(path, exe);

            if( File.Exists(combo) )
                return combo;
            else // not installed
                return ""; 
        }
    }
}
A: 

EDIT: I remember this issue, now! When you close OneNote, check if an instance of it is still running in taskman, I think this sort of locks the addon in future instances and grays them out, make sure you dont have any code left running that would be causing the instance to stay alive.

kyndigs
Thanks for the tip. I'll double check this, but I'm pretty sure I killed all instances of both OneNote and my application before restarting OneNote to find that it was still grayed out. But I believe rebooting may have been a quick fix, so you may be on to something.
superjoe30
I dont remember exactly what caused it for me, it was either privacy settings or the instance was not closing properly, your problem may be totally different though. You may also look at Disposing some of the stuff like the IntPtr which may contribute to the application locking up.
kyndigs
A: 

In my project properties Build tab, I had forgotten to check "Register for COM interop" in Release mode. This caused intermittent errors.

superjoe30