I have written a service which starts a java.exe or ruby.exe (I know there are some solutions but I need my own service for some reasons).
The service works find so far, I gather my configs from the registry, then start the services. When the service get stopped I get my processes and send a .Kill(). So far so good. But I found out, that the .Kill() is a problem due the fact that the ruby.exe (I use thin to start a service) or the java.exe (I start a SOLR with it) listen on a tcp socket port. If this port get in use and I kill the process windows will block the ports for 72 seconds (by design).
If I do a solr:start and a thin -start from a shell command shell and stop it using the Ctrl+C the processes terminate and the port is available to use instantly.
So my guess is: If I manage to send a ctrl-c to the process it terminate correctly.
So I found this thread How to Run an exe from windows service and stop service when the exe process quits? where a proof of concept is posted. But by starting a process from a window service I don't have a windowHandle.
I start my service like this:
m_process.StartInfo = new ProcessStartInfo
{
FileName = "java"
, Arguments = arguments
, UseShellExecute = true
, WorkingDirectory = workDirectory
, CreateNoWindow = false
};
m_process.Start();
Where arguments contais the jetty data to start the SOLR or in the ruby case I use "ruby.exe thin start ...".
Now on stopping the service I tried:
[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();
}
}
But as I don't have a WindowTitle, I guess I don't even have a window I can't allocate the process like this.
So does anyone have a idea how I can allocate process and send the stop signal to it? I can live with just killing the process, but this just a service restart impossible without waiting a long time. Thanks for any hints, tips and solutions.
GenerateConsoleCtrlEvent might work
When time to kill child app...
member declarations