如何使用 Register-ObjectEvent 来检测 PowerShell 中进程的 MainWindowTitle 的变化?

问题描述 投票:0回答:1

我一直在努力寻找任何关于 .Net 事件的例子,这些例子揭示了一个过程的

MainWindowTitle
的变化。

为了检测文件内容的变化,我可以简单地使用

function Register-FileWatcherEvent {
    param (
        [string]$folder,
        [string]$file,
        [string]$SourceIdentifier = 'File_Changed'
    )

    $watcher = New-Object IO.FileSystemWatcher $folder, $file -Property @{
        IncludeSubdirectories = $false
        EnableRaisingEvents = $true
    }
    $watcher.NotifyFilter = 'LastWrite'

    Register-ObjectEvent $watcher -EventName 'Changed' -SourceIdentifier $SourceIdentifier
}

但是我应该使用什么对象、属性和通知程序来注册事件以更改

MainWindowTitle
或相应的属性?

powershell events ui-automation user32
1个回答
2
投票

没有专门的事件可以让您响应进程中的更改

.MainWindowTitle
属性(仅在 Windows 上可用)。

  • System.Diagnotics.Process
    帮助主题显示are可用的事件,向圣地亚哥致敬。从.NET 7开始是:
    OutputDataReceived
    ErrorDataReceived
    (用于接收stdout和stderr输出异步)和
    Exited
    (用于处理进程的终止)。[1]

作为解决方法,您可以基于 System.Timers.Timer

 实例实施定期 
轮询 方法。

  • 请注意,轮询方法本质上比真实事件更占用 CPU。
  • 您可以通过选择较长的轮询操作间隔来减轻影响,但这可能会导致您错过标题更改和/或响应不够快。

下面是一个独立的例子:

# Create an initially disabled timer that fires every 100 msecs. when enabled.
$timer = [System.Timers.Timer] 100

# Get the process whose title should be monitored.
# (The PowerShell instance itself in this example.s)
$process = Get-Process -Id $PID

# Register for the "Elapsed" event. 
# Note the hashtable passed to -MessageData with relevant data from the caller's
# state, which the -Action scriptblock can access via $Event.MessageData
$eventJob = Register-ObjectEvent -InputObject $timer -EventName Elapsed -Action { 
  ($process = $Event.MessageData.Process).Refresh()
  if (($currTitle = $process.MainWindowTitle) -ne $Event.MessageData.CurrentWindowTitle) {
    Write-Verbose -Verbose (
      'Title of process {0} changed from "{1}" to "{2}".' -f $process.Id, $Event.MessageData.CurrentWindowTitle, $currTitle
    )
    $Event.MessageData.CurrentWindowTitle = $currTitle
  }
} -MessageData @{
  Process = $process
  CurrentWindowTitle = $process.MainWindowTitle
}

# Sample code that sleeps a little and changes the window title, twice.

Write-Verbose -vb 'Starting the timer...'
# Note that the first event will fire only 
# after the configured interval has elapsed.
$timer.Start() # alternative: $timer.Enabled = $true
try {

    Write-Verbose -vb 'About to change the title twice...'

    # Simulate foreground activity.
    # Note: Do NOT use Start-Sleep, because event processing is BLOCKED during sleep.
    $eventJob | Wait-Job -Timeout 1

    [Console]::Title = 'foo'
    $eventJob | Wait-Job -Timeout 1
    [Console]::Title = 'bar'

    $eventJob | Wait-Job -Timeout 1

} finally {
   Write-Verbose -vb 'Stopping the timer and removing the event job...'
   $timer.Dispose()
   Remove-Job $eventJob -Force
}

样本输出:

VERBOSE: Starting the timer...
VERBOSE: About to change the title twice...
VERBOSE: Title of process 3144 changed from "Windows PowerShell" to "foo".
VERBOSE: Title of process 3144 changed from "foo" to "bar".
VERBOSE: Stopping timer and removing the event job...

[1] 还有继承的

Disposed
事件,但它与 .NET 实例本身有关,而不是它所代表的进程。

© www.soinside.com 2019 - 2024. All rights reserved.