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

本文关键字:SIGBREAK 启动 服务 EXE 文件 | 更新日期: 2023-09-27 18:10:59

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

到目前为止,服务工作正常,我从注册表收集配置,然后启动服务。当服务停止时,我获取进程并发送. kill()。到目前为止一切顺利。但是我发现,. kill()是一个问题,因为ruby.exe(我使用thin启动服务)或java.exe(我用它启动SOLR)在tcp套接字端口上侦听。如果这个端口被使用并且我杀死了进程,窗口将阻塞端口72秒(按设计)。

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

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

所以我发现这个线程如何从windows服务运行exe并在exe进程退出时停止服务?张贴概念证明的地方。但是,如果从窗口服务启动进程,我就没有windowHandle了。

我像这样启动我的服务:

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

其中参数包含启动SOLR的jetty数据,或者在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,我想我甚至没有一个窗口,我不能像这样分配进程

所以有人知道我如何分配进程并向它发送停止信号吗?我可以忍受只是杀死进程,但这只是一个服务重启不可能等待很长时间。谢谢你的提示,技巧和解决方案。

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

GenerateConsoleCtrlEvent可能会工作

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

何时终止子应用程序…

 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);