29
Developing OneNote 2010 Add-Ins www.malteahrens.com/blog/howto-onenote-dev/ 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 – blogs.msdn.com/b/descapa/ ) 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): This is a tutorial / guide on how to do this. This has been tested with Visual Studio 2008 Professional and Visual Studio 2010 Professional. Download the Visual Studio 2008 source code Download the Visual Studio 2010 source code This guide is broken down into five parts: Part 1 – Creating the project Part 2 – Creating the ribbon Part 3 – Writing some code Part 4 – Fixing the Installer Part 5 – Tips & Good Sites Malte Ahrens www.malteahrens.com

Developing OneNote 2010 Addins

Embed Size (px)

DESCRIPTION

A good introduction

Citation preview

Page 1: Developing OneNote 2010 Addins

Developing OneNote 2010 Add-Ins www.malteahrens.com/blog/howto-onenote-dev/

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 – blogs.msdn.com/b/descapa/ ) 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):

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

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

Professional.

Download the Visual Studio 2008 source code

Download the Visual Studio 2010 source code

This guide is broken down into five parts:

Part 1 – Creating the project

Part 2 – Creating the ribbon

Part 3 – Writing some code

Part 4 – Fixing the Installer

Part 5 – Tips & Good Sites

Malte Ahrens

www.malteahrens.com

Page 2: Developing OneNote 2010 Addins

Developing OneNote 2010 Add-Ins P a g e | 2

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

Page 3: Developing OneNote 2010 Addins

Developing OneNote 2010 Add-Ins P a g e | 3

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

a. Right-Click on the Project → Properties

b. Application tab → Assembly Information

Page 4: Developing OneNote 2010 Addins

Developing OneNote 2010 Add-Ins P a g e | 4

c. Select „Make assembly COM-Visible‟. This makes the class library / .dll

generated by the project visible to OneNote.

d. Click OK

e. Build tab → Register for COM Interop. This gets Visual Studio to

automatically register the application for COM Interop when it‟s built

Page 5: Developing OneNote 2010 Addins

Developing OneNote 2010 Add-Ins P a g e | 5

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

a. Open: Properties → AssemblyInfo.cs

b. Change the following:

[assembly: AssemblyVersion("1.0.0.0")] [assembly: AssemblyFileVersion("1.0.0.0")]

to:

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

Page 6: Developing OneNote 2010 Addins

Developing OneNote 2010 Add-Ins P a g e | 6

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 an 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).

a. Right Click on the Project → Properties → Resources → „Click here

to create one‟

Page 7: Developing OneNote 2010 Addins

Developing OneNote 2010 Add-Ins P a g e | 7

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

3. MSDN has a great introduction to XML and the Ribbon.

See: msdn.microsoft.com 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> <!-- Our content goes here --> </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>

Page 8: Developing OneNote 2010 Addins

Developing OneNote 2010 Add-Ins P a g e | 8

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 (www.microsoft.com/downloads). 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"/>

Page 9: Developing OneNote 2010 Addins

Developing OneNote 2010 Add-Ins P a g e | 9

9. This is what it should look like now:

<?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>

Page 10: Developing OneNote 2010 Addins

Developing OneNote 2010 Add-Ins P a g e | 10

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 (the 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 Object1 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;

1 For Visual Studio 2008, it appears as „Microsoft OneNote 14.0 Type Library‟

Page 11: Developing OneNote 2010 Addins

Developing OneNote 2010 Add-Ins P a g e | 11

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

a. Tools → Create GUID (if it isn‟t there, do a search in the start-menu)

b. 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 42

[Your app‟s ProgId] = Project.ClassName3

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).

2 For example: 61139959-A5E4-4261-977A-6262429033EB 3 For example: HelloWorld.Class1

Page 12: Developing OneNote 2010 Addins

Developing OneNote 2010 Add-Ins P a g e | 12

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) { }

