It has been awhile since I have blogged about the OneNote API so I thought I would post a nice long article showing a sample app I made awhile ago.
Goal: Write an app that allows you to send a file from the Windows shell directly to OneNote, and it looks like this:
High-level: We will write an app that takes command line args that are paths to files. We will then create XML for a page in OneNote which contain embedded files pointing to these source files. Import this all into OneNote and success.
Requirements: Visual Studio 2005 & OneNote 2007 (this XML works with the RTM version)
using OneNote = Microsoft.Office.Interop.OneNote;
private OneNote.Application onApp;
onApp = new Microsoft.Office.Interop.OneNote.Application();
MessageBox.Show("Please install Micorosft Office OneNote 2007");
onApp = null;
As you can see when you first instantiate the class it will get a COM reference to OneNote, if OneNote isn't installed then we will throw a dialog box @ the user and we exit. Don't ask me why I use exit error code -99, heck I imagine that most of you will say that you don't even need an error exit code, but whatever : )
string unfiledID = "";
onApp.GetSpecialLocation(Microsoft.Office.Interop.OneNote.SpecialLocation.slUnfiledNotesSection, out unfiledPath);
onApp.OpenHierarchy(unfiledPath, null, out unfiledID, Microsoft.Office.Interop.OneNote.CreateFileType.cftNone);
catch (Exception e)
MessageBox.Show("Couldn't get your Unfiled Notes Location");
What does this do? I call OneNote and I ask it for the path to the Unfiled Notes section (that is the GetSpecialLocation call) and then I ask OneNote to open that path and give me back the ID. You might ask why would I do this if OneNote already has the Unfiled Notes open, well this is an easy way for me to get the ID instead of needing to parse through XML or anything else. Anytime you ask OneNote to open something (with OpenHierarchy) then OneNote will return the ID back to you.
pathCache="D:\Documents and Settings\descapa\Local Settings\Application Data\Microsoft\OneNote\12.0\OneNoteOfflineCache_Files\Sample file.one"
pathSource="D:\Documents and Settings\descapa\Desktop\Sample file.one"
I did take out some of the XML but you can see the basics of the page here. I have a title which says "Sent Files" and then there is an embedded file on the page which is for the file "Sample file.one". You can see that we have a pathSource and a pathCache attributes on the InsertedFile element. The IDs & objectIDs will be filled in by OneNote once the XML has been imported and there are other special items like exact positioning that we can ignore when we import content. If you really wanted to place this in a certain location we could do so, but let's just deal with the basics now.
You can easily embed a file in OneNote because you just need to specify the path via the XML and then OneNote will do the rest. You don't need to actually break down the file and put it on the page, just give it a path. OneNote will then take this, insert it into the file, and put a cached copy in the OneNote cache.
I think we can go and write insertFiles().
void importFiles(string args)
string unfiledID = findUnfiledID();
string importedPageID = "";
onApp.CreateNewPage(unfiledID, out importedPageID, Microsoft.Office.Interop.OneNote.NewPageStyle.npsDefault);
MessageBox.Show("Could not create a new page! Error code: " + e.Message);
string xml2importBase = "<?xml version=\"1.0\"?>\n<one:Section xmlns:one=\"http://schemas.microsoft.com/office/onenote/2007/onenote\" ID=\"";
xml2importBase += unfiledID + "\">\n";
xml2importBase += "<one:Page ID=\"" + importedPageID + "\">\n";
xml2importBase += "<one:Title>\n<one:OE>\n<one:T><![CDATA[Sent Files]]></one:T>\n</one:OE>\n</one:Title>\n";
string tailXml = "</one:Page>\n</one:Section>";
bool succeeded = false;
foreach (string s in args)
string xml2import = xml2importBase + "<one:InsertedFile pathSource=\"" + s + "\"></one:InsertedFile>\n";
xml2import += tailXml;
succeeded = true;
if (args.Length == 1)
catch (Exception e1)
MessageBox.Show("Could not delete page and error on insert, bailing! Error: " + e1.Message);
MessageBox.Show("You cannot import a folder into OneNote!");
//supressed, we just hit a folder but we will jsut keep on going...
//MessageBox.Show("Couldn't import " + s + " into OneNote. Error code: " + e.Message);
MessageBox.Show("Failed to delete the page with nothing on it. Error: " + e.Message);
//add code to remove this stuff!
MessageBox.Show("You cannot send folders to OneNote!");
onApp.NavigateTo(importedPageID, null, false);
*wipes brow* Okay lots going on here so I will take look @ each part.
This code will create a new page, with CreateNewPage, in the section that I supply with unfiledID and then it will output the new pageID. If it fails then we capture that error code but in most cases this should never fail, but you _just_ never know.
string tailXml = "</one:Page>\n</one:Section>";
This might seem like a lot of code but what I am doing is going through each string in the arguments (that came from Windows Explorer when I chose to send to OneNote).
There is a lot more going on with this code for example I put all of the XML together and you can see to embed a file you only need to provide the pathSource. I then send this to OneNote with the UpdateHierarchy method, you might ask why I do this for each individual file instead of creating the XML for all of the files and import that together? I did this because I wanted my imports to be more transactional; if something failed to import I wanted to know more about it and have something atomic that I could rollback if need be. It also made my code pretty clean and easy (imho).
If we failed on the import that means that we tried to insert something which cannot be embedded which was probably a folder. If the user only tried to import the folder this is invalid and we throw an error to the user. I also go ahead and delete the page that I just created, otherwise the user would have a blank page in their Unfiled Notes.
However if we were successful I go through and do this for each file that was passed to our app.
The last steps would be to test this out and put a shortcut in your SendTo folder under your user profile. At some point I hope to package this all up and make it a download that anyone can easily use. I guess I will have to wait until RTM when we don't have any more changes in the code.
As always I appreciate your feedback and thoughts on this, hope you learned something.
Update: I am including the source as well, you can find it here: SendtoOneNote.zip
PingBack from http://www.onenotepowertoys.com/2006/10/04/send-to-onenote-from-windows-explorer-sample-app/
Nice example. Thanks.
I thank you for your time and efforts to keep us abreast of these applications with Windows Explorer. I don't usually have good usage of them either (e.g., at times). But, anyway THNAK YOU for your TIME.
Thank you for the great example. My 11 yr old son is interested in learning program code and this will make a great example. I am not going to let him download the zip file but have him enter the code following your instructions. It has been more than 20 yrs since I programed so you know how out of date I am. If this question is too revealing of my ignorance please bear with me. Will this code work for OneNote 2003 SP1? If not can it be easily adapted? and can you tell me how?
Thank you, I have never run across code like this before .. I want to look for more ... my son will enjoy learning from practical applications that the whole family can use.
This code will not work with OneNote 2003, only OneNote 2007 so sadly you would need to download the trial or find some other code. That being said I have some pointers for you:
o Code4Fun (http://msdn.microsoft.com/coding4fun/default.aspx) which is a site to help kids learn how to program.
o Camp CAEN (http://www.engin.umich.edu/caen/campcaen/) this is a camp that I used to work at. During my time there I taught a great many kids how to program in Java. I am sure there are other camps nearby where you live if you aren't in the midwest.
Hope this helps and please keep your son interested in programming! Take care
Finally a powertoy that I wrote! This is a small application that I blogged about before where I included
Lo trovo piuttosto impressionante. Lavoro grande fatto..)
9 su 10! Ottenerlo! Siete buoni!
Interessieren. SEHR interessant! ;)
L'information interessante que vous avez! I'am allant revenir bientot.
pagine piuttosto informative, piacevoli =)
Is there any way to open One Note 2007 application using VB script/Java script?
I tried this VB script ...this failes because VB script is not supporting OUT parameter
set oNote = CreateObject("OneNote.Application")
oNote.OpenHierarchy unfiledPath, "", unfiledID, 0
oNote.CreateNewPage unfiledID,importedPageID, 0
Dim xml2importBase 'As String
xml2importBase = "<?xml version=""1.0""?><one:Section xmlns:one=""http://schemas.microsoft.com/office/onenote/2007/onenote"" ID="""
xml2importBase = xml2importBase + unfiledID + """>"
xml2importBase = xml2importBase + "<one:Page ID=""" + importedPageID + """>"
xml2importBase = xml2importBase + "<one:Title><one:OE><one:T><![CDATA[Title Comes here-2]]></one:T></one:OE></one:Title>"
tailXml = "</one:Page></one:Section>"
xml2import = xml2importBase + tailXml
oNote.NavigateTo importedPageID, "", False
I know we cant send out parameter in the VB script.
So Is there any way to overcome this problem and make this script run?
Or can I import XML to the OneNote2007 application without SectionID and PageID?
Could you explain how to add the short cut key to the oneNote 2007 application in the SendTo option.
Alok - I don't programm in VB but you should search online and discuss with VB.Net developers who might be able to help you.
Kaushik - I don't understand your question, do you want to know how to add the shortcut key to this application? This wouldn't work so well since you would have to have a file path that you send to this application, I don't think it would do what you are interested in.