【发布时间】:2011-10-12 14:37:48
【问题描述】:
我编写了一个启动 java.exe 或 ruby.exe 的服务(我知道有一些解决方案,但由于某些原因我需要自己的服务)。
到目前为止,该服务工作正常,我从注册表中收集我的配置,然后启动服务。当服务停止时,我得到我的进程并发送一个 .Kill()。 到目前为止,一切都很好。 但我发现,.Kill() 是一个问题,因为 ruby.exe(我使用瘦启动服务)或 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();
参数包含启动 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,我想我什至没有窗口我无法像这样分配进程。
那么有人知道我如何分配进程并向它发送停止信号吗? 我可以忍受只是杀死进程,但这只是一个服务重启,如果不等待很长时间是不可能的。 感谢您提供任何提示、提示和解决方案。
【问题讨论】:
-
Windows 不做信号。那是 *nix 丑陋。
-
Pinvoke GenerateConsoleCtrlEvent().
-
你试过
Process.CloseMainWindow()(MSDN)吗? -
好像没有窗口,已经试过不同的窗口句柄了。