Page 13: Developing OneNote 2010 Addins

Developing OneNote 2010 Add-Ins P a g e | 13

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 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... */ }

Page 14: Developing OneNote 2010 Addins

Developing OneNote 2010 Add-Ins P a g e | 14

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) { }

Page 15: Developing OneNote 2010 Addins

Developing OneNote 2010 Add-Ins P a g e | 15

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.

a. First add:

using System.Windows.Forms;

b. To get the ID of the current page, we call the ApplicationClass we

created earlier:

string id = onApp.Windows.CurrentWindow.CurrentPageId;

c. And we will show it in a MessageBox

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

18. 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

a. First, we need to add the image to our project (similarly to how we

added ribbon.xml)

i. Go to Resources (Right-Click on the Project → Properties →

Resources)

ii. Click on the down-arrow next to „Add Resource‟, click „Add

existing file‟, and select the file (HelloWorld.png)

iii. In the Solution Explorer → Resources → right-click the inserted

image → Properties → change its „Build Action‟ to „Content‟

b. We start off by creating a new class (Right-Click on the Project → Add

→ New Class). Call it CCOMStreamWrapper.cs

c. Paste in the following code written by Nani (Microsoft) (relevant blog

link: blogs.msdn.com/b/johnguin/ ) that converts the image to an

IStream

Comments have been removed to fit this onto two pages. Original: CCOMStreamWrapper.cs

Page 16: Developing OneNote 2010 Addins

Developing OneNote 2010 Add-Ins P a g e | 16

/* * Code from: * TOC Power Toy 2010 by Nani (Microsoft) * See: http://blogs.msdn.com/b/johnguin/archive/2010/10/25/code-for-the-table-sorting-powertoy-for-onenote-2010.aspx * */ using System; using System.Collections.Generic; using System.Text; using System.Runtime.InteropServices; using System.Runtime.InteropServices.ComTypes; namespace HelloWorld { class CCOMStreamWrapper : IStream { public CCOMStreamWrapper(System.IO.Stream streamWrap) { m_stream = streamWrap; } public void Clone(out IStream ppstm) { ppstm = new CCOMStreamWrapper(m_stream); } public void Commit(int grfCommitFlags) { m_stream.Flush(); } public void CopyTo(IStream pstm, long cb, IntPtr pcbRead, IntPtr pcbWritten) { } public void LockRegion(long libOffset, long cb, int dwLockType) { throw new System.NotImplementedException(); } public void Read(byte[] pv, int cb, IntPtr pcbRead) { Marshal.WriteInt64(pcbRead, m_stream.Read(pv, 0, cb)); } public void Revert() { throw new System.NotImplementedException(); } public void Seek(long dlibMove, int dwOrigin, IntPtr plibNewPosition) { long posMoveTo = 0; Marshal.WriteInt64(plibNewPosition, m_stream.Position); switch (dwOrigin) { case 0: { /* STREAM_SEEK_SET */

Page 17: Developing OneNote 2010 Addins

Developing OneNote 2010 Add-Ins P a g e | 17

posMoveTo = dlibMove; } break; case 1: { /* STREAM_SEEK_CUR */ posMoveTo = m_stream.Position + dlibMove; } break; case 2: { /* STREAM_SEEK_END */ posMoveTo = m_stream.Length + dlibMove; } break; default: return; } if (posMoveTo >= 0 && posMoveTo < m_stream.Length) { m_stream.Position = posMoveTo; Marshal.WriteInt64(plibNewPosition, m_stream.Position); } } public void SetSize(long libNewSize) { m_stream.SetLength(libNewSize); } public void Stat(out System.Runtime.InteropServices.ComTypes.STATSTG pstatstg, int grfStatFlag) { pstatstg = new System.Runtime.InteropServices.ComTypes.STATSTG(); pstatstg.cbSize = m_stream.Length; if ((grfStatFlag & 0x0001/* STATFLAG_NONAME */) != 0) return; pstatstg.pwcsName = m_stream.ToString(); } public void UnlockRegion(long libOffset, long cb, int dwLockType) { throw new System.NotImplementedException(); } public void Write(byte[] pv, int cb, IntPtr pcbWritten) { Marshal.WriteInt64(pcbWritten, 0); m_stream.Write(pv, 0, cb); Marshal.WriteInt64(pcbWritten, cb); } private System.IO.Stream m_stream; } }

