1

I want to show a MessageBox if any (not a specific program) new process is running. For example:

  1. Any program is ran

  2. When any program is ran, a MessageBox is shown saying New process!

How is this done?

Sorry for the lack of detail in this question. There isn't really much to add.

Visual Vincent
  • 18,045
  • 5
  • 28
  • 75
  • Possible duplicate of [.NET Process Monitor](https://stackoverflow.com/questions/1986249/net-process-monitor) – Visual Vincent Jun 23 '18 at 08:37
  • 1
    @VisualVincent while I agree with you, there's some consensus on meta to not allow cross language duplicates, [even c# vs vb.net](https://meta.stackoverflow.com/a/348797/4975230), and your dupe target has no VB.NET code. See the comment thread under that answer... please vote accordingly on those posts. – jrh Jun 23 '18 at 21:26
  • Good heavens, he (being old, I use the masculine pronoun for he or she, if I am forced to change, I will use "it" ;-) ) did it again! General Price becomes Sir Price becomes Sir. Price. – Mary Jun 23 '18 at 21:53
  • But no signs of original research. Has OP searched how to get process information from the system? Has OP coded anything to attempt to corral this information and check it for differences? Has OP searched how to monitor system events? – AJD Jun 24 '18 at 00:00
  • 1
    @jrh : Thanks for the link! I usually only VTC cross language duplicates if I find the code to be quite easy to convert. In this case since the answer is about declaring two variables and attaching two event handlers, I find it to be very simple. But since I have had a hard time finding good VB.NET answers about this before, I suppose I'll write one! – Visual Vincent Jun 24 '18 at 08:26
  • 1
    @VisualVincent yeah I personally am usually okay with cross language duplicates, FWIW every VB.NET programmer I ran into could read C# code and understand it (it's pretty much a requirement, there's no CLR via VB.NET for example), so I personally don't support the opinion that others have on meta, I just wanted to make you aware of it. For reasons that don't make a lot of sense to me, there is sometimes a great deal of resistance towards treating C# and VB.NET as similar languages. Thanks for answering, the VB.NET side could definitely use more content. – jrh Jun 24 '18 at 20:04

2 Answers2

3

You can use WMI (Windows Management Instrumentation) for this. It provides the Win32_ProcessStartTrace and Win32_ProcessStopTrace events for detecting when a process has been started/terminated.

Before we do anything you need to add a reference to the managed WMI library. Right-click your project in the Solution Explorer and press Add Reference.... Then go to the .NET tab, select System.Management and press OK.

Based on Hans Passant's answer:

Imports System.Management

Public Class Form1

    Dim WithEvents ProcessStartWatcher As New ManagementEventWatcher(New WqlEventQuery("SELECT * FROM Win32_ProcessStartTrace"))
    Dim WithEvents ProcessStopWatcher As New ManagementEventWatcher(New WqlEventQuery("SELECT * FROM Win32_ProcessStopTrace"))

    Private Sub Form1_Load(sender As Object, e As System.EventArgs) Handles MyBase.Load
        ProcessStartWatcher.Start()
        ProcessStopWatcher.Start()
    End Sub

    Private Sub Form1_FormClosing(sender As Object, e As System.Windows.Forms.FormClosingEventArgs)
        ProcessStartWatcher.Stop()
        ProcessStopWatcher.Stop()
    End Sub

    Private Sub ProcessStartWatcher_EventArrived(sender As Object, e As System.Management.EventArrivedEventArgs) Handles ProcessStartWatcher.EventArrived
        Dim ProcessName As String = e.NewEvent.Properties("ProcessName").Value
        Dim PID As Integer = e.NewEvent.Properties("ProcessID").Value

        MessageBox.Show(String.Format("Process ""{0}"" with ID {1} started.", ProcessName, PID))
    End Sub

    Private Sub ProcessStopWatcher_EventArrived(sender As Object, e As System.Management.EventArrivedEventArgs) Handles ProcessStopWatcher.EventArrived
        Dim ProcessName As String = e.NewEvent.Properties("ProcessName").Value
        Dim PID As Integer = e.NewEvent.Properties("ProcessID").Value

        MessageBox.Show(String.Format("Process ""{0}"" with ID {1} stopped.", ProcessName, PID))
    End Sub
