Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
1.2k views
in Technique[技术] by (71.8m points)

powershell - Running a script before locking a computer on Windows

I've written some powershell which allows me to harness the power of the keyboard media keys to control any music that's currently running.

What I want to be able to do is run the script on the event of the computer being locked. So I can pause/stop the music. Then once the machine is unlocked, resume the music. Cool huh?!

My first 2 attempts have been:

1 - WMI Event registration

This is the on lock event

Register-wmievent –query "Select * from __instancecreationevent within 1 where TargetInstance isa 'Win32_NTLogEvent' And TargetInstance.EventCode = 4800" -Action {write-host "Pausing`r`n"; set-playpausetrack}

This is the unlock event

Register-wmievent –query "Select * from __instancecreationevent within 1 where TargetInstance isa 'Win32_NTLogEvent' And TargetInstance.EventCode = 4801" -Action {write-host "Resuming`r`n"; set-playpausetrack}

Unfortunately, I think the lock event fires too late, at which point background interaction is halted by the OS for security reasons. When I unlock the computer it fires both the locked and unlocked events.

2 - Using the task scheduler "On workstation locked" trigger

Similar issue to above, but it also runs in a different context so doesn't work properly.

Does anyone know how to get a script to run before the system actually locks? I.e. is there an event I can watch for which triggers before?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

This seems to work

PS> $sysevent = [microsoft.win32.systemevents]
PS> $sysevent

IsPublic IsSerial Name                                     BaseType
-------- -------- ----                                     --------
True     False    SystemEvents                             System.Object


PS> Register-ObjectEvent -InputObject $sysevent -EventName "SessionSwitch" -Action {[console]::Beep()}

Id              Name            State      HasMoreData     Location             Command
--              ----            -----      -----------     --------             -------
1               fa48b95f-299... NotStarted False                                [console]::Beep()

You can find the list of SytemEvents in Microsoft documentation.

DisplaySettingsChanged  Occurs when the user changes the display settings. 
DisplaySettingsChanging Occurs when the display settings are changing. 
EventsThreadShutdown    Occurs before the thread that listens for system events is terminated. 
InstalledFontsChanged   Occurs when the user adds fonts to or removes fonts from the system. 
LowMemory               Occurs when the system is running out of available RAM. 
PaletteChanged          Occurs when the user switches to an application that uses a different palette. 
PowerModeChanged        Occurs when the user suspends or resumes the system. 
SessionEnded            Occurs when the user is logging off or shutting down the system. 
SessionEnding           Occurs when the user is trying to log off or shut down the system. 
SessionSwitch           Occurs when the currently logged-in user has changed. 
TimeChanged             Occurs when the user changes the time on the system clock. 
TimerElapsed            Occurs when a windows timer interval has expired. 
UserPreferenceChanged   Occurs when a user preference has changed. 
UserPreferenceChanging  Occurs when a user preference is changing. 

To unregister event

PS> Unregister-Event -SubscriptionId 1

If you want to be able to distinguish Lock and Unlock the SessionSwitchEventHandler receives two parameters

  1. The source of the event.
  2. SessionSwitchEventArgs indicating the type of the session change event.

The SessionSwitchEventArgs own one propertie Reason which is an enum SessionSwitchReason values are :

ConsoleConnect        A session has been connected from the console.  
ConsoleDisconnect     A session has been disconnected from the console.  
RemoteConnect         A session has been connected from a remote connection.  
RemoteDisconnect      A session has been disconnected from a remote connection.  
SessionLogon          A user has logged on to a session.  
SessionLogoff         A user has logged off from a session.  
SessionLock           A session has been locked.  
SessionUnlock         A session has been unlocked.  
SessionRemoteControl  A session has changed its status to or from remote controlled mode.

Example :

PS> Register-ObjectEvent -InputObject $sysevent -EventName "SessionSwitch" -Action {[console]::Beep();Write-Host ($args[1]).Reason}

Id              Name            State      HasMoreData     Location             Command
--              ----            -----      -----------     --------             -------
9               20e6ecd4-fc0... NotStarted False                                [console]::Beep();fore...


PS >
SessionLock

SessionUnlock

If you want a list of events suscribed you can use Get-EventSubscriber :

SubscriptionId   : 5
SourceObject     : Microsoft.Win32.SystemEvents
EventName        : SessionSwitch
SourceIdentifier : 96fbabe4-518a-47b5-8a3f-bb89c68f7f39
Action           : System.Management.Automation.PSEventJob
HandlerDelegate  :
SupportEvent     : False
ForwardEvent     : False

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...