Get Notified When A Process Starts Using PowerShell

For a while now, I noticed a weird behavior on my PC where I’d see instances of iexplore.exe and ielowutil.exe running when I’d review my Task Manager’s list of processes. I’ve tried to understand where these were coming from as I haven’t used Internet Explorer in a long time.

What perplexed me even more, is I was able to see the same behavior with a client’s PC that I performed a fresh install of Windows on.

So I was looking for a way to identify when the process(es) were initiated and decided on PowerShell because it is baked into Windows so available.
 

Quick and Dirty

Initially, I created a simply PS script that performed a loop every second and checked for the specified process. It looked like:

while ($true) {
    $ieProcess = Get-Process | Where-Object { $_.Name -eq "iexplore" }
    if ($ieProcess) {
        Write-Host "Internet Explorer process found!"
        # break #Uncomment to only report it once and then stop monitoring
    }
    Start-Sleep -Seconds 1
}

Obviously, simply change the ‘1’ to any interval (number of seconds) you’d like to use for your sampling.

Furthermore, PowerShell makes it extremely easy to change the loop delay measurement unit between milliseconds, seconds, minutes, … here’s a few examples of how it would be done:

    Start-Sleep -Milliseconds 250 #Check every 250 milliseconds
    Start-Sleep -Seconds 30 #Check every 30 seconds
    Start-Sleep -Minutes 15 #Check every 15 minutes
    Start-Sleep -Hours 3 #Check every 3 hours

 

A Litlle More Pizzazz

Now the above worked, but it simply displays a notification within the PS ISE window and if I was doing something else it was easy to overlook it. As such, I wanted to up my game a little and display a notification that wasn’t so easy to ignore. That’s when I remembered my Toast work for displaying Windows level notifications and thus I created:

while ($true) {
    $ieProcess = Get-Process | Where-Object { $_.Name -eq "iexplore" }
    if ($ieProcess) {
        New-BurntToastNotification -Text "Alert", "Internet Explorer process found!" -Sound 'Alarm'
        # break #Uncomment to only report it once and then stop monitoring
    }
    Start-Sleep -Seconds 1
}

Then, I adjusted the code slightly so it would check for both processes instead of just the one.

while ($true) {
    $ieProcesses = Get-Process | Where-Object { $_.Name -in ("iexplore", "ielowutil") }
    if ($ieProcesses) {
        $processNames = $ieProcesses.Name -join ", "
        New-BurntToastNotification -Text "Alert", "Internet Explorer-related processes found: $processNames" -Sound 'Alarm'
        # break #Uncomment to only report it once and then stop monitoring
    }
    Start-Sleep -Seconds 1
}

And that where I left things for my needs.
 

Log It Instead

Now, if instead of wanting to display some pop-up notification we simply wanted to log the activity to a text file, we could simply do:

$logFile = "C:\Temp\IEProcessLog.txt"
while ($true) {
    $ieProcesses = Get-Process | Where-Object { $_.Name -in ("iexplore", "ielowutil") }
    if ($ieProcesses) {
        $processDetails = $ieProcesses | ForEach-Object { "$($_.Name) (PID: $($_.Id))" }
        $processInfo = $processDetails -join ", "
        $logMessage = "$(Get-Date -Format 'yyyy-MM-dd HH:mm:ss') - Alert: Internet Explorer-related processes found: $processInfo"
        Add-Content -Path $logFile -Value $logMessage
        # break #Uncomment to only report it once and then stop monitoring
    }
    Start-Sleep -Seconds 1
}

We could easily pursue this further and send a notification e-mail, … but that will be for another day.
 

Terminate the Identified Process(es)

The last step I examined was automatically terminating the found processes.

Prompt The User For Confirmation

while ($true) {
    $ieProcesses = Get-Process | Where-Object { $_.Name -in ("iexplore", "ielowutil") }
    if ($ieProcesses) {
        $processNames = $ieProcesses.Name -join ", "
        New-BurntToastNotification -Text "Alert", "Internet Explorer-related processes found: $processNames" -Sound 'Alarm'
        
        $confirmation = Read-Host "Do you want to terminate these processes? (Y/N)"
        if ($confirmation -eq 'Y') {
            foreach ($process in $ieProcesses) {
                Stop-Process -Id $process.Id -Force
                Write-Host "Terminated process: $($process.Name) (ID: $($process.Id))"
            }
        }
        # break #Uncomment to only report it once and then stop monitoring
    }
    Start-Sleep -Seconds 1
}

Terminate Without User Intervention

while ($true) {
    $ieProcesses = Get-Process | Where-Object { $_.Name -in ("iexplore", "ielowutil") }
    if ($ieProcesses) {
        $processNames = $ieProcesses.Name -join ", "
        New-BurntToastNotification -Text "Alert", "Internet Explorer-related processes found: $processNames" -Sound 'Alarm'
        
        foreach ($process in $ieProcesses) {
            Stop-Process -Id $process.Id -Force
            Write-Host "Terminated process: $($process.Name) (ID: $($process.Id))"
        }
        # break #Uncomment to only report it once and then stop monitoring
    }
    Start-Sleep -Seconds 1
}

 

VBA You Say

Yes, of course, VBA offers us the ability to perform the same type of monitoring. Below would be one possible approach:

Sub ProcessMonitor()
    Dim oWMI                  As Object
    Dim oProcesses            As Object
    Dim oProcess              As Object
    Dim sProcessNames         As String

    Set oWMI = GetObject("winmgmts:\\.\root\cimv2")

    Do
        Set oProcesses = oWMI.ExecQuery("Select * from Win32_Process Where Name='iexplore.exe' OR Name='ielowutil.exe'")
        If oProcesses.Count > 0 Then
            sProcessNames = ""
            For Each oProcess In oProcesses
                If sProcessNames <> "" Then sProcessNames = sProcessNames & ", "
                sProcessNames = sProcessNames & oProcess.Name
            Next oProcess

            ShowNotification "Alert", "Internet Explorer-related processes found: " & sProcessNames
            Exit Do
        End If

        Wait 1
    Loop

    Set oProcess = Nothing
    Set oProcesses = Nothing
    Set oWMI = Nothing
End Sub

Sub ShowNotification(sTitle As String, sMessage As String)
    Dim oWscript              As Object

    Set oWscript = CreateObject("Wscript.Shell")
    oWscript.Popup sMessage, 5, sTitle, vbInformation + vbSystemModal
    Set oWscript = Nothing
End Sub

Sub Wait(seconds As Long)
    Dim endTime               As Date

    endTime = DateAdd("s", seconds, Now())
    Do While Now() < endTime
        DoEvents
    Loop
End Sub