我正在创建一个简单的窗口服务,当我去调试时,我得到错误,“无法计算表达式,因为本机帧位于调用堆栈的顶部。”此外,当我在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);
}
最近在ErenErsönmez的评论中添加了内部虚空运行()。他的想法对于帮助调试我的逻辑非常有帮助,直到我能够完成其余的工作。
我能够进入Native调用堆栈并且它位于一个位置,76F17094 ret。现在我不知道这是什么,但也许别人会。
此外,当我启动服务并考虑将其附加到VS时,我注意到它的两个实例。一个是正常的.exe,另一个是.vshost.exe。当我启动其他服务时,我只看到Attach for process部分调试器中的.exe文件。这可能是因为一个是v4框架(.vshost .exe服务)而另一个是v2(单个.exe服务)框架?
我相信我让它运转了。似乎问题与我使用的计时器有关。我使用的原始计时器是一个System.Windows.Forms计时器。我把它切换到System.Timers.Timers,一切都开始工作了。仍然无法将VS附加到它但我仍然可以使用Internal Run()方法调试它。感谢所有帮助n.n
答案 0 :(得分:2)
问题
此通知表示该线程当前正在执行非托管代码,因此无法用于评估表达式。
在某些情况下,您可以在评估表达式之前等待调用返回托管代码。不幸的是,在这种情况下,直到关闭服务才会发生这种情况。
另类
您可以考虑覆盖ServiceBase.OnCustomCommand方法并在其中放置断点,以便评估表达式。
protected override void OnCustomCommand(int command)
{
//Debugger.Break() <- or just put a breakpoint in here.
}
您可以按如下方式调用自定义命令:
c:\>sc control YourServiceName 129
答案 1 :(得分: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
方法,该方法会生成一个运行服务循环的新线程。此外,您还可以在Run
内调用相同的MyService1.Onstart
方法。
此方案在由SCM启动时将其作为服务运行,但在VS中调试时(或直接作为VS外部的exe运行)将其视为普通exe。
答案 2 :(得分: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);
}
}
然后在Debug选项卡下的项目属性中输入/console
作为命令行参数。您应该能够进入应用程序并进行调试。您只能通过先安装服务来调试服务:http://msdn.microsoft.com/en-us/library/7a50syb3(v=vs.80).aspx