As with other Microsoft Office applications, you can also create add-ins for OneNote. In OneNote 2007 you wrote add-ins by implementing IOneNoteAddin (see Daniel Escapa’s tutorial – http://blogs.msdn.com/b/descapa/archive/2006/08/31/734298.aspx) and they integrated well with OneNote’s UI, being toolbar based add-ins in a toolbar based UI. With OneNote 2010′s ribbon, however, these ‘toolbar based’ add-ins only show up on a separate Add-Ins tab, and even then only appearing as small icons. Integrating these add-ins with the ribbon / fluent UI is what we want for OneNote 2010, to properly ‘integrate’ them with the UI.

Like this (a custom button in a custom tab in the ribbon):
Add-in in Ribbon

This is a tutorial / guide on how to do this.

Rather not view this in a web browser? Ok, here’s the pdf and xps documents of this tutorial

This has been tested with Visual Studio 2008 Professional and Visual Studio 2010 Professional.


Part 1 – Creating the project

Whereas the “common” (not that OneNote isn’t) office programs, like Word, PowerPoint, Outlook, and Excel, all have VSTO (Visual Studio Tools for Office) templates, making it really easy to create add-ins for those programs. OneNote does not, but it does share a very similar add-in architecture.

  1. Open Visual Studio as Administrator (so that Visual Studio can register your add-in with COM Interop)
  2. New Project → [Your Language of Choice] → Windows → Class Library


    For this tutorial we will choose .NET 3.5 and C#, but you can choose what you want

  3. First up we need to make the application COM-Visible

    1. Right-Click on the Project → Properties
    2. Application tab → Assembly Information
    3. Select ‘Make assembly COM-Visible’. This makes the class library / .dll generated by the project visible to OneNote.
    4. Click OK
    5. Build tab → Register for COM Interop. This gets Visual Studio to automatically register the application for COM Interop when it’s built.
  4. To make debugging and building the project easier, we will change the AssemblyVersion attribute to automatically increment. This way, we won’t have to always update this attribute each time we want to update your application

    1. Open: Properties → AssemblyInfo.cs
    2. Change the following:
      [assembly: AssemblyVersion("1.0.0.0")]
      [assembly: AssemblyFileVersion("1.0.0.0")]

      to:
      [assembly: AssemblyVersion("1.0.*")]
      [assembly: AssemblyFileVersion("1.0.*")]

Part 2 – Creating the Ribbon

The Fluent UI or Ribbon in Microsoft Office (the ‘new interface’) was launched with Office 2007 with the ‘common’ programs (again, not that OneNote isn’t) first – Word, PowerPoint, and Excel. In 2010 it came to the others, OneNote, Outlook, etc. Since the Fluent UI is controlled by an XML file, extending it (at least visually) is quite easy. So, our second step is to create an XML file that will contain this code to extend the ribbon:

  1. Add a XML file to the Add-In Project (Right Click → Add → Add New Item → Data → XML File). Call it something like ribbon.xml

  2. To make this XML file readable by our add-in during runtime we will make it a resource (so that it is embedded in the .dll created).
    1. Right Click on the Project → Properties → Resources → ‘Click here to create one’

    2. Next, just Click-and-drag ribbon.xml into the Resources box

  3. MSDN has a great introduction to XML and the Ribbon. See: http://msdn.microsoft.com/en-us/library/aa338202.aspx Basically, we need a Tab (our own or an already existing one) to place our Group – a collection of controls – filled with our controls.
  4. The XML document to customize the ribbon starts with:

    <?xml version="1.0" encoding="utf-8" ?>
    <customUI xmlns="http://schemas.microsoft.com/office/2006/01/customui">
     <ribbon>
      <tabs>
       <!-- Our content goes here… -->
      </tabs>
     </ribbon>
    </customUI>

  5. In order to display images in the ribbon, they need to be parsed in a special way. We will do this later on in this guide, but we need to set-up the function so that we can do this. Just add the following attribute to the <CustomUI> element:

    loadImage="GetImage"
    so that it looks like this:
    <customUI xmlns="http://schemas.microsoft.com/office/2006/01/customui" loadImage="GetImage">
     ...
    </customUI>

  6. In the ribbon, the first thing that we need is a tab. Either we can hook into an existing tab or we can create our own. For this demo we will create our own tab. If you want to extend an already existent tab, check out the Control IDs (http://www.microsoft.com/downloads/en/details.aspx?FamilyID=3f2fe784-610e-4bf1-8143-41e481993ac6 ). Just replace id="" with the idMso="[the control id]" (without square brackets).

    All that a tab needs is an id and a label:

    <tab id="tabCustom" label="Custom">
    </tab>

  7. Next we need a group in which to place our controls. Again this can be our own group or an already existing one. For this demo we will create our own Group. Again, all it needs is an id and a label:

    <group id="groupHello" label="Hello">
    </group>

  8. In this group we place our controls – for example Buttons, Menus, Checkboxes, etc. For this demo we will just add a simple button. Again it needs an id and a label, but we will also change (the next ones are optional) its size to large (for a big button), and add a tooltip. Also, we need to give it the path to the image and we need to give it an onAction function (basically the OnClick() event):

    <button id="buttonHello" label="Hello World!" size="large" screentip="Press this for a 'Hello World!' message" onAction="showHello" image="HelloWorld.png" />

  9. This is what it should look like now (like this):

    <?xml version="1.0" encoding="utf-8" ?>
    <customUI xmlns="http://schemas.microsoft.com/office/2006/01/customui" loadImage="GetImage">
     <ribbon>
      <tabs>
       <tab id="tabCustom" label="Custom">
        <group id="groupHello" label="Hello">
         <button id="buttonHello" label="Hello World!" size="large" screentip="Press this for a 'Hello World' message" onAction="showHello" image="HelloWorld.png"/>
        </group>
       </tab>
      </tabs>
     </ribbon>
    </customUI>


Part 3 – Writing some code

With the ribbon done, next up we need to hook up the ribbon's events, and get
our add-in to do something.

  1. Go to Class1.cs (you can rename it if you want, just be certain that if you change the class name public class [classname]), you update the ProgId as well)
  2. Add a reference (Right-Click on References → Add Reference…)

    to the following:

    Tab Name
    .NET
    Extensibility (note the capital E) (for the COM Add-In code)
    .NET System.Windows.Forms (for a MessageBox)
    .NET System.Drawing (for putting Images into the ribbon)
    COM Microsoft OneNote 14.0 Object (Type for VS2008) Library (for the OneNote API)
    COM Microsoft Office 14.0 Object Library (for Ribbon Extensibility)

    If you are using .NET 4 / VS 2010 be sure to turn off ‘Embed Interop Types’ for Microsoft OneNote 14.0 Object Library. See Daniel Escapa’s post on how and why: blogs.msdn.com/b/descapa

  3. Add a using to the top of Class1.cs, among the other ‘usings’:

    using System.Runtime.InteropServices;

  4. Next, the Add-In requires a GUID to identify it. To create one:

    1. Tools → Create GUID (if it isn’t there, do a search in the start-menu for GUID)
    2. Choose Registry Format → Copy → Exit
  5. Just above:
    public class Class1
    add:
    [GuidAttribute("[Your app’s Guid]"),ProgId("[Your app’s ProgId]")]
    [Your app’s Guid] = <paste> (without curly braces) the one created in Step 4
    [Your app’s ProgId] = Project.ClassName

    Ensure that you have these values on hand (i.e. copied into Notepad, or even better OneNote) as they are needed for the setup project (later).

  6. Add a using to the top of Class1.cs, among the other ‘usings’:

    using Extensibility;

  7. This will allow us to implement IDTExtensibility2 (it contains all the COM Add-in functions), so that our code now looks like this:

    public class Class1 : IDTExtensibility2
    { }

  8. Right-Click on IDTExtensibility2 (in the code (above) that we just added) → Implement Interface → Implement Interface. This will generate all the method stubs that the Add-In encounters during runtime
  9. So now there are a whole heap of stub methods with the code:

    throw new NotImplementedException();
    This needs to be removed; otherwise, when these methods are encountered during runtime, the application will exist because of these exceptions being thrown.

    So delete them, that only the methods remain:
    public void OnAddInsUpdate(ref Array custom) { }
    public void OnBeginShutdown(ref Array custom) { }
    public void OnConnection(object Application, ext_ConnectMode ConnectMode, object AddInInst, ref Array custom) { }
    public void OnDisconnection(ext_DisconnectMode RemoveMode, ref Array custom) { }
    public void OnStartupComplete(ref Array custom) { }

  10. Add a using to the top of Class1.cs, among the other ‘usings’:

    using Microsoft.Office.Interop.OneNote;

  11. The OnConnection() function is called when the Add-In is being loaded. Here OneNote passes in the current instance of the ApplicationClass, the programmatic interface to OneNote’s API, so we set a new class-wide variable, onApp,
    to equal it.

    ApplicationClass onApp = new ApplicationClass();
    public void OnConnection(object application, ext_ConnectMode connectMode, object addInInst, ref System.Array custom)
    {
     onApp = (ApplicationClass)application;
    }

  12. To hook the ribbon’s events to our code we need to add:

    using Microsoft.Office.Core;

  13. This will allow us to implement IRibbonExtensibility (it contains all the Ribbon functions), so that our code now looks like this:

    public class Class1 : IDTExtensibility2, IRibbonExtensibility
    {
     /* Code here… */
    }

  14. Right-Click on IRibbonExtensibility (in the code above that we just added) → Implement Interface → Implement Interface. This will create a stub of the Ribbon’s load event for us.

  15. Replace the code:

    public string GetCustomUI(string RibbonID)
    {
     throw new NotImplementedException();
    }

    With returning the XML Resource (the ribbon.xml file) that we created in Step 2

    public string GetCustomUI(string RibbonID)
    {
     return Properties.Resources.ribbon;
    }

  16. Now to make the button work we create a function with the same name that we mentioned in the ribbon.xml for our button’s onAction event. It is important that this function is both public and takes an IRibbonControl as a parameter:

    public void showHello(IRibbonControl control)
    {
    }

  17. This is the part where you can do what you want with your own code. This function will be called when the (in our case) button is pressed. For this demo, we will just make it show a Messagebox with the current page’s ID.
  1. First add:

    using System.Windows.Forms;

  2. To get the ID of the current page, we call the ApplicationClass we created earlier:

    string id = onApp.Windows.CurrentWindow.CurrentPageId;

  3. And we will show it in a MessageBox

    MessageBox.Show("Current Page ID = " + id, "Hello World!");

  • To get an image to load on the ribbon, e.g. as the image of a button, we need to pass the image as an
    IStream
    1. But first we need to add the image to our project (similarly to how we added
      ribbon.xml).
      1. Go to Resources (Right-Click on the Project → Properties → Resources)
      2. Click on the down-arrow next to ‘Add Resource’, click ‘Add existing file’, and select the file (HelloWorld.png)

      3. In the Solution Explorer → Resources → right-click the inserted image → Properties → change its ‘Build Action’ to ‘Content’
    2. We start off by creating a new class (Right-Click on the project → Add → New Class). Call it CCOMStreamWrapper.cs
    3. Paste in the following code (CCOMStreamWrapper.cs) written by Nani (Microsoft) (relevant blog link: http://blogs.msdn.com/b/johnguin/archive/2010/10/25/code-for-the-table-sorting-powertoy-for-onenote-2010.aspx )that converts the image to an IStream
    4. Going back to Class1.cs, next we need to use the function,
      GetImages(), that we referenced in the ribbon.xml earlier
      1. The function called, GetImage() needs an IStream of the image passed back. It provides one variable, the image name, that is the string specified in
        ribbon.xml each time in the image attribute (for example in a button).
      2. So first we add (for the IStream and ImageFormat):

        using System.Runtime.InteropServices.ComTypes;
        using System.Drawing.Imaging;

      3. So we start off with an empty function (making sure that its name is the same as the one specified in
        ribbon.xml load image attribute):

        public IStream GetImage(string imageName)
        { }

      4. Next we need to create a memory stream, save the image to it (with the correct
        ImageFormat), and return it (after it has been through the
        CCOMStreamWrapper function):

        public IStream GetImage(string imageName)
        {
         MemoryStream mem = new MemoryStream();
         Properties.Resources.HelloWorld.Save(mem, ImageFormat.Png);
         return new CCOMStreamWrapper(mem);
        }

        (where ImageName is the name of the image that you imported)

  • When the application is closing, we want to ensure that we clear up the memory used. To do this, we:
    1. Collect the ‘Garbage’ with .NET’s GC (GarbageCollector) in the OnDisconnection
      void

      public void OnDisconnection(ext_DisconnectMode disconnectMode, ref System.Array custom)
      {
        onApp = null;
        GC.Collect();
        GC.WaitForPendingFinalizers();
      }

    2. Make our ApplicationClass variable (onApp) equal to null in the
      OnBeginShutdown void

      public void OnBeginShutdown(ref System.Array custom)
      {
        if (onApp != null)
        onApp = null;
      }

  • Now, Class1.cs should look like (with a different GUID & ProgId) this

  • Part 4 – Fixing the Installer

    The last thing to do now is to create an installer. Office Add-ins use the registry to specify settings and link the dll with the Office application. The installer needs to create these registry keys, and copy the Project Output (the dll created) to the Program Files directory.

    1. Add a Setup Project to the solution: File → Add → New Project → Other Project Types → Setup and Deployment → Visual Studio Installer → Setup Project

    2. Click on the setup project, and choose ‘Registry Editor’

    3. Remove all the keys, so that only the default hives are left

    4. Note your app’s GUID and ProgId, found in Class1.cs
    5. Create the following keys (Right-Click on a [Key / Hive] → Key) with their respective values (Right-Click → New → <Type>). Be sure to check their spelling – a common source of frustration when the add-in doesn’t load in OneNote
      • HKEY_CLASSES_ROOT\AppID\[Your app's GUID]
        Type Name Value
        string DllSurrogate

      • HKEY_CLASSES_ROOT\CLSID\[Your app's GUID]
        Type Name Value
        string AppID [Your app's GUID]

      • HKEY_CURRENT_USER\Software\Classes\AppID\[Your app's GUID]
        Type Name Value
        string DllSurrogate

      • HKEY_CURRENT_USER\Software\Classes\CLSID\[Your app's GUID]
        Type Name Value
        string AppID [Your app's GUID]

      • HKEY_LOCAL_MACHINE\Software\Classes\AppID\[Your app's GUID]
        Type Name Value
        string DllSurrogate

      • HKEY_LOCAL_MACHINE\Software\Classes\CLSID\[Your app's GUID]
        Type Name Value
        string AppID [Your app's GUID]

      • HKEY_LOCAL_MACHINE\Software\Microsoft\Office\OneNote\AddIns\[Your app's ProgID]
        Type Name Value
        string Description [Your app's description]
        string FriendlyName [Your app's name]
        DWORD LoadBehavior 3

        LoadBehavior should be "9" (load the add-in when the tab loads) for editing existing tabs or "3" (load the add-in when the application loads) for newly created tabs. We are using "3" in this tutorial, because otherwise (if we used "9") our tab would only load when the tab containing it would load, but because a tab is not contained in a tab, it would never load.

        For more information, see: http://msdn.microsoft.com/en-us/library/bb386106.aspx#LoadBehavior

        If you don’t want to add all the keys to Visual Studio’s Registry Editor manually:

        1. Open notepad and paste in the following code (regkeys.reg):
          Windows Registry Editor Version 5.00
           
          [HKEY_CLASSES_ROOT\AppID\[Your app’s GUID]]
          “DllSurrogate”=”"
           
          [HKEY_CLASSES_ROOT\CLSID\[Your app’s GUID]]
          “AppID”=”[Your app’s GUID]”
           
          [HKEY_CURRENT_USER\Software\Classes\AppID\[Your app’s GUID]]
          “DllSurrogate”=”"
           
          [HKEY_CURRENT_USER\Software\Classes\CLSID\[Your app’s GUID]]
          “AppID”=”[Your app’s GUID]”
           
          [HKEY_LOCAL_MACHINE\Software\Classes\AppID\[Your app’s GUID]]
          “DllSurrogate”=”"
           
          [HKEY_LOCAL_MACHINE\Software\Classes\CLSID\[Your app’s GUID]]
          “AppID”=”[Your app’s GUID]”
           
          [HKEY_LOCAL_MACHINE\Software\Microsoft\Office\OneNote\AddIns\[Your app’s ProgId]]
          “Description”=”Press for a Hello World!”
          “FriendlyName”=”Hello World!”
          “LoadBehavior”=dword:00000003
        2. Save the file as <filename>.reg (e.g. regkeys.reg)
        3. <Right-Click> on ‘Registry on Target Machine’ → Import…
        4. Find the save *.reg file and open it
        5. Visual Studio will insert the keys and values for you

          Be sure to check the imported values, sometimes (especially with the DWORD) insert doesn’t quite work)

    6. Now it should look like this (your GUID will be different, and your ProgID will probably be different to the one displayed here):

    7. Click on the setup project, and choose ‘File System Editor’
    8. Second last, we need to add the project’s output (the dll created) to the install location:
      Click on the Application Folder (generally the \Program Files\ directory) → Right-Click → Add → Project Output… → OK
    9. Running 64-Bit Office? Be sure to also change the TargetPlatform to x64 in the Installer Properties (Click on the setup project → F4) – Thanks for the tip, Ryan!
    10. Change the installer setting (Click on the setup project → F4) RemovePreviousVersions to True.
      You may also want to change some of the other settings, especially Product Name and Manufacturer, as the default install location is:
      [ProgramFilesFolder]\[Manufacturer]\[ProductName]

    Done!

    So, now we are done with process in Visual Studio, so we just build the solution, install the setup project that it creates, and you should see your add-in in OneNote!

    Add-in in Ribbon


    Tips & Good Sites

    Currently, when you want to debug the addin you need to change the Version of the Installer (as it checks for later versions before installing), build the solution, and install it. This can become very annoying when compiling frequently and attempting to debug an add-in. Speeding up this process (after the installer has run once, and made all the changes to the registry as necessary) you can get Visual Studio to simply build the project at its install location, thus not needing to constantly reinstall the application. To do this:

    1. First we will create a new Solution Configuration so that we can get Visual Studio to build the solution in the C:\Program Files path, while still easily able to go back to our previous config where Visual Studio built the solution in the bin\debug folder. Go to Solution Configurations Selector → Configuration Manager

    2. From the ‘active solution configuration’, choose <New…>
    3. Create a new Solution Configuration, copying settings from ‘Debug’

    4. Click OK, and Close
    5. Right-Click on the Project → Properties

    6. In Properties, go to the Debug tab. Change the Output path (under Output) to the install path of the application (generally C:\Program Files\<Manufacturer>\<ProductName>\ )
    7. Now simply build (Build → Build Solution) the project as normal, open OneNote again, and your add-in should have updated.

    Note:

    1. You may need to close dllhost.exe and OneNote before Visual Studio will allow you to build the project (files may be in use that would otherwise be overwritten)
    2. If your addin hasn’t updated in OneNote, especially if the image in the ribbon hasn’t, ‘reload’ the addin in OneNote. To do this:
      1. File → Options → Add-Ins → (Manage: COM Add-Ins) → Go

      2. Deselect your add-in and click OK (and OK in the OneNote Options window)

      3. Repeat the process (starting at a) again, but this time selecting your Add-In again
      4. This generally works, as it gets OneNote to completely reload the add-in, thus (hopefully) loading the newer image for your add-in in the ribbon

    Useful links


    • http://rustynotes.blogspot.com Dazzur

      Makes for interesting reading Malte; it’s obvious that you have spent some time learning and understanding the Microsoft development tools and environment(s). I mentioned that you may also be interested in looking at mobile applications and the ability to support multiple platforms using tools like Rhomobile. A colleague of mine has produced an interesting app with source-code that yo may find interesting at http://nycbigapps.com/submissions/2062.
      Darren

    • http://www.onenotepowertoys.com/2011/02/03/guide-publishing-2010-powertoys-ribbon/ How To Guide for publishing 2010 PowerToys to the Ribbon. | OneNote PowerToys

      [...] for your OneNote PowerToys. (Then you send me an email and I’ll publish/promote it here Developing OneNote 2010 Add-Ins – VS2008 and VS2010 tested. Source code available. – PDF and XPS versions of instructions [...]

    • http://www.facebook.com/norbauer Ryan Norbauer

      Thanks for the awesome, incredibly detailed tutorial!

      One thing folks running 64-bit Windows should note is that the default target platform of the setup project as described above will be x86. This will cause the resulting installer to run as an x86 process, adding its registry keys to the Wow6432Node section of the registry instead of the main branch. This is problematic if you are running 64-bit Office, as Office will not look at the Wow6432Node section of the registry for addins.

      So, for example, if you follows the original steps in the tutorial, a key will be inserted in
      HKEY_LOCAL_MACHINESoftwareWow6432NodeMicrosoftOfficeOneNoteAddIns[Your app's ProgID]
      instead of
      HKEY_LOCAL_MACHINESoftwareMicrosoftOfficeOneNoteAddIns[Your app's ProgID].

      If you do happen to be running 64-bit Windows, a solution is to set the “TargetPlatform” property of the setup project to match the platform of Office. x64 for 64-bit Office and x86 for 32-bit Windows.

      Thanks again for the hard work you put into this excellent resource. With the exception of the above issue, I went through it step-by-step, knowing next to nothing about Office or OneNote development, and successfully built and installed a OneNote project! :)

      Cordially,
      Ryan

    • http://www.facebook.com/norbauer Ryan Norbauer

      Also, note that idMso appears actually to be case-sensitive when specifying a ControlID. Your example uses all lower-case: “idmso.”

      R

    • http://www.malteahrens.com Malte Ahrens

      Thanks for the heads-up! Unfortunately I only have 32-bit machines, so I failed to test this.

      I have updated the tutorial (including the pdf & xps versions) to include this.

      Thanks again!,

      Malte

    • http://www.malteahrens.com Malte Ahrens

      Correct. I’ve fixed this as well.

      Thanks for pointing out those mistakes.

    • http://www.facebook.com/norbauer Ryan Norbauer

      Hi again Malte,

      Incidentally, do you know the syntax to use in the GetImage method in the case where one wants to use multiple buttons with different png icons?

      For example:
      Properties.Resources.icon.Save(mem, ImageFormat.Png);

      Where I have multiple resources rather than just one “icon.png.” Is there any way to get the icon specifically based on what is bring requested by the ribbon.xml for that particular button (presumably this is passed as imageName into the GetImage method by the framework).

      Thanks!

      –Ryan Norbauer

    • http://www.malteahrens.com Malte Ahrens

      That’s correct, the string variable (in this case imageName) passes the image=”" parameter from the ribbon’s xml file.

      The method that I like to use to pass multiple images, is a switch statement. e.g.:

      public IStream GetImages(string imageName)
      {
       MemoryStream mem = new MemoryStream();

       switch (imageName)
        {
        case “icon.png”:
          Properties.Resources.icon.Save(mem, ImageFormat.Png);
          break;

        case “my_second_icon.png”:
          Properties.Resources.my_second_icon.Save(mem, ImageFormat.Png);
          break;

         default:
          return null;
        }

       return new CCOMStreamWrapper(mem);
      }

    • http://www.facebook.com/norbauer Ryan Norbauer

      Ah, OK. I was thinking there might be a more D.R.Y. way to do it, but that works. Thanks again, Malte.

    • http://blogs.msdn.com/noahc/ noahcoad

      Wow, this is an intense post, lots of great information.  Thanks for laying out how to create OneNote addins so clearly.

    • Steven Devetter

      It doesn’t work at me. Can it be that the problem is that i work with a 64bit-machine and run a 32bit office? I even test your source code and it does nothing. Even when I do what Ryan Norbauer say.

    • http://www.malteahrens.com Malte Ahrens

      You shouldn’t have to make any changes to the source code to get it to work since you have 32bit office (it’s the bit-ness of office, not the OS that matters).

      Does the add-in get installed (i.e. you get a new tab called ‘Custom’ with a ‘Hello World button’) when you run the installer from the downloaded source code, i.e.HelloWorld-Visual-Studio-2010-SourceSetupDebugSetup.msi ?

    • http://www.cogniview.com/ pdf to excel converter

      HI, 

      Its great post guys about Malte Ahrens, you have explained it so brilliantly guys. Really well work….

    • Jeremy

      How would I create a WiX installer for the addin? I don’t have the full VS2010, only the express edition and SharpDevelop.
      I currently can’t get the addin to load in OneNote 2010 – “runtime error” after enabling addin from OneNote options, although your MSI works.
      Great article by the way, really easy to follow with the screenshots.
      Jeremy

    • http://www.malteahrens.com Malte Ahrens

      Is it the addin from the MSI on this page, or your own addin that brings up the “runtime error”?

      A ‘runtime error’ can come both from some keys & values being incorrectly named (or non existent) in the registry, or from coding bugs.

      Have you checked the registry manually to see if the keys have been put in correctly?

      Thanks for the nice comments BTW.

    • Jeremy

      Hi its Jeremy again
      The addin I compiled loads with Word, Excel and PowerPoint, but not OneNote. (all 2010)
      I have checked disabled addins in OneNote… but to no avail.

      Anything else I can try?

      p.s. The addin from this page works AOK!
      Thnx

    • http://www.malteahrens.com Malte Ahrens

      Can you see it in File → Options → Add-Ins?

      If yes (based on your first comment), and all the keys have been correctly set in the registry, I would take a look at that code.

      If you comment out all your code in the OnConnection, OnStartupComplete, etc. events and just have a MessageBox.Show() in the OnConnection function, and then run it and it works, then it has something to do with your code. If the messagebox doesn’t show up at all, and it’s still listed under ‘Disabled’ or ‘Inactive’ Add-Ins, it will have something to do with the registry.

    • Jeremy

      Thanks Malte, I had to fix the registry entries in wix.

    • http://www.malteahrens.com Malte Ahrens

      Great to hear! I’m glad you were able to get it to work.

    • Roused42

      I’ve run through several times and each time I get the same error when I try to install.  This is my first .NET code so it’s possible I’m making a really simple mistake but the error is as follows:

      “The installer has encountered an unexpected error installing this package.  This may indicate a problem with this package.  The error code is 2324.”

      Thanks,

    • http://www.malteahrens.com Malte Ahrens

      I’ve never encountered that error, but searching on google, it could result from:
       - 64-bit vs. 32-bit problems ( http://www.appdeploy.com/msierrors/detail.asp?id=363 )
       - Hardrive issues ( http://forums.techguy.org/all-other-software/952455-solved-visual-studio-2005-professional.html )
       - Registry issues ( https://discussions.apple.com/thread/2330949?start=0&tstart=0 )

      Does the Setup.msi in HelloWorld-Visual-Studio-2010-SourceSetupDebug work?

    • Roused42

      No, that gives the same error.

    • Roused42

      I tried building a wix installer for it, the installer runs fine but it doesn’t seem to be adding the Registry values in SoftwareMicrosoftOffice…

      It did edit the other registry folders, which is odd.  For some reason it isn’t touching anything in that directory.

      To be sure it’s not something I missed or messed up I plan to download your source code and compile it to see if i can get it to install.

    • Roused42

      I’ve compared my code to your source and found two items I was missing from Class1.cs.

      OnDisconnection (  Extensibility.ext_DisconnectMode…

      IStream GetImage(string imageName) 

      After I corrected these two items it compiled and installed without errors.

    • http://www.malteahrens.com Malte Ahrens

      Fantastic! I’m happy to hear you got it to work – and thanks for sharing your solution!

    • Gattu

      You must have mentioned the Note part before Tips & Good Sites
      It got frustrated for some time not finding my addIn

    • Ross Gao

      Following your tutorial, I build my first add-in successfully, but get stuck when trying to make it a little more complex.

      I want a function to be called when OneNote UI is navigated away from current page. My code is:
      public void OnConnection(object Application, ext_ConnectMode ConnectMode, object AddInInst, ref Array custom)
      {
                  onApp = (OneNote.ApplicationClass)Application;
                  try
                  {
                      onApp.OnNavigate += new Microsoft.Office.Interop.OneNote.IOneNoteEvents_OnNavigateEventHandler(OnNavigate);
                  }
                  catch (Exception ex)
                  {
                      MessageBox.Show(ex.Message);
                  }
      }public void OnNavigate()
      {
           MessageBox.Show(“test!”);
      }I get the exception message: “Error HRESULT E_FAIL has been returned from a call to a COM component.”, and function OnNavigate() doesn’t work. Do you know why? Or is there other ways to get the navigate event?Thank you.

    • http://www.malteahrens.com Malte Ahrens

      Great Question!

      The MSDN docs http://msdn.microsoft.com/en-us/library/gg649853.aspx state that ‘Events cannot currently be added in managed code.’ While I can’t confirm that this is the case, it does still seem to be so - I’m getting the same HRESULT E_FAIL error (also for the OnHierarchyChange event).

      You could try using Varun Srinivasan’s post http://blogs.msdn.com/b/descapa/archive/2011/08/24/c-c-add-ins-for-onenote-2010.aspx which talks about creating C++ add-ins for OneNote (though in my quick try-out and with my still-improving C++ skills I couldn’t find these events in the header file)

      I’m sorry I can’t help much – I’ll aim to have another look on the weekend.

      Let me know how it goes,

      Malte

    • Poul Sørensen

      I cant get this working with 4.0 of .net. The ApplicationClass cant be embedded and using Application dont have the methods needed.

    • http://www.malteahrens.com Malte Ahrens

      There’s a bug with the OneNote 14.0 Object Library, .NET 4, and Visual Studio. To stop this error, just open the properties of Microsoft.Office.Interop.OneNote (Solution Explorer → References) and set ‘Embed Interop Types’ to False.

      You can read more on Danial Escapa’s blog: http://blogs.msdn.com/b/descapa/archive/2010/04/27/onenote-2010-and-visual-studio-2010-compatibility-issues.aspx

    • http://www.creativementor.com.au/microsoft-excel-training.html Excel courses

      This is really nice stuff about Onenote 2101 add ins information. OneNote is a computer program for a free form information gathering and multi-user collaboration. This tutorial is nice to create project on OneNote 2010. 

    • Ruben Lardies

      First of all I’d like to thank you very much the great work you did with this tutorial. I followed the post as a guide for develop my own addin and it worked great for One Note. I think this guide should be right for access and publisher addins as well only changing the references, so I tried it but it didn’t work… the add in cannot be loaded. And still appears on inactive addins.

      Have you got any clue about this?

      Thanks a lot again for this great work you did.

    • Dan

      Malte,

      This is an excellent write up, thank you for such a thorough tutorial. I’m not sure if you still keep track of this comment thread, but I have a question about installing the add-in using WiX. It seems that the registry entries are not being written properly with my msi. The dlls are copied to the program files folder just fine.

      What is curious is that on my development machine I can uninstall and install the add-in using the msi I have created with WiX and it shows up in OneNote with no problems. But when I try to install on a different machine (same configuration, same version of OneNote 2010 SP2, 32-bit on 64-bit windows) the add-in does not appear in the com add-ins “available add-ins” list. The Dlls are in the right location, and after installing I manually went in and edited the registry to the appropriate values but have not had any luck getting the add-in to appear. I do not seem to have any misspellings and have checked and double checked all the values in HKCR, HKCU, and HKLM, but still no luck. Any ideas on how I can debug this issue further?

      Any advice would be greatly appreciated. Thank you!

      -Dan

    • Dan

      Oh, and the reason I’m using WiX is that I am also using VS 2012, which no longer supports VS installer projects, which I am sure you are already aware of. Very frustrating!

    • Raoul

      Hello :-)
      I have try the sample with Visual Studio 2010 on a Windows 7 64 bits/Office 2010 32 bits,
      After installing the HelloWorld with the Setup… The ribbon is not displayed in OneNote.
      In the list of Add-Ins, the HelloWorld is not displayed…. And if I want to add it manually, I have the error: “HelloWorld.dll is not a valid Office Add-in” :-(
      Can you help me ?
      Raoul

    • http://www.shiftedexposure.com/ Beryl

      Its like you read my mind! You appear to know a lot about this, like you wrote the book in it or something.
      I think that you could do with a few pics to drive the message home a little bit, but other than that, this is magnificent blog.

      An excellent read. I will definitely be back.

      my web site; site (Beryl)

    • http://automat-online.com Britney

      I was extremely pleased to uncover this great site. I need to to thank you for your time for this particularly fantastic read!!

      I definitely liked every little bit of it and i also have
      you book-marked to look at new stuff in your website.

    • http://buy-essay.webs.com/ Rosalie

      Hurrah! At last I got a webpage from where I can in fact get useful information regarding my study and knowledge.

    • http://allanguagesolutions.co.uk/services/ homepage

      Usually I don’t read article on blogs, however I would like to say that
      this write-up very pressured me to check out and do so!
      Your writing taste has been surprised me.
      Thanks, quite nice article.

    • Darren Beale

      Firstly I wanted to thank you for this excellent tutorial. It’s just about the only one out there and certainly the only one that breaks it down step-by-step. The comments thread has proved very helpful too.

      I seem to not be the only person who has had some issues with OneNote 2013, though. I’ve been pretty thorough in my debugging but there’s something not right. It builds fine but the plugin won’t load, OneNote disables it after trying. I’ve posted a detailed breakdown on Stack Overflow. Maybe it’ll get some response, I link it here just in case others have similar issues and want a place to start digging.

      http://stackoverflow.com/questions/20024066/onenote-2013-add-in-wont-load-how-to-debug

    • Alexey Borisov

      Malte, good day!

      I’m tying to follow your steps in VB (just convert this code) and stuck with Property method.

      Could you advice, how to solve this problem?

      Thanks.

    • James Jack

      Hi Malte,

      I’m new to OneNote add-in development, but thanks to your HelloWorld application I’m off to a flying start. I’m developing code that interacts with embedded EMF files in OneNote and the one issue blocking me that I can’t seem to find any information on is how to determine / get a handle on which object a user has selected on a page. I need to be able to do this to determine if my code should run or not and to get the EMF content and use it in my code in some way. Can you advise?

    • James Jack

      I found the solution myself:

      XmlNodeList[k].Attributes.GetNamedItem(“selected”).Value == “all” &&

      XmlNodeList[k].Attributes.GetNamedItem(“format”).Value == “emf”)

    • James Jack

      So I have another question… I can now launch my application from inside my OneNote Add-in. The application allows the user to edit the EMFs in the OneNote page and update them. Obviously if the user edits the OneNote page whilst my editor is also trying to edit stuff – that could be bad… Can I block the OneNote application’s ability to edit and then restore its ability to edit when my application completes? I managed to get the CurrentWindow’s window handle and tried to block editing with a modal dialog, but that only partially works – I’m warned, but I can still edit stuff behind the modal dialog…

    • James Jack

      Actually the modal dialog seems to block some features, such as page editing, but unfortunately its not blocking me from deleting entire notebooks/pages

    • Vikas

      Hi.. did you get a chance to try the same with OneNote 2013? I’ve followed the same steps and after installing the addin from the setup.msi file, i see that the addin is going into the Inactive add-ins section.

      I’ve also tried to change the registry value of LoadBehavior to 3 and restart OneNote, but it is changing the value back to 2. Any help is appreciated.

    • Vikas

      Hi Darren,
      Even I’m facing same issues when following the above steps with OneNote 2013. any update on your findings?

    • UD

      Hi,
      First, thank you for your hard work posting this. I don’t understand why it is so difficult finding information about how to code for OneNote an reasonably easy finding information for the other Office applications. I’m however having the same problem as described by Vikas with OneNote 2013 and Visual Studio 2013. Could you help?
      Thank you!

    • Eric Peukert

      Hi Ross,

      could you find a way to work with events in OneNote? I am struggeling with the same problems.

      Best,
      Eric

    • Sheraz Khan

      Very informative, thanks
      for sharing. I came across another useful .NET API for working with Microsoft
      Office OneNote files, I am sure it’s going to be useful. Here it is: http://www.aspose.com/.net/note-component.aspx

    • Arno

      Great writeup! Very helpful. I got this to work in Outlook 2010 as well, with a few very minor tweaks. Thanks again!

    • Dmitry

      So
      Does anyone have a solution for OneNote 2013?

    • Lagos Mihali

      Has the 2013 problem been solved? How?

    • Lagos Mihali

      That is, the above code works perfectly on 2010, but not 2013. It shows up as com AddIn, but button does not display. When you try to check the AddIn, OneNote unchecks it. BTW: this is maybe the best written programming article I have ever read. Thanx so much!

    • Anthony Iacobacci

      Commenting out the onApp = (ApplicationClass)Application; line in OnConnection() seems to fix the problem. I attachted the Debugger to the dllhost.exe process and it displayed an error with casting. It seems that it doesn’t kuje casting the Application object as an ApplicationClass.

    • Paul Hodgson

      if you find you need a reference to onApp replace the content of the OnConnection() method with the following:-
      onApp = new Microsoft.Office.Interop.OneNote.Application();

    • Paul Hodgson

      I don’t suppose anyone could share a WiX file for this could they, I’m trying to make one and failing epically.

    • sdecorme

      Great post, it wprks
      But now i need to had multiple button on my ribbon how can I modify your code

      Thks

    • Wim

      I’d like to know this as well.

    • The Living Tribunal

      Same here, but when I run the source code given at the beginning of the tutorial, it works fine. I think there must be some property or missing bit of information that is not specified in the tutorial, but I can’t figure out what it is.

      Anyway, thanks so much for this tutorial! It’s the best Office add-in tutorial I’ve seen, let alone the best OneNote add-in tutorial. Much appreciated!

    • Menashe Schwob

      Thanks you, this is very useful tutorial!

      I got a problem running the add-in on oneNote 2016. It does run on oneNote 2010, but for oneNote 2016 it going under ‘Inactive Application Add-ins’ (in option menu) and when I trying activate it menually it give error ‘Not loaded. A runtime occurred during the loading of the COM Add-in’

      how can i fix it?

    • Nicolae Daian

      In my case I don’t even see it in Options/Add-ins. Setup completes successfully but i cannot find it after that.

    • Nicolae Daian

      I just found this sample on Microsoft site, the add-in is activated and you can use it. I still had to turn off ‘Embed Interop Types’.
      https://support.microsoft.com/en-us/kb/2555352

    • Jonathan Wong

      I think I may have found the solution if you are having trouble with the Add-in not showing up in OneNote2013

      1. Put “[ComVisible(true)]” (Without the quotes) above “[Guid(), ProgId()]” in Class1.cs
      2. Replace “Application Class onApp = new ApplicationClass();” with “protected Application onApp{get;set;}”
      3. In the OnConnection method replace “onApp = (ApplicationClass)Application;” with “onApp = (Application)Application;”

      I got this from comparing a framework found here: https://github.com/OneNoteDev/VanillaAddIn
      Good luck!

      P.S Thanks for the great tutorial!

    • Nicolae Daian

      Fantastic tutorial !!! Thank you Malte for putting it together!

      Unfortunately it doesn’t work for me on Office Professional 2016. I downloaded the VS 2010 solution and the add-in is deployed and it shows up in OneNote but it doesn’t get activated. When i select it in “COM Add-ins” dialog it says “Not loaded. A runtime error occurred during the loading of the COM Add-in”.
      I guess this is because i am trying to use it with OneNote 2016.
      Any chance that you can update your tutorial to a more recent version of Office? Or could you point me to another tutorial? I tried the VanillaAddIn (https://github.com/OneNoteDev/VanillaAddIn) with the same result.

      Thank you in advance!!

      Nicolae Daian

    blog comments powered by Disqus