【问题标题】:Monitor when an exe is launched监控 exe 何时启动
【发布时间】:2009-06-09 00:22:57
【问题描述】:

我有一些服务,应用程序需要运行这些服务才能使应用程序的某些功能正常工作。我想启用仅在启动应用程序后启动外部 Windows 服务以进行初始化的选项。 (而不是让它们随机器自动启动并在不需要应用程序时占用内存)

我无法访问 exe 的代码来实现这一点,所以理想情况下,我想编写一个 C# .Net Windows 服务来监控 exe 何时启动。

到目前为止,我发现的是 System.IO.FileSystemEventHandler。该组件仅处理更改、创建、删除和重命名的事件类型。我不认为文件系统组件会是查找所需内容的理想位置,但不知道还能去哪里。

也许我没有使用正确的关键字进行搜索,但我还没有在 Google 或 stackoverflow.com 上找到任何非常有用的内容。

该解决方案需要在 XP、Vista 和 Win 7 上运行...

提前感谢您的任何指点。

【问题讨论】:

标签: c# .net windows-services monitoring


【解决方案1】:

this article,您可以在服务中使用 WMI(System.Management 命名空间)来监视进程启动事件。

 void WaitForProcess()
{
    ManagementEventWatcher startWatch = new ManagementEventWatcher(
      new WqlEventQuery("SELECT * FROM Win32_ProcessStartTrace"));
    startWatch.EventArrived
                        += new EventArrivedEventHandler(startWatch_EventArrived);
    startWatch.Start();

    ManagementEventWatcher stopWatch = new ManagementEventWatcher(
      new WqlEventQuery("SELECT * FROM Win32_ProcessStopTrace"));
    stopWatch.EventArrived
                        += new EventArrivedEventHandler(stopWatch_EventArrived);
    stopWatch.Start();
}

  static void stopWatch_EventArrived(object sender, EventArrivedEventArgs e) {
    stopWatch.Stop();
    Console.WriteLine("Process stopped: {0}"
                      , e.NewEvent.Properties["ProcessName"].Value);
  }

  static void startWatch_EventArrived(object sender, EventArrivedEventArgs e) {
    startWatch.Stop();
    Console.WriteLine("Process started: {0}"
                      , e.NewEvent.Properties["ProcessName"].Value);
  }
}

WMI 允许相当复杂的查询;您可以在此处修改查询以仅在您观看的应用程序启动时或其他条件下触发您的事件处理程序。 Here's a quick introduction,从 C# 的角度来看。

【讨论】:

  • 在 Windows 7 上执行此代码时遇到一些问题。调用 startWatch.Start() 时出现“拒绝访问”错误。有没有人找到解决方法?
  • @tjjjohnson:没有调查,我怀疑 Windows 7 需要从提升的进程运行手表。尝试使用“以管理员身份运行”。
  • +1 - 请注意...似乎在停止事件中,ProcessName 可能会被截断。
  • 太棒了,我们可以让 WMI 池更快吗?我的意思是,当我尝试使用它时,显示创建的进程名称或已破坏的进程名称总是有延迟。我们不能让这个通知更快吗?
【解决方案2】:

这里有 3 个选项:

可靠的/侵入式的,在非托管代码中设置一个挂钩,每当启动应用程序时,它都会与您的 C# 应用程序进行通信。这很难做到正确,并且涉及为每个进程加载一个额外的 DLL。 (或者你可以设置一个驱动程序,这更难写)

不太可靠的方法是定期(例如每 10-30 秒)列出所有进程(使用 System.Diagnostics.Process 类)以查看应用程序是否已启动。

还可以从托管代码中观察 Win32_Process、InstanceCreationEvent WMI 事件。不确定这有多可靠,但我怀疑它会比轮询过程更好。

【讨论】:

    【解决方案3】:

    监控进程是否正在运行 - 但必须运行一项服务才能执行此操作。

    如果您真的不想消耗任何资源 - 用纯 C 编写一个简单的服务。不使用 MFC/ATL 编写的服务应用程序可以消耗低至 300-400 kb 的内存并且几乎没有 CPU 周期。当您感兴趣的进程启动时,您可以生成 C# 服务。

    【讨论】:

      【解决方案4】:
       public Process IsProcessOpen(string name)
              {
                  foreach (Process clsProcess in Process.GetProcesses())
                      if (clsProcess.ProcessName.Contains(name))
                          return clsProcess;
                  return null;
              }
      

      【讨论】:

        【解决方案5】:

        回复 Windows 7 方面的问题。如果您正在监视 64 位进程,则您的进程也需要构建为在 64 位地址空间中工作。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2014-01-14
          相关资源
          最近更新 更多