WatiN:当前线程需要将其ApartmentState设置为ApartmentState.STA,才能自动化Internet Explorer。

26

我正在从C# Windows服务中调用WatiN。当我调用WatiN时,它抛出以下异常:“CurrentThread 需要将其 ApartmentState 设置为 ApartmentState.STA 才能自动化 Internet Explorer。”

我尝试启动一个线程并通过以下方式设置 ApartmentState:

mythread.SetApartmentState(ApartmentState.STA)

但这导致了另一个错误。

无法评估表达式,因为代码已被优化或本机框架位于调用栈顶部。

我还尝试向服务入口点添加属性。

static class Program
{
      [STAThread]
      static void Main()
      {
          ...

有什么想法吗?


2
我不理解第二个(粗体)错误。你能展示更多的代码吗?我有一个类似的需求,创建一个新线程,设置ApartmentState并调用.Start(),然后跟着.Join() - 基本上只在STA绑定的东西里面工作 - 对我来说很好用。 - Benjamin Podszun
进一步澄清一下,我在我的服务中创建了一个线程,并设置了SetApartmentState(ApartmentState.STA),以调用我的WATiN代码。这引发了以下异常。 - Jonathan
嗨,本杰明!确实你是正确的!我没有加入我的线程。你应该把它发布为答案 ;) - Jonathan
3个回答

18

我知道Benjamin已经发布了一个“可行”的答案,但是当我尝试执行WatiN测试时遇到这个错误时,我想补充一些我经历过的事情: 对于NUnit,你应该在app.config中为测试添加类似于以下内容的东西:

  <configSections>
    <sectionGroup name="NUnit">
      <section name="TestRunner" type="System.Configuration.NameValueSectionHandler"/>
    </sectionGroup>
  </configSections>
  <NUnit>
    <TestRunner>
      <!-- WatiN can only host IE in STA mode -->
      <add key="ApartmentState" value="STA"/>
    </TestRunner>
  </NUnit>

在 MbUnit 中,将您的 TestFixture 属性修改如下:

[TestFixture(ApartmentState = ApartmentState.STA)] 

谢谢,Pete。

哈哈 - 实际上这在文档中有说明。唉! http://watin.org/documentation/sta-apartmentstate/


3
当你想让WatiN与IE在你的测试项目中正常工作时,这是最有帮助的答案。感谢Pete! - Oliver
对于 NUnit 2.5 及以上版本,这对我不起作用,这个答案有效:https://dev59.com/v3E95IYBdhLWcg3wJKl_#5293312 - toni
链接已失效。 - Jephren Naicker
发现了一个教程 https://www.c-sharpcorner.com/UploadFile/27c648/automated-ui-test-with-watin-and-specflow-in-net-part-1777/。 - Jephren Naicker

9
那不是错误,而是调试器的诊断信息。 它告诉您它无法在监视窗口中显示任何内容的调试信息。这在使用“发布”配置进行编译的代码中很常见,JIT编译器优化机器代码并通常将本地变量放在CPU寄存器中。 这使得它们的值对调试器不可用,因为它无法找出使用了哪个寄存器。 当调用堆栈上存在非托管代码时,也会在“调试”版本中偶尔发生这种情况。 对于WebBrowser来说,这种情况并不少见,其中有大量的非托管代码使其正常工作。
顺便提一下,仅将线程的公寓状态切换为STA是不够的。 线程还必须泵送Windows消息循环,以使单线程公寓正常运作。 如果您没有这样做,您将看到像WebBrowser这样的STA对象的操作将导致死锁。 例如,当您导航到站点时,您将永远不会收到DocumentCompleted事件。 运行消息循环需要在WF应用程序中调用Application.Run()或Form.ShowDialog()。

那非常有道理! - Jonathan
非常感谢。加入线程有助于解决问题! - Jonathan

3

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