c# process logging - collection issue?

Currently reading:
c# process logging - collection issue?

Joined
Aug 1, 2007
Messages
2,636
Points
558
Location
Scotland
Working on a little console app that is basically bits and pieces found on the internet. Can get it working fine when putting strings in a arraylist but now I've added a LoggedProcess class and try storing objects in a list well - it doesn't seem to work and every process running is spat out rather than just new ones that have started. Hope that makes sense! I'm not a programmer really - have done a little Java in the past but .Net is new to me, have been pulling my hair out over this all day :bang:

I've attached the whole VS2008 project though the cs file might be enough. In vista it has to be run as administrator due to getting owner information for processes other than those run by the current user.

Any advice would be mch appreciated! :worship:
 

Attachments

  • ProcessLogger.zip
    29.5 KB · Views: 120
Code:
using System;
using System.Collections.Generic;
using System.Text;
using System.Linq;
using System.Diagnostics;
using System.Threading;
using System.Collections;
using System.IO;
using System.Management;
using System.ComponentModel;

namespace ProcessLogger
{
    class LoggedProcess
    {
        [DefaultValue("")]
        public string Name { get; set; }

        [DefaultValue(0)]
        public int PID { get; set; }

        [DefaultValue("")]
        public string Owner { get; set; }

        public string GetConsoleString()
        {
            return string.Format("{0} \tProcess Started: {1} \t Owner: {2}", PID, Name, Owner); 
        }

        public LoggedProcess(string name, int pid, string owner)
        {
            Name = name;
            PID = pid;
            Owner = owner;
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            int iCycleInterval = 1000;  // 1 second
            List<LoggedProcess> processesBook = new List<LoggedProcess>();
            bool bFirstCycle = true;

            //create file
            FileInfo info = new FileInfo("C:\\Test.txt");
            FileStream stream = info.Open(FileMode.Create, FileAccess.Write);            
            stream.Close();

            StreamWriter sw = info.CreateText();
            Console.CancelKeyPress += (sender, e) => 
                {
                    sw.Close();
                    sw.Dispose();
                };

            while (true)
            {
                IEnumerable<LoggedProcess> currentlyRunning = 
                    from p in Process.GetProcesses().Distinct()
                    select new LoggedProcess(p.ProcessName, p.Id, GetProcessInfoByPID(p.Id));

                // Record starting time for new processes
                foreach (LoggedProcess process in currentlyRunning)
                {
                    if (!processesBook.Contains(process))   // A new process started
                    {
                        // Log the Now as the start time for this process (Don't log if this is the the first cycle)
                        if (!bFirstCycle)
                        {
                            string toWrite = process.GetConsoleString();

                            //write to text.
                            Console.WriteLine(toWrite);
                            sw.WriteLine(toWrite);
                        }

                        // Book-keep the new process
                        processesBook.Add(process);
                    }
                }

                // We looped already once, so turn this flag off
                bFirstCycle = false;

                // Record ending time for finished processes
                IEnumerable<LoggedProcess> nonLogged = 
                    processesBook.Where(p => !currentlyRunning.Contains(p));

                foreach (LoggedProcess logged in nonLogged)
                {
                    // Log the Now as the end time for this process
                    string console = logged.GetConsoleString();

                    //write to text file
                    Console.WriteLine(DateTime.Now.ToString() + console);
                    sw.WriteLine(DateTime.Now.ToString() + console);
                }

                // Now Update the process book
                processesBook = currentlyRunning.ToList();
                
                // Sleep till the next loop
                Thread.Sleep(iCycleInterval);
            }
        }

        public static string GetProcessInfoByPID(int PID)
        {
            string User = String.Empty;
            string Domain = String.Empty;
            string OwnerSID = String.Empty;
            string processname = String.Empty;
            try
            {
                ObjectQuery sq = new ObjectQuery
                    ("Select * from Win32_Process Where ProcessID = '" + PID + "'");
                ManagementObjectSearcher searcher = new ManagementObjectSearcher(sq);
                if (searcher.Get().Count == 0)
                    return OwnerSID;
                foreach (ManagementObject oReturn in searcher.Get())
                {
                    string[] o = new String[2];
                    //Invoke the method and populate the o var with the user name and domain
                    oReturn.InvokeMethod("GetOwner", (object[])o);

                    //int pid = (int)oReturn["ProcessID"];
                    processname = (string)oReturn["Name"];
                    //dr[2] = oReturn["Description"];
                    User = o[0];
                    if (User == null)
                        User = String.Empty;
                    Domain = o[1];
                    if (Domain == null)
                        Domain = String.Empty;
                    string[] sid = new String[1];
                    oReturn.InvokeMethod("GetOwner", (object[])sid);
                    OwnerSID = sid[0];
                    return OwnerSID;
                }
            }
            catch
            {
                return OwnerSID;
            }
            return OwnerSID;
        }
    }
}

