A PowerShell script to switch monitor input sources (HDMI/DisplayPort) using DDC/CI commands.
This script allows you to programmatically switch all connected monitors between different input sources, functioning as a software-based KVM switch. It uses DDC/CI (Display Data Channel Command Interface) to communicate with monitors and change their input sources.
This is a software-free alternative to NirSoft's ControlMyMonitor command-line tool, which offers similar functionality. While ControlMyMonitor is an excellent utility, it may be blocked by corporate software use policies or security software. This PowerShell script provides the same core monitor input switching capabilities without requiring any external executables, making it ideal for corporate environments with strict software restrictions.
This project is designed to enable a complete software-based KVM (Keyboard, Video, Mouse) solution by combining monitor switching with USB peripheral switching:
Monitor Switching (This Repository)
- Uses DDC/CI commands to switch monitor input sources
- Programmatically controls which computer your monitors display
- No physical monitor button pressing required
USB Peripheral Switching (USBPiSwitcher)
- Integrates with a Raspberry Pi Zero HTTP API to control a USB switch
- Switches keyboard, mouse, and other USB peripherals between computers
- Controlled via simple HTTP requests to the Pi Zero
Combined Workflow: When you want to switch between computers, a single command can:
- Switch all monitor inputs to the target computer (using this script)
- Switch USB peripherals to the target computer (via Pi Zero API call)
This creates a seamless, software-controlled KVM experience without expensive KVM hardware, perfect for multi-PC setups where you want to share monitors and peripherals between work and personal computers, or between desktop and laptop systems.
If you find this project useful and it's helped you automate your monitor switching, please consider supporting it! Your support helps maintain and improve this project.
Support this project:
Other ways to help:
- ⭐ Star this repository - It helps others discover the project
- 🐛 Report issues - Help improve the project by reporting bugs
- 🔧 Contribute - Submit pull requests with improvements or new features
- 📢 Share - Tell others who might find this useful
Every bit of support is appreciated and motivates continued development!
The script uses Windows-specific APIs (dxva2.dll and kernel32.dll) and .NET Windows Forms to interact with monitors.
For macOS and Linux users: Similar DDC/CI functionality is available through native command-line tools. See the Cross-Platform Alternatives section below.
- Toggle Mode: Automatically switches between HDMI1 and DisplayPort
- Direct Input Selection: Explicitly select HDMI or DisplayPort
- Monitor Discovery: Scans and lists all connected monitors
- DDC/CI Verification: Tests which monitors support DDC/CI commands
- Input Verification: Confirms successful input switching
- Detailed Logging: Provides comprehensive feedback during operation
- Windows operating system
- Monitors must support DDC/CI
- DDC/CI must be enabled in each monitor's OSD (On-Screen Display) settings menu
- PowerShell 5.1 or later
.\SwitchMonitors.ps1or
.\SwitchMonitors.ps1 -Input ToggleThis will automatically detect the current input on the first monitor and switch all monitors to the opposite input.
Switch to HDMI:
.\SwitchMonitors.ps1 -Input HDMISwitch to DisplayPort:
.\SwitchMonitors.ps1 -Input DP.\SwitchMonitors.ps1 -Input ListThis displays all connected monitors, their DDC/CI status, and current input values without making any changes.
- Input (Optional): Specifies the switching mode
Toggle(Default): Switches between HDMI1 and DisplayPort automaticallyHDMI: Switches all monitors to HDMI1 (VCP value: 17)DP: Switches all monitors to DisplayPort (VCP value: 19)List: Lists all monitors and their current status without switching
- Uses Windows APIs to enumerate all connected displays
- Opens monitor handles via DDC/CI interface
- Reads current VCP (Virtual Control Panel) feature 0x60 (input source)
- Sends SetVCPFeature commands to change input sources
- Verifies the switch was successful
The script uses VCP code 0x60 for input source control. Common values:
1: VGA13: DVI115: DisplayPort116: DisplayPort217: HDMI118: HDMI219: HDMI3 or DisplayPort (monitor-dependent)
If you see this error:
-
Enable DDC/CI in each monitor's OSD settings menu
- Access your monitor's physical menu buttons
- Look for DDC/CI or DDC settings (often in System or Advanced settings)
- Enable the option
-
Run as Administrator - Some systems may require elevated privileges
# Right-click PowerShell and select "Run as Administrator" .\SwitchMonitors.ps1 -
Restart your computer after enabling DDC/CI on your monitors
-
Check cable compatibility - Some cables may not support DDC/CI properly
If a monitor is detected but DDC/CI doesn't work:
- Verify DDC/CI is enabled in that monitor's settings
- Try a different cable (some low-quality cables may not support DDC/CI)
- Some monitors have buggy DDC/CI implementations; check for firmware updates
If you see a warning that the monitor is at a different value than expected:
- The monitor may still be in the process of switching (it can take a second or two)
- Run the script with
-Input Listafter a few seconds to verify the final state
- Uses P/Invoke to call Windows DDC/CI APIs
- Leverages
System.Windows.Forms.Screenfor monitor enumeration - VCP feature code 0x60 controls input source selection
- Implements proper handle management and cleanup
While this PowerShell script is Windows-only, similar DDC/CI functionality is available on other operating systems using command-line tools:
ddcutil - The standard Linux tool for DDC/CI control:
# Install
sudo apt install ddcutil # Debian/Ubuntu
sudo dnf install ddcutil # Fedora
sudo pacman -S ddcutil # Arch
# List monitors
ddcutil detect
# Get current input source (VCP code 0x60)
ddcutil getvcp 60
# Set input to HDMI1 (value 17)
ddcutil setvcp 60 17
# Set input to DisplayPort (value 19)
ddcutil setvcp 60 19Example toggle script for Linux:
#!/bin/bash
current=$(ddcutil getvcp 60 --terse | cut -d' ' -f4)
if [ "$current" == "17" ]; then
ddcutil setvcp 60 19 # Switch to DP
else
ddcutil setvcp 60 17 # Switch to HDMI
fiddcctl or m1ddc (for Apple Silicon):
# Install via Homebrew
brew install ddcctl
# Or for Apple Silicon Macs
brew install m1ddc
# List monitors
ddcctl -d 1
# Set input (syntax varies by tool)
ddcctl -d 1 -i 17 # HDMI1
ddcctl -d 1 -i 19 # DisplayPort- DDC/CI must be enabled in your monitor's OSD settings on all platforms
- The VCP codes are standardized (0x60 for input source, values 17/19 for HDMI/DP)
- Not all monitors support DDC/CI; check your monitor's documentation
- Some cables may not support DDC/CI properly; use high-quality cables