End Class

This polls after a couple of seconds, so if you think this is too slow you could poll the __InstanceCreationEvent and __InstanceDeletionEvent events instead, which lets you specify the polling interval:

Const PollingInterval As Double = 2.0 'Seconds.

Dim WithEvents ProcessStartWatcher As New ManagementEventWatcher(New WqlEventQuery("SELECT * FROM __InstanceCreationEvent WITHIN " & PollingInterval & " WHERE TargetInstance ISA 'Win32_Process'"))
Dim WithEvents ProcessStopWatcher As New ManagementEventWatcher(New WqlEventQuery("SELECT * FROM __InstanceDeletionEvent WITHIN " & PollingInterval & " WHERE TargetInstance ISA 'Win32_Process'"))

(...form code...)

Private Sub ProcessStartWatcher_EventArrived(sender As Object, e As System.Management.EventArrivedEventArgs) Handles ProcessStartWatcher.EventArrived
    Dim ProcessName As String = CType(e.NewEvent.Properties("TargetInstance").Value, ManagementBaseObject)("Name")
    Dim PID As Integer = CType(e.NewEvent.Properties("TargetInstance").Value, ManagementBaseObject)("ProcessId")

    MessageBox.Show(String.Format("Process ""{0}"" with ID {1} started.", ProcessName, PID))
End Sub

Private Sub ProcessStopWatcher_EventArrived(sender As Object, e As System.Management.EventArrivedEventArgs) Handles ProcessStopWatcher.EventArrived
    Dim ProcessName As String = CType(e.NewEvent.Properties("TargetInstance").Value, ManagementBaseObject)("Name")
    Dim PID As Integer = CType(e.NewEvent.Properties("TargetInstance").Value, ManagementBaseObject)("ProcessId")

    MessageBox.Show(String.Format("Process ""{0}"" with ID {1} stopped.", ProcessName, PID))
End Sub

IMPORTANT: WMI polling can use a lot of CPU, so don't set too small intervals.

Visual Vincent
  • 18,045
  • 5
  • 28
  • 75
  • Minor suggestion, you may want to look into [interpolated strings](https://learn.microsoft.com/en-us/dotnet/visual-basic/programming-guide/language-features/strings/interpolated-strings) instead of using `String.Format`, personally I've found them to be a lot easier to use and a lot less error prone. – jrh Jun 25 '18 at 00:03
  • @jrh : Interpolated strings aren't as widely compatible as `String.Format()`. Not everyone out there is using VS 2015 or later (myself included :). Personally I actually like `String.Format()` more than interpolated strings. – Visual Vincent Jun 25 '18 at 07:55
  • Hi, Visual. I've just noticed this error in the line `Dim ProcessName As String = CType(e("TargetInstance"), ManagementBaseObject)("Name")` and ` Dim PID As Integer = CType(e("TargetInstance"), ManagementBaseObject)("ProcessId")`. Under 'e' I get an error saying "Class 'EventArrivedArgs' cannot be indexed because it has no default property. Also, why can't I use `ProcessStartWatcher_EventArrived` in a different sub like this: `ProcessStartWatcher_EventArrived`? It just gives me an error “Argument not specified for parameter 'e' of 'Private Sub ProcessStartWatcher_EventArrived()” –  Jun 25 '18 at 08:48
  • @Sir.Price : `ProcessStartWatcher_EventArrived` is an event handler that requires two arguments (`sender` and `e`). You can't call it without passing it these arguments, and besides it isn't meant to be called by your code anyway. If you want to run the code inside it manually then you have to create a separate method for it. || I edited my answer to fix the other error. – Visual Vincent Jun 25 '18 at 08:56
  • @VisualVincent NP, I actually just got off of VS 2010 recently myself, and I'm now stuck on 2015. I thought I was the only one here who had to use something older than the latest. – jrh Jun 25 '18 at 11:54
  • @jrh : I don't have to use it if I don't want to (I'm using 2010), but I really don't like the design in the newer versions. I'm a sucker for skeuomorphism. ;) – Visual Vincent Jun 25 '18 at 11:58
-1

Use WMI (Windows Management Instrumentation) to receive events on process creation. Display your MessageBox on these incoming events.

Ton Plooij
  • 2,583
  • 12
  • 15