【问题标题】:Cannot evaluate expression because a native frame is on top of the call stack无法评估表达式,因为本机框架位于调用堆栈的顶部
【发布时间】:2012-06-01 14:01:02
【问题描述】:

我正在创建一个简单的窗口服务,当我进行调试时,我收到错误消息“无法评估表达式,因为本机框架位于调用堆栈的顶部。”。此外,当我在 Release 中构建服务并运行它时,它只是挂起。

 static void Main()
    {
        ServiceBase[] ServicesToRun;
        ServicesToRun = new ServiceBase[] { new MyService1() };

        ServiceBase.Run(ServicesToRun);
    }

这就是 Program.cs 文件中的全部内容,它通常挂在 ServiceBase.Run(ServicesToRun) 行上。

我能找到的所有内容都只与未评估的表达式有关,因为代码已优化或必须处理 asp.net 和 response.redirect。

服务代码。

    public TruckRateClearService()
    {
        InitializeComponent();
    }

    protected override void OnStart(string[] args)
    {
        tmrProcess.Enabled = true;
    }

    protected override void OnCustomCommand(int command)
    {
        base.OnCustomCommand(command);
        if (command == 129)
        {
            OnStart(null);
        }
    }

    protected override void OnStop()
    {
        tmrProcess.Enabled = false;
    }

    private void tmrProcess_Tick(object sender, EventArgs e)
    {
        tmrProcess.Enabled = false;

        try 
        {
            eventLog.WriteEntry("Clearing Truck Rates Start" + DateTime.Now.ToString());

            TruckRateClearingAgent.Process();

            eventLog.WriteEntry("Clearing Truck Rates Finished" + DateTime.Now.ToString());
        }
        catch (Exception ex)
        {
            eventLog.WriteEntry(ex.ToString(), EventLogEntryType.Error);
        }

        tmrProcess.Enabled = true;
    }

    internal void Run()
    {
        tmrProcess_Tick(tmrProcess, null);
    }

Internal Void Run() 是最近根据 Eren Ersönmez 在 cmets 中的建议添加的。他的想法对帮助我调试逻辑非常有帮助,直到我弄清楚其余部分。

我能够进入本机调用堆栈,它位于一个位置,76F17094 ret。现在我不知道这是什么,但也许其他人会。

此外,当我启动服务并考虑将其附加到 VS 时,我注意到它的两个实例。一个是普通的 .exe,另一个是 .vshost.exe。当我启动其他服务时,我只在 Attach to process 调试器的一部分中看到 .exe 文件。这可能是因为一个在 v4 框架(.vshost .exe 服务)上,另一个在 v2(单个 .exe 服务)框架上?

我相信我成功了。看来问题出在我使用的计时器上。我使用的原始计时器是 System.Windows.Forms 计时器。我将它切换到 System.Timers.Timers 并且一切都重新开始工作。仍然无法将 VS 附加到它,但我仍然可以使用 Internal Run() 方法对其进行调试。感谢所有的帮助n.n

【问题讨论】:

    标签: c# windows-services


    【解决方案1】:

    您的主要问题是您试图直接运行 Windows 服务 exe。 Windows 服务只能通过服务控制管理器 (SCM) 启动。为了能够在 VS 中进行调试,我建议如下:

    static void Main()
    {
        if (Environment.UserInteractive)
        {
            new MyService1().Run();
            Thread.Sleep(Timeout.Infinite);
        }
        else
        {
            ServiceBase.Run(new ServiceBase[] { new MyService1() });
        }
    }
    

    您将创建一个MyService1.Run 方法,该方法会生成一个运行服务循环的新线程。此外,您可以从MyService1.Onstart 中调用相同的Run 方法。

    此方案在被单片机启动时作为服务运行,但在VS中调试(或在VS外直接作为exe运行)时将其视为普通exe。

    【讨论】:

      【解决方案2】:

      问题

      此通知表示线程当前正在执行非托管代码,因此不能用于计算表达式。

      在某些情况下,您可以等待调用返回托管代码,然后再计算表达式。不幸的是,在这种情况下,在您关闭服务之前不会发生这种情况。

      另一种选择

      您可以考虑覆盖 ServiceBase.OnCustomCommand 方法并在其中放置一个断点,以便您可以评估您的表达式。

      protected override void OnCustomCommand(int command)
      {
         //Debugger.Break()   <- or just put a breakpoint in here.
      }
      

      您可以按如下方式调用自定义命令:

      c:\>sc control YourServiceName 129
      

      【讨论】:

      • 我把所有东西都放好了,然后执行了命令,它成功了。但是,当我退出该功能时,它不会让我进一步前进。当我去 Debug->Break All 时,它是在服务失败的同一点。我想我在这里做错了。
      • 你看到什么样的失败?挂起还是异常?
      • 与我在“无法评估表达式...”之前得到的相同。服务是否会挂在 ServiceBase.Run(ServicesToRun) 部分。
      • 哦,我以为您只是想使用“快速观看”窗口。现在听起来您想要在应用程序代码中设置断点。是否为要调试的程序集加载了符号? (您可以在输出窗口中找到(ctrl+alt+o))
      • 符号已加载,我永远无法在 Program.cs 文件中触发断点。
      【解决方案3】:

      您看到的异常意味着非托管代码正在引发异常,因此 .NET 调试器无法向您显示通常有用的详细信息。

      你在 MyService1() 中做什么?能把里面的代码贴出来吗?

      您还尝试通过从环境中启动服务来调试服务。那可能行不通。

      我通常会这样写:

      static void Main(params string[] args)
      {
         if (args.Length > 0 && args[0] == "/console")
         {
            // Run whatever your service calls here
         }
         else
         {
            ServiceBase[] ServicesToRun;
            ServicesToRun = new ServiceBase[] { new MyService1() };
      
            ServiceBase.Run(ServicesToRun);
        }
      }
      

      然后在“调试”选项卡下的项目属性中输入/console 作为命令行参数。您应该能够进入应用程序并对其进行调试。您只能通过先安装来调试服务:http://msdn.microsoft.com/en-us/library/7a50syb3(v=vs.80).aspx

      【讨论】:

      • 我最初是在重新安装服务并将 VS 附加到它。我查看了 Eren 的建议并将其添加到我的代码中,这样我就可以使用普通的调试器了。但是,我还没有找到任何非托管代码。进入项目的属性并打开“允许不安全代码”是否安全?
      猜你喜欢
      • 1970-01-01
      • 2012-07-11
      • 2012-10-22
      • 1970-01-01
      相关资源
      最近更新 更多