我已经编写了一个启动java.exe或ruby.exe的服务(我知道有一些解决方案,但由于某些原因需要我自己的服务)。从服务启动一个EXE文件,并通过发送SIGBREAK来停止它
到目前为止,该服务的工作发现,我从注册表收集我的配置,然后启动服务。当服务停止时,我得到我的进程并发送.Kill()。 目前为止这么好。 但我发现,.Kill()是一个问题,因为ruby.exe(我使用thin来启动服务)或java.exe(我用它启动一个SOLR)在一个tcp套接字上侦听港口。如果这个端口被使用,并且我终止进程窗口将阻塞端口72秒(按设计)。
如果我从shell命令shell执行solr:start和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();
如果参数contais码头数据开始SOLR或红宝石情况下,我用“ruby.exe薄开始......”。
现在就停止服务,我试过:
[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,我想我甚至不有一个窗口,我不能分配这样的过程。
那么有没有人有一个想法,我可以如何分配进程并发送停止信号给它? 我可以生活在只是杀死进程,但这只是一个服务重启不可能等待很长时间。 感谢您提供任何提示,提示和解决方案。
Windows不会做信号。这是* nix丑陋。 – cHao
Pinvoke GenerateConsoleCtrlEvent()。 –
您是否尝试过'Process.CloseMainWindow()'([MSDN](http://msdn.microsoft.com/zh-cn/library/system.diagnostics.process.closemainwindow.aspx))? – AntonR