|
[CmdletBinding()] |
|
|
|
# Run Get-PnpDevice to find the full device names |
|
$devices = @{ |
|
InternalGpu = "Intel(R) UHD Graphics 630" |
|
DiscreteGpu = "NVIDIA GeForce GTX 1050 Ti with Max-Q Design" |
|
ExternalGpu = "AMD Radeon RX 5700 XT" |
|
} |
|
|
|
# Relaunch as an elevated process: |
|
if (-NOT ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)) { |
|
Start-Process powershell.exe "-File", ('"{0}"' -f $MyInvocation.MyCommand.Path) -Verb RunAs |
|
exit |
|
} |
|
|
|
# Make PowerShell Disappear |
|
$windowcode = '[DllImport("user32.dll")] public static extern bool ShowWindowAsync(IntPtr hWnd, int nCmdShow);' |
|
$asyncwindow = Add-Type -MemberDefinition $windowcode -name Win32ShowWindowAsync -namespace Win32Functions -PassThru |
|
$null = $asyncwindow::ShowWindowAsync((Get-Process -PID $pid).MainWindowHandle, 0) |
|
|
|
function Get-Devices { |
|
$names = $devices.GetEnumerator() | % { $_.Value } |
|
Get-PnpDevice | Where-Object { |
|
$_.friendlyName -in $names |
|
} |
|
} |
|
function Get-Device { |
|
param ( [string]$deviceName ) |
|
$input | Where-Object { $_.friendlyname -like $deviceName } |
|
} |
|
|
|
function Disable-Device { |
|
param ( [string]$deviceName ) |
|
Write-Verbose "Disabling $deviceName" |
|
Get-Devices | Get-Device $deviceName | Disable-PnpDevice -Confirm:$false |
|
Start-Sleep -s 1 |
|
} |
|
|
|
function Enable-Device { |
|
param ( [string]$deviceName ) |
|
Write-Verbose "Enabling $deviceName" |
|
Get-Devices | Get-Device $deviceName | Enable-PnpDevice -Confirm:$false |
|
Start-Sleep -s 1 |
|
} |
|
|
|
function Switch-Device { |
|
param ( [string]$deviceName ) |
|
$status = (Get-Devices | Get-Device $deviceName).status |
|
if ($status -like "error") { |
|
# disabled |
|
Enable-Device $deviceName |
|
} |
|
elseif ($status -like "ok") { |
|
# enabled |
|
Disable-Device $deviceName |
|
} |
|
else { |
|
Write-Verbose "Not toggling, status: $status" |
|
} |
|
} |
|
|
|
function Get-Device-Status { |
|
param ( [string]$deviceName ) |
|
$allDevices = $input |
|
if ($null -eq $allDevices) { |
|
$allDevices = (Get-Devices) |
|
} |
|
$status = (($allDevices | Get-Device $deviceName).status) |
|
return $status |
|
} |
|
|
|
|
|
[System.Reflection.Assembly]::LoadWithPartialName('System.Windows.Forms') | out-null |
|
[System.Reflection.Assembly]::LoadWithPartialName('presentationframework') | out-null |
|
[System.Reflection.Assembly]::LoadWithPartialName('System.Drawing') | out-null |
|
[System.Reflection.Assembly]::LoadWithPartialName('WindowsFormsIntegration') | out-null |
|
|
|
$icon = [System.Drawing.Icon]::ExtractAssociatedIcon("C:\Windows\System32\resmon.exe") |
|
|
|
# Create an application context for it to all run within. |
|
# This helps with responsiveness, especially when clicking Exit. |
|
$appContext = New-Object System.Windows.Forms.ApplicationContext |
|
|
|
# ---------------------------------------------------- |
|
# Add the systray menu |
|
# ---------------------------------------------------- |
|
|
|
$Main_Tool_Icon = New-Object System.Windows.Forms.NotifyIcon |
|
$Main_Tool_Icon.Text = "GPU Systray" |
|
$Main_Tool_Icon.Icon = $icon |
|
$Main_Tool_Icon.Visible = $true |
|
|
|
$gpu_Menus = $devices.GetEnumerator() | ForEach-Object { |
|
$menu = New-Object System.Windows.Forms.MenuItem |
|
$menu.Text = $_.Value |
|
$menu.add_Click( { Switch-Device $this.Text }) |
|
return $menu |
|
} |
|
|
|
$Menu_Exit = New-Object System.Windows.Forms.MenuItem |
|
$Menu_Exit.Text = "Exit" |
|
|
|
$contextmenu = New-Object System.Windows.Forms.ContextMenu |
|
$Main_Tool_Icon.ContextMenu = $contextmenu |
|
$Main_Tool_Icon.contextMenu.MenuItems.AddRange($gpu_Menus) |
|
$Main_Tool_Icon.contextMenu.MenuItems.AddRange($Menu_Exit) |
|
|
|
$Main_Tool_Icon.ContextMenu.Add_Popup( { |
|
$devices = Get-Devices |
|
foreach ($menu in $gpu_Menus) { |
|
$menu.Checked = ($devices | Get-Device-Status $menu.Text) -like "ok" |
|
} |
|
}) |
|
|
|
|
|
# When Exit is clicked, close everything and kill the PowerShell process |
|
$Menu_Exit.add_Click( { |
|
$Main_Tool_Icon.Visible = $false |
|
$Main_Tool_Icon.Dispose() |
|
$appContext.ExitThread() |
|
exit |
|
}) |
|
|
|
# Force garbage collection just to start slightly lower RAM usage. |
|
[System.GC]::Collect() |
|
|
|
[void][System.Windows.Forms.Application]::Run($appContext) |