Created
August 9, 2025 20:46
-
-
Save AlexDev404/118e5365c1914bebbae0f141805f73a3 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add-Type @" | |
using System; | |
using System.Runtime.InteropServices; | |
using System.Diagnostics; | |
public class Win32 { | |
[DllImport("user32.dll")] | |
public static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, | |
int X, int Y, int cx, int cy, uint uFlags); | |
[DllImport("user32.dll")] | |
public static extern bool ShowWindow(IntPtr hWnd, int nCmdShow); | |
[DllImport("user32.dll")] | |
public static extern bool IsWindowVisible(IntPtr hWnd); | |
[DllImport("user32.dll")] | |
public static extern IntPtr GetShellWindow(); | |
[DllImport("user32.dll")] | |
public static extern IntPtr GetWindow(IntPtr hWnd, uint uCmd); | |
[DllImport("user32.dll")] | |
[return: MarshalAs(UnmanagedType.Bool)] | |
public static extern bool EnumWindows(EnumWindowsProc lpEnumFunc, IntPtr lParam); | |
[DllImport("user32.dll")] | |
public static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint lpdwProcessId); | |
public delegate bool EnumWindowsProc(IntPtr hWnd, IntPtr lParam); | |
public static IntPtr FindMainWindow(uint processId) { | |
IntPtr windowHandle = IntPtr.Zero; | |
EnumWindows(delegate (IntPtr hWnd, IntPtr lParam) { | |
uint windowProcessId; | |
GetWindowThreadProcessId(hWnd, out windowProcessId); | |
if (windowProcessId == processId && IsWindowVisible(hWnd) && hWnd != GetShellWindow()) { | |
windowHandle = hWnd; | |
return false; // stop enumerating | |
} | |
return true; // continue enumerating | |
}, IntPtr.Zero); | |
return windowHandle; | |
} | |
} | |
"@ | |
# Constants for SetWindowPos | |
$SWP_SHOWWINDOW = 0x0040 | |
$HWND_TOP = [IntPtr]::Zero | |
$SW_SHOWNORMAL = 1 | |
Add-Type -AssemblyName System.Windows.Forms | |
$monitors = [System.Windows.Forms.Screen]::AllScreens | |
# If only one monitor, exit | |
if ($monitors.Count -lt 2) { | |
Write-Host "Only one monitor detected. Exiting..." | |
exit | |
} | |
# Application path | |
$appPath = "C:\Program Files (x86)\Xibo Player\XiboClient.exe" | |
function Start-And-MoveWindow { | |
param( | |
[string]$appPath, | |
[System.Drawing.Rectangle]$bounds, | |
[PSCredential]$cred = $null, | |
[string]$workingDir = $null | |
) | |
if ($null -ne $cred) { | |
$process = Start-Process -FilePath $appPath -PassThru -Credential $cred -WorkingDirectory $workingDir | |
} else { | |
$process = Start-Process $appPath -PassThru | |
} | |
# Wait for main window to appear | |
$hwnd = [IntPtr]::Zero | |
for ($i=0; $i -lt 20; $i++) { | |
Start-Sleep -Milliseconds 500 | |
$hwnd = [Win32]::FindMainWindow($process.Id) | |
if ($hwnd -ne [IntPtr]::Zero) { break } | |
} | |
if ($hwnd -ne [IntPtr]::Zero) { | |
[Win32]::ShowWindow($hwnd, $SW_SHOWNORMAL) | Out-Null | |
[Win32]::SetWindowPos($hwnd, $HWND_TOP, $bounds.X, $bounds.Y, $bounds.Width, $bounds.Height, $SWP_SHOWWINDOW) | Out-Null | |
Write-Host ("Moved and resized window to monitor at X={0}, Y={1}, W={2}, H={3}" -f $bounds.X, $bounds.Y, $bounds.Width, $bounds.Height) | |
} else { | |
Write-Host "Could not find the application window within timeout." | |
} | |
} | |
$cred = Get-StoredCredential -Target "XIBO2" | |
# Handle 3 or more monitors | |
if ($monitors.Count -gt 2) { | |
# First instance (second monitor) under XIBO2 | |
Start-And-MoveWindow -appPath $appPath -bounds $monitors[1].Bounds -cred $cred -workingDir "C:\Windows\System32" | |
# Second instance (third monitor) as current user | |
Start-And-MoveWindow -appPath $appPath -bounds $monitors[2].Bounds | |
} | |
if ($monitors.Count -eq 2) { | |
# First instance (first monitor) under XIBO2 | |
Start-And-MoveWindow -appPath $appPath -bounds $monitors[0].Bounds -cred $cred -workingDir "C:\Windows\System32" | |
# Second instance (second monitor) as current user | |
Start-And-MoveWindow -appPath $appPath -bounds $monitors[1].Bounds | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment