C# 尝试调用COM库时,服务引发异常

C# 尝试调用COM库时,服务引发异常,c#,.net,windows-services,error-handling,C#,.net,Windows Services,Error Handling,我正在编写一个使用COM库的应用程序。我有一个类库,它包装了对COM库的调用,并添加了更多功能。最终,它将作为Windows服务运行。现在我使用Winforms测试工具来测试它 当测试线束创建类库时,一切似乎都正常工作。当我尝试将其作为服务运行时,问题就开始了。它被创建为OK,甚至对COM的第一次调用也是OK。然后,COM对象引发我处理的事件,并响应事件中的结果,调用COM库中的另一个函数。当我从测试线束运行该函数时,会成功调用该函数,但当作为服务运行时,会引发异常: System.Invali

我正在编写一个使用COM库的应用程序。我有一个类库,它包装了对COM库的调用,并添加了更多功能。最终,它将作为Windows服务运行。现在我使用Winforms测试工具来测试它

当测试线束创建类库时,一切似乎都正常工作。当我尝试将其作为服务运行时,问题就开始了。它被创建为OK,甚至对COM的第一次调用也是OK。然后,COM对象引发我处理的事件,并响应事件中的结果,调用COM库中的另一个函数。当我从测试线束运行该函数时,会成功调用该函数,但当作为服务运行时,会引发异常:

System.InvalidCastException发生消息=“无法转换COM 类型为“”的对象到接口类型“”。此操作失败,因为 与的接口的COM组件上的QueryInterface调用 IID“{350ADD2A-18CB-4D9C-BE28-48D53F14E6FB}”由于以下原因失败: 以下错误:应用程序调用的接口 已为其他线程封送。(HRESULT异常:0x8001010E (RPC_E_错误_线程))。”


我可以看出存在线程问题。在测试线束的情况下,所有这些调用都发生在主线程上,而在Windows服务的情况下,Service OnStart override和COM事件处理程序都位于不同的线程上。我一直在尝试不同的事情,但都没有成功。有什么建议吗?

某些COM组件只能由STA线程访问。如果你的情况是这样的, 您可以在STA线程中执行COM工作,如下所示:

RunInSTAThread( () => com_object.DoSomething() );

private static void RunInSTAThread(ThreadStart thread_start)
        {
            Exception threadEx = null;
            ThreadStart wrapped_ts = () =>
                                         {
                                             try
                                             {
                                                 thread_start();
                                             }
                                             catch (Exception ex)
                                             {
                                                 MethodInfo preserveStackTrace =
                                                     typeof(Exception).GetMethod("InternalPreserveStackTrace",
                                                                                 BindingFlags.Instance | BindingFlags.NonPublic);
                                                 preserveStackTrace.Invoke(ex, null);
                                                 threadEx = ex;
                                             }
                                         };
            Thread thread = new Thread(wrapped_ts);
            thread.SetApartmentState(ApartmentState.STA);
            thread.Start();
            thread.Join();
            if (threadEx != null)
            {
                throw threadEx;
            }
        }

对于您的情况,这可能不是线程(每次调用都有一个新线程)的最佳使用,但这是一个起点。

Win服务是否与Winforms应用程序在同一用户帐户下运行?

现在已解决。我不得不重新整理这些线。现在COM对象和对它的所有调用都在同一个线程上,没有线程间问题。
在普通情况下如何处理这个问题仍然不清楚。

我刚刚关闭了项目并再次打开它,错误得到了解决

你能提供一些示例代码吗?@Jeremy Lew:它也完全不需要。创建RCW时,如果对象是在非STA线程上创建的,CLR将把对象放在它自己的线程中。您也没有在STA线程上发送消息,这是处理STA COM对象的必要条件。我仍然不清楚为什么它从Winforms启动时有效,而不是从服务启动时有效。我只是作为用户尝试了一下,结果基本相同。