从服务启动EXE文件并通过发送SIGBREAK停止它

时间:2011-10-12 14:37:49

标签: c# service process

我已经编写了一个启动java.exe或ruby.exe的服务(我知道有一些解决方案,但出于某些原因我需要自己的服务)。

到目前为止,服务工作找到了,我从注册表收集我的配置,然后启动服务。当服务停止时,我得到我的进程并发送一个.Kill()。 到现在为止还挺好。 但我发现,.kill()是一个问题,因为ruby.exe(我使用thin启动服务)或java.exe(我用它启动SOLR)监听tcp套接字端口。如果此端口正在使用并且我终止进程窗口将阻塞端口72秒(按设计)。

如果我执行solr:从shell命令shell启动并执行thin -start并使用Ctrl + C停止它,进程将终止,并且该端口可立即使用。

所以我的猜测是:如果我设法向进程发送一个ctrl-c,它就会正确终止。

所以我找到了这个帖子How to Run an exe from windows service and stop service when the exe process quits?,其中发布了一个概念证明。 但是通过从窗口服务启动进程,我没有windowHandle。

我开始这样的服务:

m_process.StartInfo = new ProcessStartInfo
                                  {
                                      FileName = "java"
                                      , Arguments = arguments
                                      , UseShellExecute = true
                                      , WorkingDirectory = workDirectory
                                      , CreateNoWindow = false
                                  };
m_process.Start();

如果参数包含jetty数据以启动SOLR,或者在ruby情况下,我使用“ruby.exe thin start ...”。

现在停止我试过的服务:

[DllImport("user32.dll", CharSet = CharSet.Auto)]
public static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
[DllImport("user32")]
public static extern int SetForegroundWindow(IntPtr hwnd);
[DllImport("user32.dll", SetLastError = true)]
public static extern void SwitchToThisWindow(IntPtr hWnd, bool fAltTab);

foreach (int i in m_processList)
  {
    MyLogEvent(Process.GetProcessById(i).MainModule.ModuleName);
    MyLogEvent(Process.GetProcessById(i).MainWindowTitle);
    try
    {
      IntPtr ptr = FindWindow(null, Process.GetProcessById(i).MainWindowTitle);
      {
        SetForegroundWindow(ptr);
        Thread.Sleep(1000);
        InputSimulator.SimulateModifiedKeyStroke(VirtualKeyCode.CONTROL, VirtualKeyCode.CANCEL);
        // SendKeys.Send("^{BREAK}");
        Thread.Sleep(1000);
      }
      //Process.GetProcessById(i).Kill();
    }
    catch(Exception ex)
    {
      MyLogEvent(ex.ToString());
      Process.GetProcessById(i).Kill();
    }
  }

但由于我没有WindowTitle,我想我甚至没有窗口我无法像这样分配这个过程。

那么有没有人知道如何分配流程并向其发送停止信号? 我可以忍住只是杀死这个过程,但这只是一个服务重启不可能没有等待很长时间。 感谢任何提示,技巧和解决方案。

1 个答案:

答案 0 :(得分:1)

GenerateConsoleCtrlEvent可能会有效

 m_process.StartInfo = new ProcessStartInfo
                              {
                                  FileName = "java"
                                  , Arguments = arguments
                                  , UseShellExecute = true
                                  , WorkingDirectory = workDirectory
                                  , CreateNoWindow = false
                              };
 var process = m_process.Start();

什么时候杀儿童app ...

 GenerateConsoleCtrlEvent(CTRL_C_EVENT, process.Id);

成员声明

 public const UInt32 CTRL_C_EVENT = 0;

[DllImport("kernel32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool GenerateConsoleCtrlEvent(uint dwCtrlEvent,
   uint dwProcessGroupId);