如何跟踪应用程序的使用?

时间:2009-06-23 20:25:38

标签: c#

我想开发一个应用程序(我想在后台随时运行)来跟踪应用程序的使用情况(msword,excel,powerpoint,* .exe等)。

我可以处理将数据发布到数据库但是不知道从哪里开始监视正在运行的应用程序(当它们启动时,停止时)。有人有任何线索吗?

4 个答案:

答案 0 :(得分:3)

您可以使用System.Diagnostics.Process.GetProcesses()定期轮询正在运行的流程列表。

以下代码输出有关启动和退出流程的信息。退出系统进程将无法识别。

class Program
{
    struct ProcessStartTimePair
    {
        public Process Process { get; set; }
        public DateTime StartTime { get; set; }
        public DateTime ExitTime
        {
            get
            {
                return DateTime.Now; // approximate value
            }
        }

        public ProcessStartTimePair(Process p) : this()
        {
            Process = p;
            try
            {
                StartTime = p.StartTime;
            }
            catch (System.ComponentModel.Win32Exception)
            {
                StartTime = DateTime.Now; // approximate value
            }
        }
    }

    static void Main(string[] args)
    {
        List<ProcessStartTimePair> knownProcesses = new List<ProcessStartTimePair>();
        while (true)
        {
            foreach (Process p in Process.GetProcesses())
            {
                if (!knownProcesses.Select(x => x.Process.Id).Contains(p.Id))
                {
                    knownProcesses.Add(new ProcessStartTimePair(p));
                    Console.WriteLine("Detected new process: " + p.ProcessName);
                }
            }

            for (int i = 0; i < knownProcesses.Count; i++) 
            {
                ProcessStartTimePair pair = knownProcesses[i];
                try
                {
                    if (pair.Process.HasExited)
                    {
                        Console.WriteLine(pair.Process.ProcessName + " has exited (alive from {0} to {1}).", pair.StartTime.ToString(), pair.ExitTime.ToString());
                        knownProcesses.Remove(pair);
                        i--; // List was modified, 1 item less
                        // TODO: Store in the info in the database
                    }
                }
                catch (System.ComponentModel.Win32Exception)
                {
                    // Would have to check whether the process still exists in Process.GetProcesses().
                    // The process probably is a system process.
                }
            }
            Console.WriteLine();
            System.Threading.Thread.Sleep(1000);
        }
    }
}

您可能只是忽略了不允许您读取HasExited属性的系统进程。

修改

这是.net 2.0版本:

    static void Main(string[] args)
    {
        List<ProcessStartTimePair> knownProcesses = new List<ProcessStartTimePair>();
        while (true)
        {
            foreach (Process p in Process.GetProcesses())
            {
                if (!ProcessIsKnown(knownProcesses, p.Id))
                {
                    knownProcesses.Add(new ProcessStartTimePair(p));
                    Console.WriteLine("Detected new process: " + p.ProcessName);
                }
            }

            for (int i = 0; i < knownProcesses.Count; i++) 
            [...]
        }
    }

    static bool ProcessIsKnown(List<ProcessStartTimePair> knownProcesses, int ID)
    {
        foreach (ProcessStartTimePair pstp in knownProcesses)
        {
            if (pstp.Process.Id == ID)
            {
                return true;
            }
        }
        return false;
    }

请注意,代码可以改进,只显示概念。

答案 1 :(得分:1)

您可以定期轮询所有顶级窗口并记录窗口标题文本;并在此基础上对哪个程序正在运行做出一些结论。

或者您可以通过流程名称或组合来完成。

有关枚举窗口的信息,请参阅http://msdn.microsoft.com/en-us/library/ms633497(VS.85).aspxhere is how to use it in managed code。 对于枚举过程,请使用Process.GetProcesses方法或查看http://www.codeproject.com/KB/threads/enumprocess.aspx

答案 2 :(得分:1)

当进程启动/退出时,可以使用WMI进行通知

A full working example is in a blog post on ASP.NET

它的基础知识(从后代的博客文章中复制):

创建一个继承自ManagementEventWatcher

的类

在构造函数中,设置:

this.Query.QueryLanguage = "WQL";
this.Query.QueryString = @"SELECT * FROM 
__InstanceOperationEvent WITHIN 1 WHERE TargetInstance ISA 'Win32_Process'";
this.EventArrived += watcher_EventArrived; // Delegate for EventArrivedEventHandler

制作EventArrivedEventHandler之类的:

private void watcher_EventArrived(object sender, EventArrivedEventArgs e)
{
    string eventType = e.NewEvent.ClassPath.ClassName;
    Win32_Process proc = new 
        Win32_Process(e.NewEvent["TargetInstance"] as ManagementBaseObject);

    switch (eventType)
    {
        case "__InstanceCreationEvent":
            Console.WriteLine("Process Created");
            break;
        case "__InstanceDeletionEvent":
            Console.WriteLine("Process Deleted (Ended)");
            break;
        case "__InstanceModificationEvent":
            Console.WriteLine("Process Modified (possibly still running)");
            break;
    }
}

答案 3 :(得分:0)

轮询很简单,但您应该真正了解win32事件,而是接收有关这些事情何时发生的通知。

我有一个类似的副项目来创建一个“任务栏”类型的应用程序。我的目标是在移动/创建/关闭窗口时通知应用程序,以便我可以使用此信息来显示/更新UI。

bb4win app有这个“层”,可以从系统中捕获不同类型的通知,并使用它来创建备用桌面shell。源代码可用,并以c编码。

这是我用来开始Win32 Hooks的链接。