5

我正在创建一个简单的窗口服务,当我去调试时,我收到错误消息“无法评估表达式,因为本机框架位于调用堆栈的顶部。”。此外,当我在 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);
    }

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

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

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

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

4

3 回答 3

2

您的主要问题是您试图直接运行 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方法来生成一个运行服务循环的新线程。此外,您可以RunMyService1.Onstart.

该方案在由 SCM 启动时将其作为服务运行,但在 VS 中调试时将其视为普通 exe(或在 VS 外部直接作为 exe 运行)。

于 2012-06-01T14:22:22.540 回答
2

问题

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

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

替代

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

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

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

c:\>sc control YourServiceName 129
于 2012-06-01T14:07:15.987 回答
0

您看到的异常意味着非托管代码正在引发异常,因此 .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

于 2012-06-01T14:19:27.953 回答