I was spammingasking around earlier this week about how to monitor process creation in windows. I was expecting to have to go the IFEO or hook-an-API route, but Wes Haggard pointed me to a class he wrote that uses WMI for monitor process creation/modification/deletion!
Since this involves hooking up for events and doing operations on background threads (as the delegates are called), this is the kind of thing you're much better off doing in a cmdlet than trying (and most likely failing) to pull it off in "only" powershell script.
Since Wes had already wrapped his effort into a class, all I had to do was write a cmdlet that use that class.
Lessons I learned during the creation of this cmdlet:
I've also moved this new cmdlet and the other one (get-tfhistory) into the same zip file of PowerShell scripts so others can more easily play with them if they want (that solution also includes Win32_Process and Wes' ProcessWatcher class).
Here's some example output (excuse WLW for the formatting :)
C:\> trace-processcreation gvim.exe | select CommandLine,CreationDate CommandLine CreationDate----------- ------------"C:\Program Files\Vim\vim70\gvim.exe" 2/20/2007 4:40:20 PM"c:\program files\vim\vim70\gvim.exe" 2/20/2007 4:41:05 PM"c:\program files\vim\vim70\gvim.exe" foo bar baz 2/20/2007 4:41:11 PMC:\>
C:\> trace-processcreation gvim.exe | select CommandLine,CreationDate
CommandLine CreationDate----------- ------------"C:\Program Files\Vim\vim70\gvim.exe" 2/20/2007 4:40:20 PM"c:\program files\vim\vim70\gvim.exe" 2/20/2007 4:41:05 PM"c:\program files\vim\vim70\gvim.exe" foo bar baz 2/20/2007 4:41:11 PMC:\>
Here's the cmdlet code:
[Cmdlet(VerbsDiagnostic.Trace, "ProcessCreation")] public class TraceProcessCreationCommand : PSCmdlet { private Queue<Win32_Process> m_eventRecords = new Queue<Win32_Process>(); private object m_lock = new object(); private ProcessWatcher m_procWatcher; private string m_processName; [Parameter(Mandatory = false, Position = 0, ValueFromPipeline = true)] public string ProcessName { get { return m_processName; } set { m_processName = value; } } protected override void BeginProcessing() { m_procWatcher = new ProcessWatcher(m_processName); m_procWatcher.ProcessCreated += new ProcessEventHandler(procWatcher_ProcessCreated); //m_procWatcher.ProcessDeleted += new ProcessEventHandler(procWatcher_ProcessDeleted); //m_procWatcher.ProcessModified += new ProcessEventHandler(procWatcher_ProcessModified); m_procWatcher.Start(); } protected override void ProcessRecord() { while (!Stopping) { // any new objects to write? if (m_eventRecords.Count > 0) { Win32_Process record; lock (m_lock) { record = m_eventRecords.Dequeue(); } WriteObject(record); } // Sleep for a bit so we're not too CPU-hungry System.Threading.Thread.Sleep(100); } } protected override void EndProcessing() { m_procWatcher.Stop(); } private void procWatcher_ProcessCreated(Win32_Process proc) { lock (m_lock) { m_eventRecords.Enqueue(proc); } } }