gpt4 book ai didi

windows - 我可以向 Windows 上的应用程序发送 ctrl-C (SIGINT) 吗?

转载 作者:可可西里 更新时间:2023-11-01 11:54:25 26 4
gpt4 key购买 nike

我(过去)编写了跨平台(Windows/Unix)应用程序,当从命令行启动时,处理用户键入的 Ctrl-C 以相同的方式组合(即干净地终止应用程序)。

是否有可能在 Windows 上从另一个(不相关的)进程发送一个 Ctrl-C/SIGINT/等同于一个进程来请求它干净地终止(给它整理资源等的机会)?

最佳答案

我围绕这个主题做了一些研究,结果比我预期的更受欢迎。 KindDragon 的回复是关键点之一。

我写了一个longer blog post关于这个主题并创建了一个工作演示程序,它演示了使用这种类型的系统以几种不错的方式关闭命令行应用程序。该帖子还列出了我在研究中使用的外部链接。

简而言之,这些演示程序执行以下操作:

  • 使用 .Net 启动带有可见窗口的程序,使用 pinvoke 隐藏,运行 6 秒,使用 pinvoke 显示,停止.Net.
  • 使用 .Net 启动一个没有窗口的程序,运行 6 秒,通过附加控制台并发出 ConsoleCtrlEvent
  • 停止

编辑:来自@KindDragon 的修改后的解决方案,适用于那些对此时此地的代码感兴趣的人。如果您打算在停止第一个程序后启动其他程序,您应该重新启用CTRL+C 处理,否则下一个进程将继承父进程的禁用状态而不会响应CTRL+C

[DllImport("kernel32.dll", SetLastError = true)]
static extern bool AttachConsole(uint dwProcessId);

[DllImport("kernel32.dll", SetLastError = true, ExactSpelling = true)]
static extern bool FreeConsole();

[DllImport("kernel32.dll")]
static extern bool SetConsoleCtrlHandler(ConsoleCtrlDelegate HandlerRoutine, bool Add);

delegate bool ConsoleCtrlDelegate(CtrlTypes CtrlType);

// Enumerated type for the control messages sent to the handler routine
enum CtrlTypes : uint
{
CTRL_C_EVENT = 0,
CTRL_BREAK_EVENT,
CTRL_CLOSE_EVENT,
CTRL_LOGOFF_EVENT = 5,
CTRL_SHUTDOWN_EVENT
}

[DllImport("kernel32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool GenerateConsoleCtrlEvent(CtrlTypes dwCtrlEvent, uint dwProcessGroupId);

public void StopProgram(Process proc)
{
//This does not require the console window to be visible.
if (AttachConsole((uint)proc.Id))
{
// Disable Ctrl-C handling for our program
SetConsoleCtrlHandler(null, true);
GenerateConsoleCtrlEvent(CtrlTypes.CTRL_C_EVENT, 0);

//Moved this command up on suggestion from Timothy Jannace (see comments below)
FreeConsole();

// Must wait here. If we don't and re-enable Ctrl-C
// handling below too fast, we might terminate ourselves.
proc.WaitForExit(2000);

//Re-enable Ctrl-C handling or any subsequently started
//programs will inherit the disabled state.
SetConsoleCtrlHandler(null, false);
}
}

此外,如果 AttachConsole() 或发送的信号失败,请计划一个应急解决方案,例如 sleep ,然后这个:

if (!proc.HasExited)
{
try
{
proc.Kill();
}
catch (InvalidOperationException e){}
}

关于windows - 我可以向 Windows 上的应用程序发送 ctrl-C (SIGINT) 吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/813086/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com