powershellwindows-10plug-and-play

How to log "new pnp devices" events to console on Windows?


I want to write something like nestat (that log new tcp connections to console) but for pnp devices with powershell.

Is there an API method "to subscribe to some kind of events bus" specific to PnP and get "connected" and "disconnected" events?

Or only one way to achive this is looping with Get-PnpDevice and "manually" seacrh for the differences?


Solution

  • You can use WMI events to do this. For example, here is one way to do it (seems over-complicated, so maybe someone can improve on it):

    $addIdentifier = "WMI.PnpAddEvent"
    $removeIdentifier = "WMI.PnpRemoveEvent"
    
    $addAction = { $pnpEntity = $EventArgs.NewEvent.TargetInstance; Write-Host "`nPNPEvent: Plugged In`nCaption: $($pnpEntity.Caption)`nPNPDeviceID: $($pnpEntity.PNPDeviceID)`n" }
    $addQuery = "SELECT * FROM __instancecreationevent WITHIN 5 WHERE targetinstance isa 'Win32_PnPEntity'"
    
    $removeAction = { $pnpEntity = $EventArgs.NewEvent.TargetInstance; Write-Host "`nPNPEvent: Unplugged`nCaption: $($pnpEntity.Caption)`nPNPDeviceID: $($pnpEntity.PNPDeviceID)`n" }
    $removeQuery = "SELECT * FROM __instancedeletionevent WITHIN 5 WHERE targetinstance isa 'Win32_PnPEntity'"
    
    $addEventArgs = @{
        Query            = $addQuery
        SourceIdentifier = $addIdentifier
        SupportEvent     = $true
        Action           = $addAction
    }
    
    $removeEventArgs = @{
        Query            = $removeQuery
        SourceIdentifier = $removeIdentifier
        SupportEvent     = $true
        Action           = $removeAction
    }
    
    Register-WmiEvent @addEventArgs
    Register-WmiEvent @removeEventArgs
    

    Now, when you add/remove a device, you'll get output like this in the console:

    PNPEvent: Unplugged
    Caption: Apple iPhone
    PNPDeviceID: USB\VID_05AC&PID_12A8&MI_00\E&2491F388&0&0000    
    
    PNPEvent: Plugged In
    Caption: Apple iPhone
    PNPDeviceID: USB\VID_05AC&PID_12A8&MI_00\E&2491F388&0&0000
    

    A couple of things to keep in mind:

    As mentioned, the registrations should be cancelled when your session ends, but if you want to do it manually, you can do it like this:

    $addIdentifier, $removeIdentifier | ForEach-Object { Unregister-Event -Force -SourceIdentifier $_ }