在OpenOffice中,如何检查我的XComponentContext是否已关闭?

5

我是一个小应用程序,可以在OOo Writer中生成三种不同的模板文档。当单击其中一种“生成”按钮时,以下代码将被执行(使用C#):

// Connect to OOo
if (componentContext == null)
    componentContext = uno.util.Bootstrap.bootstrap();
XMultiServiceFactory multiServiceFactory =
    (XMultiServiceFactory) componentContext.getServiceManager();
XComponentLoader loader = (XComponentLoader)
    multiServiceFactory.createInstance
        ("com.sun.star.frame.Desktop");

// Initialize class members document, text, and cursor
document = (XTextDocument) loader.loadComponentFromURL
    ("private:factory/swriter", "_blank", 0,
     new PropertyValue[0]);
text = document.getText();
cursor = text.createTextCursor();

以下步骤会导致崩溃:
  1. 用户生成一个文档。
  2. 用户关闭该文档 (关闭OOo)。
  3. 用户试图生成另一个文档。
将会抛出以下异常:
unoidl.com.sun.star.lang.DisposedException: URP-Bridge: disposed(tid=4) Unexpected connection closure

在尝试生成另一个图表之前,如何检查连接是否仍然打开?如果已关闭,如何重新连接?

编辑:更具体地说,这是完整的错误消息:

Marshaling clicked signal
Exception in Gtk# callback delegate
  Note: Applications can use GLib.ExceptionManager.UnhandledException to handle the exception.
System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. ---> unoidl.com.sun.star.lang.DisposedException: URP-Bridge: disposed(tid=4) Unexpected connection closure
  at com.sun.star.bridges.mono_uno.UnoInterfaceProxy.ConstructReturnMessage (Any result, System.Object[] args, uno.Typelib.InterfaceMethodTypeDescription* methodTD, IMethodCallMessage callmsg, Any exception) [0x00000] 
  at com.sun.star.bridges.mono_uno.UnoInterfaceProxy.Invoke (IMessage request) [0x00000] 
  at System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke (System.Runtime.Remoting.Proxies.RealProxy rp, IMessage msg, System.Exception& exc, System.Object[]& out_args) [0x00000] 
  --- End of inner exception stack trace ---
  at System.Reflection.MonoMethod.Invoke (System.Object obj, BindingFlags invokeAttr, System.Reflection.Binder binder, System.Object[] parameters, System.Globalization.CultureInfo culture) [0x00000] 
  at System.Reflection.MethodBase.Invoke (System.Object obj, System.Object[] parameters) [0x00000] 
  at System.Delegate.DynamicInvokeImpl (System.Object[] args) [0x00000] 
  at System.MulticastDelegate.DynamicInvokeImpl (System.Object[] args) [0x00000] 
  at System.Delegate.DynamicInvoke (System.Object[] args) [0x00000] 
  at GLib.Signal.ClosureInvokedCB (System.Object o, GLib.ClosureInvokedArgs args) [0x00000] 
  at GLib.SignalClosure.Invoke (GLib.ClosureInvokedArgs args) [0x00000] 
  at GLib.SignalClosure.MarshalCallback (IntPtr raw_closure, IntPtr return_val, UInt32 n_param_vals, IntPtr param_values, IntPtr invocation_hint, IntPtr marshal_data) [0x00000] 
   at GLib.ExceptionManager.RaiseUnhandledException(System.Exception e, Boolean is_terminal)
   at GLib.SignalClosure.MarshalCallback(IntPtr raw_closure, IntPtr return_val, UInt32 n_param_vals, IntPtr param_values, IntPtr invocation_hint, IntPtr marshal_data)
   at Gtk.Application.gtk_main()
   at Gtk.Application.Run()
   at TestDrive.MainClass.Main(System.String[] args) in /home/matthew/Dropbox/OpenSBS-mono/TestDrive/Main.cs:line 28

The application was terminated by a signal: SIGHUP

如果我删除这行代码 if (componentContext == null) (即,尝试连接时不考虑是否已经连接),我会得到一个堆栈跟踪并伴随着这个消息:
=================================================================
Got a SIGSEGV while executing native code. This usually indicates
a fatal error in the mono runtime or one of the native libraries 
used by your application.
=================================================================

我也遇到了同样的问题。你有没有想到解决方案或变通方法? - Dan Stevens
@Doomy:我的记忆有点模糊,但我相信这个(丑陋的)解决方法有效:我创建了一个单独的可执行文件,启动OOo并根据需要与其交互。每次我需要与OOo交互时,我从主程序中调用此辅助可执行文件(传递它所需的任何参数)。因为我在一个辅助可执行文件的一次调用中只打开了一次OOo,所以我可以避免这个错误。 - Matthew
感谢您的回复。我的解决方法是安装OpenOffice Quickstarter功能,并确保在运行我的应用程序之前它已经在运行。 - Dan Stevens
2个回答

2
这只是猜测。你可以使用XComponent.addEventListener并监听disposing事件。
例如:
class App :  XEventListener
{
    private XComponentLoader m_loader;

    private XComponentLoader Loader
    {
        get
        {
            if (m_loader == null)
            {
                m_loader = (XComponentLoader)multiServiceFactory.createInstance("com.sun.star.frame.Desktop");
                XComponent comp = (XComponent)m_loader;
                comp.addEventListener(this);
            }
            return m_loader;
        }
    }

    private void disposing(EventObject Source)
    {
        m_loader = null;
    }
}

这似乎不起作用。我在获取multiServiceFactory时遇到错误,而不是在获取loader时遇到错误,但更改您的代码以调整此问题似乎没有帮助。有趣的一件事是,当我关闭OOo时,“disposing”似乎不会为componentContext、multiServiceFactory或loader调用。只有文档调用disposing(并且尝试重新连接仍然会给我错误)。也许发生的情况是连接从未完全关闭,这就是bootstrap出错的原因。有什么想法吗? - Matthew

2
我发现如果运行OpenOffice Quickstarter应用程序(位于C:\ Program Files(x86)\ OpenOffice.org 3 \ program \ quickstart.exe ),则不会出现此错误。 quickstart.exe 似乎调用soffice.exe ,即使用户关闭最后一个文档窗口后,它仍将继续运行。
如果缺少quickstart.exe ,可以通过OpenOffice安装程序安装。您的应用程序可以使用System.Diagnostics.Process.Start() 启动quickstart.exe ,以确保soffice.exe 正在运行。如果已经在运行,则不会复制该进程。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接