plugging/unplugging 笔记本电脑通过任务计划程序更改特定设置

Change a specific setting when plugging/unplugging laptop via task scheduler

免责声明:我用他们所代表的全部大写字符串更改了所有个人信息。

我将开门见山:我希望我的浏览器在我的笔记本电脑插入电源时使用我的 dGPU,而在未插入电源时使用我的 iGPU。

到目前为止,我已经在 Windows 设置中为我的浏览器设置了始终使用我的 dGPU(设置说:“高性能”):
然后每次我 plug/unplug 我的笔记本电脑我手动更改该设置并重新启动我的浏览器。

因为每次都这样做很烦人,我想使用 Windows 10 Task Scheduler 到 运行 一个脚本,当我的笔记本电脑启动时将设置更改为“高性能”当我的笔记本电脑被拔掉时,插入电源或将该设置更改为“节电”。
在这两种情况下,如果浏览器已打开,它还应通知用户重新启动浏览器以使更改生效。

我设法找到了这两个事件的日志:

<Event xmlns="http://schemas.microsoft.com/win/2004/08/events/event">
  <System>
    <Provider Name="Microsoft-Windows-Kernel-Power" Guid="{331c3b3a-2005-44c2-ac5e-77220c37d6b4}" /> 
    <EventID>105</EventID> 
    <Version>1</Version> 
    <Level>4</Level> 
    <Task>100</Task> 
    <Opcode>0</Opcode> 
    <Keywords>0x8000000000000404</Keywords> 
    <TimeCreated SystemTime="2022-05-28T09:44:34.5100785Z" /> 
    <EventRecordID>13688</EventRecordID> 
    <Correlation /> 
    <Execution ProcessID="4" ThreadID="3004" /> 
    <Channel>System</Channel> 
    <Computer>COMPUTER</Computer> 
    <Security UserID="USERID" /> 
  </System>
  <EventData>
    <Data Name="AcOnline">false</Data> 
    <Data Name="RemainingCapacity">30111</Data> 
    <Data Name="FullChargeCapacity">91245</Data> 
  </EventData>
</Event>

(堵塞事件的日志相同,但 AcOnline 设置为 true)。

我写的脚本如下:

Param([Parameter()][switch]$AcOnline)

enum GPU {
  Integrated = 1
  Dedicated = 2
}

function Update-Opera-GPU-Preference {
  Param([Parameter()][GPU]$GPU)
  Set-ItemProperty -Path 'HKCU:\Software\Microsoft\DirectX\UserGpuPreferences\' -Name 'PATHTOPROGRAMS\Opera GX\opera.exe' -Value "GpuPreference=$($GPU.value__);"
}

function Restart-Opera {
  Param([Parameter()]$opera)
  $opera.CloseMainWindow()
  Start-Sleep 3
  if (!$opera.HasExited) {
    $opera | Stop-Process -Force
  }
  $opera.Start() # Gives error. How to restart?
}

function Send-Preference-Changed-Toast {
  Param([Parameter()]$opera)
  [Windows.UI.Notifications.ToastNotificationManager, Windows.UI.Notifications, ContentType = WindowsRuntime] > $null
  $Template = [Windows.UI.Notifications.ToastNotificationManager]::GetTemplateContent([Windows.UI.Notifications.ToastTemplateType]::ToastText02)

  $RawXml = [xml] $Template.GetXml()
  ($RawXml.toast.visual.binding.text|Where-Object {$_.id -eq "1"}).AppendChild($RawXml.CreateTextNode("Opera GX GPU setting changed")) > $null
  ($RawXml.toast.visual.binding.text|Where-Object {$_.id -eq "2"}).AppendChild($RawXml.CreateTextNode("Restart Opera GX for the change to take effect")) > $null
  # Add on click behavior to restart opera if opera is open
  # Restart-Opera $opera

  $SerializedXml = New-Object Windows.Data.Xml.Dom.XmlDocument
  $SerializedXml.LoadXml($RawXml.OuterXml)

  $Toast = [Windows.UI.Notifications.ToastNotification]::new($SerializedXml)
  $Toast.Tag = "Task Scheduler"
  $Toast.Group = "Task Scheduler"
  $Toast.ExpirationTime = [DateTimeOffset]::Now.AddMinutes(1)

  $Notifier = [Windows.UI.Notifications.ToastNotificationManager]::CreateToastNotifier("Task Scheduler")
  $Notifier.Show($Toast);
}