Theres a few new things I put in there to make life easier. It seems to work?

Haven't really tested it all that much :p
 
Thanks for your input!

Still seems to log processes that have already been running though. Also not sure why its running really slowly :(

Yer i didn't really look at it all that much just tidied up what was already there.

So you just want a log of all new processes that start up? i'll have another look.
 
Done it, naturally... :p

Code:
using System;
using System.Collections.Generic;
using System.Text;
using System.Linq;
using System.Diagnostics;
using System.Threading;
using System.Collections;
using System.IO;
using System.Management;
using System.ComponentModel;

namespace ProcessLogger
{
    class LoggedProcess
    {
        [DefaultValue("")]
        public string Name { get; set; }

        [DefaultValue(0)]
        public int PID { get; set; }

        [DefaultValue("")]
        public string Owner { get; set; }

        public string GetConsoleString()
        {
            return string.Format("{0} \tProcess Started: {1} \t Owner: {2}", PID, Name, Owner); 
        }

        public LoggedProcess(string name, int pid, string owner)
        {
            Name = name;
            PID = pid;
            Owner = owner;
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            List<LoggedProcess> processesBook = new List<LoggedProcess>();

            //create file
            FileInfo info = new FileInfo("C:\\Test.txt");
            FileStream stream = info.Open(FileMode.Create, FileAccess.Write);            
            stream.Close();

            StreamWriter sw = info.CreateText();
            Console.CancelKeyPress += (sender, e) => 
                {
                    sw.Close();
                    sw.Dispose();
                };

            List<Process> loggedProcesses = Process.GetProcesses().ToList();

            while (true)
            {
                IEnumerable<Process> newProcesses =
                    (from p in Process.GetProcesses()
                     where !loggedProcesses.Exists(np => np.Id == p.Id)
                     select p);

                // Record starting time for new processes
                foreach (Process process in newProcesses)
                {
                    LoggedProcess logged = new LoggedProcess(process.ProcessName, process.Id, GetProcessInfoByPID(process.Id));
                    string toWrite = logged.GetConsoleString();

                    //write to text.
                    Console.WriteLine(toWrite);
                    sw.WriteLine(toWrite);
                }

                loggedProcesses.AddRange(newProcesses);
                Thread.Sleep(1000);
            }
        }

        public static string GetProcessInfoByPID(int PID)
        {
            string User = String.Empty;
            string Domain = String.Empty;
            string OwnerSID = String.Empty;
            string processname = String.Empty;
            try
            {
                ObjectQuery sq = new ObjectQuery
                    ("Select * from Win32_Process Where ProcessID = '" + PID + "'");
                ManagementObjectSearcher searcher = new ManagementObjectSearcher(sq);
                if (searcher.Get().Count == 0)
                    return OwnerSID;
                foreach (ManagementObject oReturn in searcher.Get())
                {
                    string[] o = new String[2];
                    //Invoke the method and populate the o var with the user name and domain
                    oReturn.InvokeMethod("GetOwner", (object[])o);

                    //int pid = (int)oReturn["ProcessID"];
                    processname = (string)oReturn["Name"];
                    //dr[2] = oReturn["Description"];
                    User = o[0];
                    if (User == null)
                        User = String.Empty;
                    Domain = o[1];
                    if (Domain == null)
                        Domain = String.Empty;
                    string[] sid = new String[1];
                    oReturn.InvokeMethod("GetOwner", (object[])sid);
                    OwnerSID = sid[0];
                    return OwnerSID;
                }
            }
            catch
            {
                return OwnerSID;
            }
            return OwnerSID;
        }
    }
}

Seems the class was/is slowing it down a lot when using LINQ to create objects of the Class and not of the Natural Process Type. I also just re-wrote it.

LINQ is very very very powerful and often eliminates a lot of for loops, nested for's and can even get rid of if statements inside for loops, ect.

In the example the class isn't really nessecary and should probably be taken out as its just used to store information that isn't in scope for long at all.

I would just replace it with the string.Format inside of the class to reduce on overheads seen as your calling the code every 1 sec and it pulls back around 60~ Processes.
 
Re: Done it, naturally... :p

Have got it working now, as you said just using a string. Had to do some logical stuff with the owner bit so only new processes go through with working out the owner - stops it slowing to a crawl.

Thanks again for your advice :)
 
Back
Top