/// <summary> /// Make a call into the OneNote application which is protected against recoverable errors. /// </summary> /// <param name="cmd">lambda function calling into the OneNote application object</param> /// <returns>Return value of the lambda function</returns> /// <typeparam name="Tresult">Return type of the protected lambda method</typeparam> /// <example>string id = onenote.ExecuteMethodProtected(o => {return o.Windows.CurrentWindow;});</example> private Tresult ExecuteMethodProtected <Tresult>(Func <Application, Tresult> cmd) { int retries = MAX_RETRIES; while (retries-- > 0) { try { return(cmd.Invoke(_on)); } catch (COMException ce) { if ((uint)ce.ErrorCode == 0x8001010A && retries >= 0) { // RPC_E_SERVERCALL_RETRYLATER TraceLogger.Log(TraceCategory.Info(), "OneNote busy. Retrying method invocation ..."); Thread.Sleep(1000); // wait until COM Server becomes responsive } else { TraceLogger.Log(TraceCategory.Error(), "Unrecoverable COM exception while executing OneNote method: {0}", ce.Message); TraceLogger.Log(TraceCategory.Error(), ce.StackTrace); TraceLogger.Log(TraceCategory.Error(), "Re-throwing exception"); throw; } } catch (Exception e) { TraceLogger.Log(TraceCategory.Error(), "Exception while executing OneNote method: {0}", e.Message); TraceLogger.Log(TraceCategory.Error(), e.StackTrace); throw; } } return(default(Tresult)); }
/// <summary> /// Create a new instance of a OneNote proxy. /// </summary> /// <param name="onenote">OneNote application object</param> internal OneNoteProxy(Application onenote) { _on = onenote; TaggingService = new BackgroundTagger(this); TaggingService.Run(); TraceLogger.Log(TraceCategory.Info(), "OneNote application proxy constructed successfully"); TraceLogger.Flush(); }
/// <summary> /// Find pages by full text search /// </summary> /// <param name="query"> query string</param> /// <param name="scopeID"> /// OneNote id of the scope to search for pages. This is the element ID of a /// notebook, section group, or section. If given as null or empty string scope is /// the entire set of notebooks open in OneNote. /// </param> /// <returns>XML page descriptors</returns> public XDocument FindPages(string scopeID, string query) { TraceLogger.Log(TraceCategory.Info(), "query={0}; Scope = {1}", query, scopeID); return(ExecuteMethodProtected <XDocument>(o => { string outXml; o.FindPages(scopeID, query, out outXml, false, fDisplay: false, xsSchema: OneNoteSchema); return XDocument.Parse(outXml); })); }
/// <summary> /// Get the XML descriptor of nodes in the OneNote hierarchy /// </summary> /// <remarks>Only basic information (as of OneNote 2010) is returned.</remarks> /// <param name="nodeID">id of the starting node</param> /// <param name="scope"> scope of the nodes to return</param> /// <returns>XML document describing the nodes in the OneNote hierarchy</returns> /// <exception cref="COMException">Call to OneNote failed</exception> public XDocument GetHierarchy(string nodeID, HierarchyScope scope) { TraceLogger.Log(TraceCategory.Info(), "Start Node = {0}; Scope = {1}", nodeID, scope); return(ExecuteMethodProtected <XDocument>(o => { string outXml; o.GetHierarchy(nodeID, scope, out outXml, OneNoteSchema); return XDocument.Parse(outXml); })); }
/// <summary> /// Find OneNote pages which have meta-data with a given key. /// </summary> /// <param name="scopeID"> /// search scope. The id of a node in the hierarchy (notebook, section group, or /// section) below which to search for content. If null or empty string, the search /// scope is the entire set of notebooks open in OneNote. for the search. /// </param> /// <param name="metadataKey">Key (name) of the meta-data</param> /// <returns>page descriptors of pages with the requested meta-data</returns> public XDocument FindPagesByMetadata(string scopeID, string metadataKey) { TraceLogger.Log(TraceCategory.Info(), "Scope = {0}; metaKey = {1}", scopeID, metadataKey); return(ExecuteMethodProtected <XDocument>(o => { string outXml; o.FindMeta(scopeID, metadataKey, out outXml, false, OneNoteSchema); return XDocument.Parse(outXml); })); }
/// <summary> /// Occurs whenever an add-in loads. /// </summary> /// <param name="custom"> /// An empty array that you can use to pass host-specific data for use when the /// add-in loads. /// </param> public void OnStartupComplete(ref Array custom) { TraceLogger.Log(TraceCategory.Info(), "Startup Arguments '{0}'", custom); try { XMLSchema s = _onProxy.OneNoteSchema; // cache the schema } catch (Exception ex) { TraceLogger.Log(TraceCategory.Error(), "{0} initialization failed: {1}", Properties.Resources.TaggingKit_About_Appname, ex); TraceLogger.Flush(); throw; } TraceLogger.Log(TraceCategory.Info(), "{0} initialization complete!", Properties.Resources.TaggingKit_About_Appname); TraceLogger.Flush(); }
/// <summary> /// Handle the connection to the OneNote application. /// </summary> /// <param name="app"> The instance of OneNote which added the add-in</param> /// <param name="ConnectMode"> /// Enumeration value that indicates the way the add-in was loaded. /// </param> /// <param name="AddInInst"> Reference to the add-in's own instance</param> /// <param name="custom"> /// An empty array that you can use to pass host-specific data for use in the add-in /// </param> public void OnConnection(object app, ext_ConnectMode ConnectMode, object AddInInst, ref Array custom) { try { TraceLogger.Log(TraceCategory.Info(), "Connection mode '{0}'", ConnectMode); _onProxy = new OneNoteProxy(app as Microsoft.Office.Interop.OneNote.Application); _dialogmanager = new AddInDialogManager(); TraceLogger.Flush(); } catch (Exception ex) { TraceLogger.Log(TraceCategory.Error(), "Connecting {0} failed: {1}", Properties.Resources.TaggingKit_About_Appname, ex); TraceLogger.Flush(); throw; } }
/// <summary> /// Occurs whenever OneNote shuts down while an add-in is running. /// </summary> /// <param name="custom"> /// An empty array that you can use to pass host-specific data for use in the add-in. /// </param> public void OnBeginShutdown(ref Array custom) { TraceLogger.Log(TraceCategory.Info(), "Beginning {0} shutdown; Arguments '{1}'", Properties.Resources.TaggingKit_About_Appname, custom); if (_dialogmanager != null) { _dialogmanager.Dispose(); _dialogmanager = null; } if (_onProxy != null) { _onProxy.Dispose(); _onProxy = null; } }
public void Dispose() { if (!_disposed) { _disposed = true; // We do not lock the window collection because closing a window also // attempts to lock that collection. foreach (System.Windows.Window w in _SingletonWindows.Values.ToArray()) { try { w.Dispatcher.Invoke(() => { TraceLogger.Log(TraceCategory.Info(), "Closing Window: {0}", w.Title); w.Close(); }); } catch (Exception e) { TraceLogger.Log(TraceCategory.Error(), "Closing window failed: {0}", e); } } } }
/// <summary> /// handle disconnection of the OneNote application. /// </summary> /// <param name="RemoveMode"> /// Enumeration value that informs an add-in why it was unloaded /// </param> /// <param name="custom"> /// An empty array that you can use to pass host-specific data for use after the /// add-in unloads. /// </param> public void OnDisconnection(ext_DisconnectMode RemoveMode, ref Array custom) { TraceLogger.Log(TraceCategory.Info(), "Disconnecting; mode='{0}'; Arguments: '{1}'", RemoveMode, custom); if (_dialogmanager != null) { _dialogmanager.Dispose(); _dialogmanager = null; } Trace.Flush(); GC.Collect(); GC.WaitForPendingFinalizers(); if (RemoveMode == ext_DisconnectMode.ext_dm_HostShutdown || RemoveMode == ext_DisconnectMode.ext_dm_UserClosed) { // a dirty hack to make sure the ddlhost shuts down after an exception // occurred. This is necessary to allow the add-in to be loaded // successfully next time OneNote starts (a zombie dllhost would prevent that) TraceLogger.Log(TraceCategory.Info(), "Forcing COM Surrogate shutdown"); Trace.Flush(); Environment.Exit(0); } }
/// <summary> /// register the logging utility with the tracing system. /// </summary> internal static void Register() { FileStream log = new FileStream(LogFile, FileMode.OpenOrCreate); // Creates the new trace listener. TextWriterTraceListener listener = new TextWriterTraceListener(log); Trace.Listeners.Add(listener); #if DEBUG string config = "Debug"; #else string config = "Release"; #endif Log(TraceCategory.Info(), "{0} logging activated.\r\n\tAddin-Version: {1}\r\n\t.net Framework Version: {2}\r\n\tConfiguration: {3}", Properties.Resources.TaggingKit_About_Appname, Assembly.GetExecutingAssembly().GetName().Version, Environment.Version, config ); Flush(); }
/// <summary> /// Action to open the "Related Pages" UI /// </summary> /// <param name="ribbon">OneNote ribbon bar</param> public void relatedPages(IRibbonControl ribbon) { TraceLogger.Log(TraceCategory.Info(), "Show related pages tracer"); _dialogmanager.Show <RelatedPages, RelatedPagesModel>(() => new RelatedPagesModel(_onProxy)); }
/// <summary> /// Occurs whenever an add-in is loaded or unloaded. /// </summary> /// <param name="custom"> /// An empty array that you can use to pass host-specific data for use in the add-in. /// </param> public void OnAddInsUpdate(ref Array custom) { TraceLogger.Log(TraceCategory.Info(), "{0} update initiated; Arguments '{1}'", Properties.Resources.TaggingKit_About_Appname, custom); }
/// <summary> /// Action to open a tag management dialog. /// </summary> /// <param name="ribbon"></param> public void manageTags(IRibbonControl ribbon) { TraceLogger.Log(TraceCategory.Info(), "Show settings editor"); AddInDialogManager.ShowDialog <TagManager, TagManagerModel>(() => new TagManagerModel(_onProxy)); }
/// <summary> /// Action to open the search tags UI /// </summary> /// <param name="ribbon">OneNote ribbon bar</param> public void findTags(IRibbonControl ribbon) { TraceLogger.Log(TraceCategory.Info(), "Show tag finder"); _dialogmanager.Show <FindTaggedPages, FindTaggedPagesModel>(() => new FindTaggedPagesModel(_onProxy)); }
/// <summary> /// Action to open a tag editor dialog. /// </summary> /// <remarks>Opens the page tag editor</remarks> /// <param name="ribbon">OneNote ribbon bar</param> public void editTags(IRibbonControl ribbon) { TraceLogger.Log(TraceCategory.Info(), "Show tag editor"); _dialogmanager.Show <TagEditor, TagEditorModel>(() => new TagEditorModel(_onProxy)); }
/// <summary> /// Get the ribbon definition of this add-in /// </summary> /// <param name="RibbonID">identifier of the ribbon</param> /// <returns>ribbon definition XML as string</returns> public string GetCustomUI(string RibbonID) { TraceLogger.Log(TraceCategory.Info(), "UI configuration requested: {0}", RibbonID); return(Properties.Resources.ribbon); }