Note: You may have to change the namespace ‘HelloWorld’ to your own namespace

Page 18: Developing OneNote 2010 Addins

Developing OneNote 2010 Add-Ins P a g e | 18

d. Going back to Class1.cs, next we need to use the function,

GetImages(), that we referenced in the ribbon.xml earlier

i. 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).

ii. So first we add (for the IStream and ImageFormat):

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

iii. 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) { }

iv. 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 HelloWorld is the name of the image that you imported

13. When the application is closing, we want to ensure that we clear up the

memory used. To do this, we:

a. 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(); }

Page 19: Developing OneNote 2010 Addins

Developing OneNote 2010 Add-Ins P a g e | 19

b. 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): (Original: class1.cs)

using System; using System.Collections.Generic; using System.Linq; using System.Text; using Extensibility; using System.Runtime.InteropServices; using Microsoft.Office.Interop.OneNote; using Microsoft.Office.Core; using System.Windows.Forms; using System.Runtime.InteropServices.ComTypes; using System.IO; using System.Drawing.Imaging; namespace HelloWorld { [GuidAttribute("61139959-A5E4-4261-977A-6262429033EB"), ProgId("HelloWorld.Class1")] public class Class1 : IDTExtensibility2, IRibbonExtensibility { #region IDTExtensibility2 Members ApplicationClass onApp = new ApplicationClass(); public void OnConnection(object Application, ext_ConnectMode ConnectMode, object AddInInst, ref Array custom) { onApp = (ApplicationClass)Application; } public void OnDisconnection(Extensibility.ext_DisconnectMode disconnectMode, ref System.Array custom) { onApp = null; GC.Collect(); GC.WaitForPendingFinalizers(); } public void OnBeginShutdown(ref System.Array custom) { if (onApp != null) onApp = null; } public void OnStartupComplete(ref Array custom) { } public void OnAddInsUpdate(ref Array custom) { }

Page 20: Developing OneNote 2010 Addins

Developing OneNote 2010 Add-Ins P a g e | 20

#endregion #region IRibbonExtensibility Members public string GetCustomUI(string RibbonID) { return Properties.Resources.ribbon; } public void showHello(IRibbonControl control) { string id = onApp.Windows.CurrentWindow.CurrentPageId; MessageBox.Show("Current Page ID = " + id, "Hello World!"); } public IStream GetImage(string imageName) { MemoryStream mem = new MemoryStream(); Properties.Resources.HelloWorld.Save(mem, ImageFormat.Png); return new CCOMStreamWrapper(mem); } #endregion } }

Page 21: Developing OneNote 2010 Addins

Developing OneNote 2010 Add-Ins P a g e | 21

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

Page 22: Developing OneNote 2010 Addins

Developing OneNote 2010 Add-Ins P a g e | 22

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.

a. HKEY_CLASSES_ROOT\AppID\[Your app's GUID]

Type Name Value

string DllSurrogate

b. HKEY_CLASSES_ROOT\CLSID\[Your app's GUID]

Type Name Value

string AppID [Your app's GUID]

c. HKEY_CURRENT_USER\Software\Classes\AppID\[Your app's GUID]

Type Name Value

string DllSurrogate

d. HKEY_CURRENT_USER\Software\Classes\CLSID\[Your app's GUID]

Type Name Value

string AppID [Your app's GUID]

e. HKEY_LOCAL_MACHINE\Software\Classes\AppID\[Your app's GUID]

Type Name Value

string DllSurrogate

f. HKEY_LOCAL_MACHINE\Software\Classes\CLSID\[Your app's GUID]

Type Name Value

string AppID [Your app's GUID]

g. 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: msdn.microsoft.com

Page 23: Developing OneNote 2010 Addins

Developing OneNote 2010 Add-Ins P a g e | 23

If you don‟t want to add all the keys to Visual Studio‟s Registry Editor

manually:

a. 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

b. Save the file as <filename>.reg (e.g. regkeys.reg)

c. <Right-Click> on „Registry on Target Machine‟ → Import…

d. Find the save *.reg file and open it

e. 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)

Page 24: Developing OneNote 2010 Addins

Developing OneNote 2010 Add-Ins P a g e | 24

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‟

Page 25: Developing OneNote 2010 Addins

Developing OneNote 2010 Add-Ins P a g e | 25

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)

10. Last, 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!

Page 26: Developing OneNote 2010 Addins

Developing OneNote 2010 Add-Ins P a g e | 26

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…>

Page 27: Developing OneNote 2010 Addins

Developing OneNote 2010 Add-Ins P a g e | 27

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 Build 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 addin should have updated.

Page 28: Developing OneNote 2010 Addins

Developing OneNote 2010 Add-Ins P a g e | 28

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 has not updated in OneNote, especially if the image in the

ribbon has not, „reload‟ the addin in OneNote. To do this:

a. File → Options → Add-Ins → (Manage: COM Add-Ins) → Go

b. Deselect your add-in and click OK (and OK in the OneNote Options

window)

c. Repeat the process (starting at a) again, but this time selecting your

Add-In again

d. 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

Page 29: Developing OneNote 2010 Addins

Developing OneNote 2010 Add-Ins P a g e | 29

Useful links

Debugging a OneNote Add-in with Visual Studio (for OneNote 2007 add-ins,

but it‟s still relevant):

http://blogs.msdn.com/b/descapa/archive/2007/05/01/debugging-a-

onenote-toolbar-addin-c.aspx

Debugging OneNote API access through the log:

http://blogs.msdn.com/b/descapa/archive/2006/12/08/debugging-the-

onenote-api-enable-logging.aspx

OneNote Error Codes / COM Exceptions:

http://msdn.microsoft.com/en-us/library/ff966472.aspx

Customizing the Ribbon / Fluent UI (for Office 2007, but it‟s still relevant):

http://msdn.microsoft.com/en-us/library/aa338202(office.12).aspx

Getting the Control IDs for Tabs, Groups, and Buttons in OneNote‟s ribbon

(useful for e.g. adding a button on the Home tab, rather than a new tab):

http://www.microsoft.com/downloads/en/details.aspx?FamilyID=3f2fe784-

610e-4bf1-8143-41e481993ac6&displaylang=en

Editing content in OneNote through OneNote‟s API:

http://msdn.microsoft.com/en-us/magazine/ff796230.aspx

OMSpy – taking a look at the XML structure of pages, sections (and section

groups), and notebooks in OneNote:

http://blogs.msdn.com/b/descapa/archive/2007/02/12/omspy-a-onenote-

developer-s-tool.aspx

Office Schema Reference (useful for trying to understand OneNote‟s XML

elements and attributes. It‟s the 2007 one, but again it‟s still relevant (and it

provides it in a HTML format and *.xsd, whereas the 2010 one only has the

*.xsd)):

http://www.microsoft.com/downloads/en/details.aspx?FamilyId=15805380-

F2C0-4B80-9AD1-2CB0C300AEF9&displaylang=en

Source Code from the Table Sorting Powertoy (by Nani – Microsoft):

http://blogs.msdn.com/b/johnguin/archive/2010/10/25/code-for-the-table-

sorting-powertoy-for-onenote-2010.aspx

All the OneNote blogs (especially John Guin and Daniel Escapa)