我已经编写了一个启动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,我想我甚至没有窗口我无法像这样分配这个过程。
那么有没有人知道如何分配流程并向其发送停止信号? 我可以忍住只是杀死这个过程,但这只是一个服务重启不可能没有等待很长时间。 感谢任何提示,技巧和解决方案。
答案 0 :(得分:1)
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);