Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Select an option

  • Save blakeNaccarato/95b576da40b016a5e1697d96fc09bfc8 to your computer and use it in GitHub Desktop.

Select an option

Save blakeNaccarato/95b576da40b016a5e1697d96fc09bfc8 to your computer and use it in GitHub Desktop.
Windows Sunshine/Moonlight monitor config scripts and guide

Windows Sunshine/Moonlight monitor config

Scripts and guide to automatic monitor configuration when streaming with Sunshine/Moonlight on Windows.

  • Click "Download ZIP" in the top-right corner of this Gist, and extract scripts to e.g. C:/ (or a directory of your choosing)
  • Download MultiMonitorTool
  • Place scripts and MultiMonitorTool.exe in a directory next to your scripts, or add the tool to your system $PATH
  • Modify your Sunshine "Do command" and "Undo command"
# Do Command
powershell.exe C:/Set-SunshineDo.ps1
# Undo Command
powershell.exe C:/Set-SunshineUndo.ps1

Next, modify Set-SunshineDo.ps1 and Set-SunshineUndo.ps1 (see below for how to find "

ID"). You can run e.g. Get-Help -Detailed .\Set-Monitors.ps1 to see what each parameter means. Note that these scripts use argument splatting for legibility, and is equivalent to the usual command-line syntax e.g. Set-Monitors.ps1 ... -Width 1920 -Height 1080.

  • Modify or remove the Tool argument, depending on where you put MultiMonitorTool.exe
  • Replace <YOUR_PRIMARY_MONITOR_SHORT_ID>
  • Remove the line for Disable if desired, or provide <SECONDARY_MONITOR_SHORT_ID_TO_DISABLE> (you may also provide an array of strings to enable/disable multiple monitors, e.g. '<FIRST_MONITOR_TO_DISABLE>', '<SECOND MONITOR TO DISABLE>')
  • Set Width, Height, and optionally, Scale for your setup
  • Optionally, Move or Maximize all windows to the primary monitor

See screenshots below for how to find the "Short Monitor ID" for your monitors. The Primary argument defaults to 'Primary', but this sometimes selects the wrong monitor so you should set it to the explicit "Short Monitor ID" of your primary monitor.

The Disable and Enable arguments are optional, in some cases disabling a secondary monitor when streaming Sunshine can reduce the occurrence of momentary "bitrate warning" freeze-ups on e.g. Moonlight clients. You could use e.g. \\.\DISPLAY3 to refer to Disable or Enable monitors (or Primary), but this sometimes disables the wrong monitor, so use the explicit "Short Monitor ID" of the monitor you may wish to disable.

image

image

image

<#.SYNOPSIS
Configure monitors. Optionally move/maximize windows.
#>
param(
# Path to MultiMonitorTool.exe. Download from https://www.nirsoft.net/utils/multi_monitor_tool.html. If not given, looks for it on system path or next to this script.
[string]$Tool,
# Primary monitor
[string]$Primary = 'Primary',
# Primary monitor width
[int]$Width,
# Primary monitor height
[int]$Height,
# Primary monitor DPI scaling
[int]$Scale,
# Monitor(s) to disable
[string[]]$Disable = @(),
# Monitor(s) to enable
[string[]]$Enable = @(),
# Move windows to the primary monitor
[switch]$Move,
# Maximize windows when moving them
[switch]$Maximize
)
#? Get tool path
$MultiMonitorToolNotFoundMessage = @'
MultiMonitorTool.exe not found
Download it from https://www.nirsoft.net/utils/multi_monitor_tool.html and place it
next to this script, add it to $PATH, or explicitly provide its path
to the -Tool parameter of this script.
'@
if (!$Tool) {
if ($Cmd = Get-Command 'MultiMonitorTool' -ErrorAction 'Ignore') { $Tool = $Cmd }
elseif (Test-Path ($Path = 'MultiMonitorTool.exe')) { $Tool = $Path }
elseif (Test-Path ($Path = "$PSScriptRoot/MultiMonitorTool.exe")) { $Tool = $Path }
else { throw $MultiMonitorToolNotFoundMessage }
}
#? Check that both width and height are specified if one is specified
$WidthHeightMessage = 'Expected both width and height to be specified.'
if (($Width -or $Height) -and !($Width -and $Height)) { throw $WidthHeightMessage }
#? Set primary monitor if needed
if ($Primary -ne 'Primary') { & $Tool /SetPrimary $Primary}
$Primary = 'Primary'
#? Set scale, move windows, enable or disable desired monitors, set resolution.
#? See Version 2.15 in Version History which mentions that the tool must be called
#? more than once since Windows 11 update 24H2. Scale changes seem to be the issue,
#? so we set scale a few times after the initial scale setting operation.
#? See: https://www.nirsoft.net/utils/multi_monitor_tool.html
if ($Scale) { $ScaleArgs = '/SetScale', $Primary, $Scale }
$ToolArgs = @(
if ($Scale) { $ScaleArgs }
if ($Move) { '/MoveWindow', $Primary, 'All' }
if ($Width -or $Height) { '/SetMonitors', "Name=$Primary Width=$Width Height=$Height" }
if ($Enable.Count) { $Enable | ForEach-Object { '/Enable', $_, '/TurnOn', $Name } }
if ($Disable.Count) { $Disable | ForEach-Object { '/Disable', $_, '/TurnOff', $Name } }
)
if ($ToolArgs.Count) {
& $Tool @ToolArgs
if ($Scale) { 1..2 | ForEach-Object { & $Tool @ScaleArgs } }
}
#? If not maximizing, we're done
if (!$Maximize) { return }
#? Define Win32 API function to maximize windows
Add-Type -Name 'Win32ShowWindow' -Namespace 'User32' -MemberDefinition @'
[DllImport("user32.dll")]
public static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);
'@
#? Maximize windows using the Win32 API
$ShowWindowMaximized = 3
(Get-Process | Where-Object { $_.MainWindowTitle }).MainWindowHandle |
ForEach-Object {
[User32.Win32ShowWindow]::ShowWindow($_, $ShowWindowMaximized)
} |
Out-Null
<#.SYNOPSIS
Sunshine "Do Command".
#>
$SetMonitorsArgs = @{
# Tool = "<PATH TO...>/MultiMonitorTool.exe" #? Only if `MultiMonitorTool.exe` can't be found.
Primary = '<YOUR_PRIMARY_MONITOR_SHORT_ID>'
Width = 1920
Height = 1080
Scale = 150
Move = $True
Maximize = $True
Disable = '<SECONDARY_MONITOR_SHORT_ID_TO_DISABLE>'
# Disable = '<FIRST_MONITOR_SHORT_ID_TO_DISABLE>', '<SECOND_MONITOR_SHORT_ID_TO_DISABLE>' # Or disable multiple
}
& "$PSScriptRoot/Set-Monitors.ps1" $SetMonitorsArgs
<#.SYNOPSIS
Sunshine "Undo Command".
#>
$SetMonitorsArgs = @{
# Tool = "<PATH TO...>/MultiMonitorTool.exe" #? Only if `MultiMonitorTool.exe` can't be found.
Primary = '<YOUR_PRIMARY_MONITOR_SHORT_ID>'
Width = 3440
Height = 1440
Scale = 125
Enable = '<SECONDARY_MONITOR_SHORT_ID_TO_ENABLE>'
# Enable = '<FIRST_MONITOR_SHORT_ID_TO_ENABLE>', '<SECOND_MONITOR_SHORT_ID_TO_ENABLE>' # Or enable multiple
}
& "$PSScriptRoot/Set-Monitors.ps1" $SetMonitorsArgs
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment