从服务启动EXE文件,并通过发送SIGBREAK停止它
本文关键字:SIGBREAK 启动 服务 EXE 文件 | 更新日期: 2023-09-27 18:10:59
我写了一个启动java.exe或ruby.exe的服务(我知道有一些解决方案,但由于某些原因我需要自己的服务)。
到目前为止,服务工作正常,我从注册表收集配置,然后启动服务。当服务停止时,我获取进程并发送. kill()。到目前为止一切顺利。但是我发现,. kill()是一个问题,因为ruby.exe(我使用thin启动服务)或java.exe(我用它启动SOLR)在tcp套接字端口上侦听。如果这个端口被使用并且我杀死了进程,窗口将阻塞端口72秒(按设计)。如果我从shell命令shell执行solr:start和thin -start,并使用Ctrl+C停止它,进程终止,端口立即可用。
所以我的猜测是:如果我设法发送一个ctrl-c到进程,它将正确终止。
所以我发现这个线程如何从windows服务运行exe并在exe进程退出时停止服务?张贴概念证明的地方。但是,如果从窗口服务启动进程,我就没有windowHandle了。
我像这样启动我的服务:
m_process.StartInfo = new ProcessStartInfo
{
FileName = "java"
, Arguments = arguments
, UseShellExecute = true
, WorkingDirectory = workDirectory
, CreateNoWindow = false
};
m_process.Start();
其中参数包含启动SOLR的jetty数据,或者在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,我想我甚至没有一个窗口,我不能像这样分配进程
所以有人知道我如何分配进程并向它发送停止信号吗?我可以忍受只是杀死进程,但这只是一个服务重启不可能等待很长时间。谢谢你的提示,技巧和解决方案。
GenerateConsoleCtrlEvent可能会工作
m_process.StartInfo = new ProcessStartInfo
{
FileName = "java"
, Arguments = arguments
, UseShellExecute = true
, WorkingDirectory = workDirectory
, CreateNoWindow = false
};
var process = m_process.Start();
何时终止子应用程序…
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);