/// <summary> /// Show a singleton WPF dialog. /// </summary> /// <typeparam name="T">dialog type</typeparam> /// <typeparam name="M">view model type</typeparam> /// <param name="viewModelFactory">factory lambda function to create a view model</param> /// <returns>dialog result</returns> public static bool?ShowDialog <T, M>(Func <M> viewModelFactory) where T : System.Windows.Window, IOneNotePageWindow <M>, new() where M : WindowViewModelBase { bool?retval = null; var thread = new Thread(() => { try { System.Windows.Window w = new T(); w.Closed += (s, e) => w.Dispatcher.InvokeShutdown(); w.Topmost = true; M viewmodel = viewModelFactory(); ((IOneNotePageWindow <M>)w).ViewModel = viewmodel; var helper = new WindowInteropHelper(w) { Owner = (IntPtr)viewmodel.OneNoteApp.CurrentWindow.WindowHandle }; BringWindowIntoView(w); retval = w.ShowDialog(); Trace.Flush(); } catch (Exception ex) { TraceLogger.Log(TraceCategory.Error(), "Exception while creating dialog: {0}", ex); TraceLogger.ShowGenericErrorBox(Properties.Resources.TagEditor_Error_WindowCreation, ex); } }); thread.SetApartmentState(ApartmentState.STA); thread.IsBackground = true; thread.Start(); thread.Join(); return(retval); }
/// <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> /// Show a WPF window. /// </summary> /// <typeparam name="W">window type</typeparam> /// <typeparam name="M">view model type</typeparam> /// <param name="viewModelFactory">factory method to generate the view model in the UI thread of the WPF window</param> public void Show <W, M>(Func <M> viewModelFactory) where W : System.Windows.Window, IOneNotePageWindow <M>, new() where M : WindowViewModelBase { var thread = new Thread(() => { try { lock (_SingletonWindows) { System.Windows.Window w; if (_SingletonWindows.TryGetValue(typeof(W), out w)) { w.Dispatcher.Invoke(() => { w.WindowState = WindowState.Normal; BringWindowIntoView(w); }); return; } w = new W(); w.Closing += (o, e) => UnregisterWindow(typeof(W)); w.Closed += (s, e) => w.Dispatcher.InvokeShutdown(); M viewmodel = viewModelFactory(); ((IOneNotePageWindow <M>)w).ViewModel = viewmodel; var helper = new WindowInteropHelper(w) { Owner = (IntPtr)viewmodel.OneNoteApp.CurrentWindow.WindowHandle }; w.Show(); BringWindowIntoView(w); _SingletonWindows.Add(typeof(W), w); } // Turn this thread into an UI thread System.Windows.Threading.Dispatcher.Run(); } catch (ThreadAbortException ta) { TraceLogger.Log(TraceCategory.Warning(), "Window Thread aborted: {0}", ta); } catch (Exception ex) { TraceLogger.Log(TraceCategory.Error(), "Exception while creating dialog: {0}", ex); TraceLogger.ShowGenericErrorBox(Properties.Resources.TagEditor_Error_WindowCreation, ex); } }); thread.SetApartmentState(ApartmentState.STA); thread.IsBackground = true; thread.Start(); }
/// <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> /// log a message. /// </summary> /// <param name="category">logging category</param> /// <param name="message"> logging message</param> /// <param name="args"> parameters for the logging message</param> internal static void Log(TraceCategory category, string message, params object[] args) { #if TRACE Trace.Write(category.CallerName, category.Category); Trace.Write(" ("); Trace.Write(category.Line); Trace.Write(") | "); try { Trace.WriteLine(string.Format(message, args)); } catch (Exception ex) { Log(TraceCategory.Error(), "Logging failed {0}", ex); } #endif //TRACE }
/// <summary> /// Show an error box for an exception. /// </summary> /// <param name="message">Message to describe the failing operation</param> /// <param name="ex"> exception</param> internal static void ShowGenericErrorBox(string message, Exception ex) { TraceLogger.Log(TraceCategory.Error(), "{0}: {1}", message, ex); Trace.Flush(); MessageBoxResult result = MessageBox.Show(string.Format(Properties.Resources.TaggingKit_ErrorBox_GenericSevereError, message, ex.Message, TraceLogger.LogFile), string.Format(Properties.Resources.TaggingKit_ErrorBox_Title, Properties.Resources.TaggingKit_About_Appname), MessageBoxButton.OKCancel, MessageBoxImage.Error); if (result == MessageBoxResult.OK) { // browse to the troubleshooting tips string wikipage = "Troubleshooting-Tips"; COMException ce = ex as COMException; if (ce != null) { switch ((uint)ce.ErrorCode) { case 0x80042019: wikipage = "0x80042019"; break; case 0x8004200C: wikipage = "0x8004200C"; break; } } try { Process.Start(new ProcessStartInfo(string.Format(Properties.Resources.TaggingKit_Wiki_Page, wikipage))); } catch (Exception ex1) { TraceLogger.Log(TraceCategory.Error(), "Failed to open web browser: {0}", ex1); } } }
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); } } } }