Update-Opera-GPU-Preference $(if ($AcOnline.IsPresent) {[GPU]::Dedicated} else {[GPU]::Integrated})
$opera = Get-Process opera -ErrorAction SilentlyContinue
if ($opera) {
  Send-Preference-Changed-Toast $opera
}
Remove-Variable opera

然后我创建了这样的任务:

<?xml version="1.0" encoding="UTF-16"?>
<Task version="1.4" xmlns="http://schemas.microsoft.com/windows/2004/02/mit/task">
  <RegistrationInfo>
    <Date>2022-05-28T10:52:12.1836624</Date>
    <Author>AUTHOR</Author>
    <URI>\Change Opera GX GPU Setting</URI>
  </RegistrationInfo>
  <Triggers>
    <EventTrigger>
      <Enabled>true</Enabled>
      <Subscription>&lt;QueryList&gt;&lt;Query Id="0" Path="Microsoft-Windows-Kernel-Power/Thermal-Operational"&gt;&lt;Select Path="Microsoft-Windows-Kernel-Power/Thermal-Operational"&gt;*[System[Provider[@Name='Microsoft-Windows-Kernel-Power'] and EventID=105]]&lt;/Select&gt;&lt;/Query&gt;&lt;/QueryList&gt;</Subscription>
    </EventTrigger>
  </Triggers>
  <Principals>
    <Principal id="Author">
      <UserId>USERID</UserId>
      <LogonType>Password</LogonType>
      <RunLevel>HighestAvailable</RunLevel>
    </Principal>
  </Principals>
  <Settings>
    <MultipleInstancesPolicy>IgnoreNew</MultipleInstancesPolicy>
    <DisallowStartIfOnBatteries>false</DisallowStartIfOnBatteries>
    <StopIfGoingOnBatteries>false</StopIfGoingOnBatteries>
    <AllowHardTerminate>true</AllowHardTerminate>
    <StartWhenAvailable>true</StartWhenAvailable>
    <RunOnlyIfNetworkAvailable>false</RunOnlyIfNetworkAvailable>
    <IdleSettings>
      <StopOnIdleEnd>true</StopOnIdleEnd>
      <RestartOnIdle>false</RestartOnIdle>
    </IdleSettings>
    <AllowStartOnDemand>true</AllowStartOnDemand>
    <Enabled>true</Enabled>
    <Hidden>false</Hidden>
    <RunOnlyIfIdle>false</RunOnlyIfIdle>
    <DisallowStartOnRemoteAppSession>false</DisallowStartOnRemoteAppSession>
    <UseUnifiedSchedulingEngine>true</UseUnifiedSchedulingEngine>
    <WakeToRun>false</WakeToRun>
    <ExecutionTimeLimit>PT0S</ExecutionTimeLimit>
    <Priority>7</Priority>
    <RestartOnFailure>
      <Interval>PT1M</Interval>
      <Count>3</Count>
    </RestartOnFailure>
  </Settings>
  <Actions Context="Author">
    <Exec>
      <Command>powershell</Command>
      <Arguments>-ExecutionPolicy Bypass -File PATHTOSCRIPTFOLDER\opera-gpu-setting-update.ps1</Arguments>
    </Exec>
  </Actions>
</Task>

如果我手动 运行 任务,它工作正常。但是,如果我插入笔记本电脑,它只会用 Windows 记事本打开脚本文件,而不是 运行ning 脚本。此外,如果我拔下笔记本电脑,任务似乎根本不会 运行(没有脚本正在执行,记事本也不会打开)。

为什么会这样?我该如何解决这个问题?
如何在我的脚本中实现注释中描述的部分?

最后打开记事本是因为我错误地创建了另一个任务
真正的问题是订阅标签值错误。为了修复它,我转到 Windows 事件记录器并从 Kernel-Power 事件创建了一个新任务,然后复制了它的 XML 订阅标签并将其粘贴到我的任务 XML 中。
更新后的标签如下所示:

<Subscription>&lt;QueryList&gt;&lt;Query Id="0" Path="System"&gt;&lt;Select Path="System"&gt;*[System[Provider[@Name='Microsoft-Windows-Kernel-Power'] and EventID=105]]&lt;/Select&gt;&lt;/Query&gt;&lt;/QueryList&gt;</Subscription>