【问题标题】:C# control 3rd party program in system trayC# 控制系统托盘中的第 3 方程序
【发布时间】:2025-12-03 09:45:02
【问题描述】:

我目前正在编写一个 C# 程序,该程序基本上用作 3rd 方程序的看门狗:如果流量低于某个值,则进程被终止,然后重新启动 [使用简单的 taskkill /im]。
这工作得很好,除了一个例外 - 如果程序被最小化到系统托盘,它不会响应taskkill /im,您必须使用taskkill /f /im 强制终止它。

可以猜到,这并不是结束程序的最佳方式。因此,我目前正在寻找一种访问 Windows 系统托盘的方法,并基本上执行单击程序/调用方法以将其最大化恢复正常。
我曾考虑过从字面上模拟托盘上的点击,但发现这种方法不准确且不可预测。
是否有另一种方法来实现这一点[例如通过使用系统 api]?

谢谢!

【问题讨论】:

  • 如果第 3 方程序没有任何关闭确认对话框,那么可以将 Process 对象附加到正在运行的 exe 中,然后调用 CloseMainWindow(),据我所知,这相当于点击主窗口上的X

标签: c# windows api system-tray


【解决方案1】:

您可以尝试使用 user32.dll 最大化进程窗口。

// Pinvoke declaration for ShowWindow
private const int SW_SHOWMAXIMIZED = 3;

[DllImport("user32.dll")]
static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);

// Sample usage
ShowWindow(proc.MainWindowHandle, SW_SHOWMAXIMIZED);

取自this SO答案。 有关窗口状态的完整列表,请访问MSDN Page

您可以通过执行以下操作来获取 WindowHandle

var processes = Process.GetProcessesByName("nameOfYourProcess");

foreach(var process in processes)
{
   var windowHandle = process.getMainWindowHandle;
}

虽然这只有在进程仍然有窗口时才有效。

【讨论】:

    【解决方案2】:

    在 Windows 中与另一个应用程序的托盘图标交互的唯一方法是模拟鼠标单击。这有一个主要缺陷,如果用户在与鼠标交互的同时你“钢”他的光标,他就不能工作。

    如果您知道您最终不会遇到内存泄漏(如果它是您赢得的托管应用程序)并且您正在杀死的应用程序在退出进程时没有做一些重要的事情,那么杀死是更好的选择。

    【讨论】: