2011-05-11 33 views
3

我有一个Windows服务,监视连接到供应商硬件的COM端口。这是一个非常繁忙的硬件,它不断地轮询线路上的其他设备(这是一个双绞线RS485“网络”)。我的软件需要在这条线上模拟X个硬件设备,所以我有一个多线程的事情在多层状态机上进行,以跟踪通信协议在任何时刻的位置。Windows服务的运行时调试提示?

问题是与Windows服务(这是我的第一个,顺便说一句)是,你需要一些调试,让你知道如果东西工作正常。当我第一次开发这个状态机/多线程代码时,我有一个带有RichTextBox的窗体,它显示了ASCII字符后退n行。似乎我不能真正拥有一个服务的GUI好看。我尝试通过另一个程序打开服务中的窗体,该程序发送通过OnCustomCommand()处理程序接收到的服务消息,但它似乎不起作用。我有“允许服务与桌面交互”选中和一切。我正在使用我的调试表单的Show()和Hide()方法。

我想我不需要看到所有的单个角色都行,但是那个人肯定会很好(我想我真的需要看到他们:-))。那么有没有人有任何疯狂的想法可以帮助我?我不想让IPC陷入困境,但这并不意味着大量的数据肯定会通过。它只是非常短期的调试,只是确认程序,RS485到USB加密狗和硬件都在工作。

回答

0

我在这里回答我自己的问题。我在这里尝试了几个建议,但这里是我最终做的...

我创建了一个带有单个按钮和RichTextBox的Windows窗体应用程序。这个应用程序构建了一个NamedPipeServerStream。该按钮的工作是将“调试开启”(命令128)或“调试关闭”(129)发送到Windows服务。初始值是“调试关闭”。点击该按钮后,将128的命令发送到Windows服务以打开调试。在Windows服务中,这触发了一个内部变量为true,并使用NamedPipeClientStream连接到Form应用程序,并开始使用BinaryWriter在COM端口上接收或发送字符时发送字符。在Form一侧,BackgroundWorker被创建为管道上的WaitForConnection()。当它获得连接时,使用BinaryReader.ReadString()从管道读取数据并将其发送到RichTextBox。

我快到了。当我再次点击调试按钮时,我打破了我的管道,随后的点击不能正确地重做管道。总而言之,我对此感到满意。如果有人感兴趣,我可以发布任何代码。感谢您的回应!

1

您可以将输出写入日志文件,然后使用其他应用程序观看该文件。这个关于"tail"的问题概述了几个使用windows观看日志文件的选项。

2

我不知道它是否适用于您,但我总是使用额外的Main构建我的服务,将它们构建为控制台应用程序以获取调试输出。

编辑:

一些示例:

class Worker : ServiceBase 
{ 

#if(RELEASE) 
     /// <summary> 
     /// The Main Thread where the Service is Run. 
     /// </summary> 
     static void Main() 
     { 
      ServiceBase.Run(new Worker()); 
     } 
#endif 

#if(DEBUG) 
     public static void Main(String[] args) 
     { 
      Worker worker = new Worker(); 
      worker.OnStart(null); 
      Console.ReadLine(); 
      worker.OnStop(); 
     } 
#endif 

     // Other Service code 
} 
+0

它可能适用于我,但我需要更多细节。 – 2011-05-11 17:34:32

+0

@凯利编辑完成 – sra 2011-05-11 17:52:25

4

使用OutputDebugString写入调试缓冲区,然后用DebugView观看。如果您在Windows XP或更低版本上运行,则可以使用PortMon来查看通过串行端口的原始字节。与日志文件相比,优势非常小,特别是当您不在观看时。您甚至可以从另一台机器运行DebugView并远程监视您的服务。

+0

我必须做错事,因为它不工作。如果我理解正确,我应该能够在任何地方转储Debug.WriteLine()语句并运行此程序,但我没有收到任何东西。 – 2011-05-11 19:06:59

+0

我想我现在有它,但我必须使用Debug.WriteLine()。 – 2011-05-11 19:40:17

0

我在处理Windows服务时通常会做的是创建它,以便它既可以作为服务运行,也可以作为普通的旧命令行应用程序运行。您可以通过检查Environment.UserInteractive轻松检查您是否作为服务运行。如果此属性为true,那么您正在从命令行运行。如果该属性为假,那么您就作为服务运行。该代码添加到Program.cs中,并使用它,你通常会调用ServiceBase.Run(servicesToRun)

/// <summary>Runs the provided service classes.</summary> 
/// <param name="servicesToRun">The service classes to run.</param> 
/// <param name="args">The command-line arguments to pass to the service classes.</param> 
private static void RunServices(IEnumerable<ServiceBase> servicesToRun, IEnumerable args) 
{ 
    var serviceBaseType = typeof(ServiceBase); 
    var onStartMethod = serviceBaseType.GetMethod("OnStart", BindingFlags.Instance | BindingFlags.NonPublic); 
    foreach (var service in servicesToRun) 
    { 
     onStartMethod.Invoke(service, new object[] { args }); 
     Console.WriteLine(service.ServiceName + " started."); 
    } 

    Console.WriteLine("Press any key to exit."); 
    Console.ReadKey(); 

    var onStopMethod = serviceBaseType.GetMethod("OnStop", BindingFlags.Instance | BindingFlags.NonPublic); 
    foreach (var service in servicesToRun) 
    { 
     onStopMethod.Invoke(service, null); 
     Console.WriteLine(service.ServiceName + " stopped."); 
    } 
} 

现在可以调试您的服务,设置断点,任何你想要的。当你运行你的应用程序时,你会得到一个适合显示控制台消息的控制台窗口,它将保持打开状态,直到你点击一个键。