Problem using Register-ObjectEvent in the PowerShell Console.

Hi guys,

I am trying to set up some PowerShell code that listens for a System Event, namely when a Display Setting in Windows is changed, then play a beep sound (the beep will later be replaced by a script that selects an appropriately sized wallpaper).

I’m noticing that the code below works perfectly fine when run from the ISE, but doesn’t seem to work from the Shell. When I change a Display setting (in this case the screen resolution), nothing happens.

Can anyone explain what i’m doing wrong? and what the difference is between the ISE and Shell?

[PRE]

$Event = [Microsoft.Win32.SystemEvents]
$EventName = ‘DisplaySettingsChanged’
$Action = {
[console]::beep()
Write-Host “Beep”
}
Register-ObjectEvent -InputObject $Event -EventName $EventName -Action $Action

[/PRE]

Hi Bobby - Check to run Get-Event whether the event is registered or not, and run Get-Job to check whether the action is triggered or not. Thank you.

The results are identical in both the Shell and the ISE, but the code only works in the ISE. The ISE seems to be constantly running in the background, where the Shell isn’t. Not really sure what the difference is.

[pre]

PS H:> $Event = [Microsoft.Win32.SystemEvents]
$EventName = ‘DisplaySettingsChanged’
$Action = {
[console]::beep()
Write-Host “Beep”
}
Register-ObjectEvent -InputObject $Event -EventName $EventName -Action $Action

Id Name PSJobTypeName State HasMoreData Location Command


1 2ad636ba-a79… NotStarted False …

PS H:> Get-Job

Id Name PSJobTypeName State HasMoreData Location Command


1 2ad636ba-a79… NotStarted False …

PS H:> Get-Event

PS H:> Get-EventSubscriber

SubscriptionId : 1
SourceObject : Microsoft.Win32.SystemEvents
EventName : DisplaySettingsChanged
SourceIdentifier : 2ad636ba-a79b-4b93-b094-cd5914b53140
Action : System.Management.Automation.PSEventJob
HandlerDelegate :
SupportEvent : False
ForwardEvent : False

PS H:> Beep
Beep

[/pre]

Are you using Windows PowerShell or PowerShell Core?

For what it is worth, the Register-ObjectEvent only lives within the current session. If the process stops or restarts it will need to be declared again in that new session. If persistence is desired you may want to consider WMI Event Consumers. They are bound to a WQL Query (WMI Filter) and then reside in the WMI repository, persisting reboots, etc.

@Bobby20 Can you try this in PS core 6.2.0 - Preview 3 and raise an issue here.

Thanks for the responses guys. I am using Windows Power Shell, not Core.

Name Value


PSVersion 5.1.16299.820
PSEdition Desktop
PSCompatibleVersions {1.0, 2.0, 3.0, 4.0…}
BuildVersion 10.0.16299.820
CLRVersion 4.0.30319.42000
WSManStackVersion 3.0
PSRemotingProtocolVersion 2.3
SerializationVersion 1.1.0.1

The code works in the ISE, where the beeping sound fires off when I change resolution settings. I’m still unsure why it doesn’t work in the Shell/Console. I understand that Register-ObjectEvent is session based, but shouldn’t it still work until I close the PowerShell Window?

I think I will have a look into WMI Event Consumers as Logan suggested.

 

Thank for the prompt response Logan. I don’t know too much about WMI Event Consumers, but persistence is certainly desired. I’m basically trying to achieve a persistent script that will change wallpapers depending on screen resolution. Is there an equivalent WMI class I can query to listen for this type of event ie) when display settings are changed?

 

[quote quote=133938]Thank for the prompt response Logan. I don’t know too much about WMI Event Consumers, but persistence is certainly desired. I’m basically trying to achieve a persistent script that will change wallpapers depending on screen resolution. Is there an equivalent WMI class I can query to listen for this type of event ie) when display settings are changed?

[/quote]
I am still learning about WMI consumers, there is not a lot of well documented stuff on the interwebs. Mostly the same couple of examples for monitoring a directory for changes to filenames, or formatting a USB drive upon insertion. I have a couple of solutions I have crafted for my own purposes and to learn more about the concepts. I have learned a lot and plan on writing a couple of blog posts on the topic and sharing my original examples based on methodology adapted by Ed Wilson, Boe Prox, and Trevor Sullivan on their blog posts. Its a VERY in-depth topic and I don’t have time to dive into all of it. I will share with you the starting point for it all, a working WQL query.

[pre]

$query = “SELECT * FROM __InstanceModificationEvent WITHIN .1 WHERE TargetInstance ISA ‘Win32_VideoController’”

[/pre]

You can use wbemtest.exe to test queries and examine TargetInstance objects in depth. I will also share some of the blogs I have used as a jumping off point to develop my solutions.

CodeProject (Good examples of consumers in MOF format)
https://www.codeproject.com/articles/28226/%2FArticles%2F28226%2FCreating-WMI-Permanent-Event-Subscriptions-Using-M

Boe Prox Blog on WMI Consumers

Ed Wilson

 

A word of caution… These bindings are PERMENANT and require explicit removal from WMI or a re-image of the box to get rid of. If you are not paying close attention, or are not completely comfortable with finding and removing bindings in WMI be careful! Pay attention to what you are doing and make sure you are on a DEV box.