我已經編寫了一個啓動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