Switching Primary Monitor Using Command Line (even on Vista with SLI enabled)

Discussion in 'Videocards - NVIDIA GeForce' started by ESPNSTI, Apr 6, 2008.

  1. ESPNSTI

    ESPNSTI New Member

    Messages:
    6
    Likes Received:
    0
    GPU:
    eVGA e-GeForce 8800GTS 640MB
    Ok, I'd figure I'd share this in case someone was as annoyed as I originally was by the lack of a simple functioning command line option to switch the primary monitor from my PC to my HDTV.
    I know there is an API in nvcpl.dll, and I was using that, but that doesn't work in Vista, so I switched to using UltraMon.
    However, now that I went SLI, I can't use that either.

    Basically what I was looking for was a way to switch my primary monitor to my HDTV (in the other room), so I can watch videos on there.
    Then when I'm done I need to switch back to my PC.
    Since I do that relatively often, I wanted to have a way of doing that without having to jump through all the hoops of manually changing it using the control panel.

    So what I did was to create a vbscript file that opens up the nVidia control panel and switches the primary monitor for me. (And it does some other stuff too).

    To use this, copy all the text in the "Code:" window below, put it in a text file and save it as SetVideoLocation.vbs (make sure it isn't saved as SetVideoLocation.vbs.txt).
    Then follow the instructions in the top section of the SetVideoLocation.vbs file itself.

    Just to be clear, the script is pretty crude and I've only ever tested it in my situation, so if something doesn't work for you, then that wouldn't be a surprise to me.

    SetVideoLocation.vbs:
    Code:
    '---------------------------------------------------------------------------------------------------
    ' SetVideoLocation.vbs
    '
    ' This (crude) script switches the primary monitor from the 'PC' monitor to the 'TV' monitor and 
    ' vice versa. It does this using either the nVidia control panel or using Ultramon.
    ' In addition, it can set SPDIF, FFDShow and Creative X-Fi settings based on the switch to 
    ' either 'PC' or 'TV'.
    '
    ' Usage:
    '   1) Put this script (and the optional SetVideoLocation_PC.reg and SetVideoLocation_TV.reg
    '      in any place you like.
    '   2) Edit the "Parms" section below and at the minimum change the 'monPCName' and 'monTVName'
    '      parameters. And then save the file (duh).
    '   3) Create two short cuts to this (SetVideoLocation.vbs) file.
    '      Edit one of the short cuts and add " PC" to the end of the "Target" field, 
    '      and edit the other one so that it has " TV" at the end of the "Target" field. 
    '      Bind each shortcut to a shortcut key for easy use.
    '   4) Optionally edit the SetVideoLocation_PC.reg and SetVideoLocation_TV.reg files to change
    '      settings to your liking.
    '      By default the reg files will:
    '        In MPC:
    '          - Enable (PC) or disable (TV) Dolby/DTS decoding in the internal filters.
    '          - Enable (TV) or disable (PC) SPDIF in the internal filters.
    '          - Set the audio renderer to SPDIF (TV) or default (PC).
    '          - Set the full screen res to 1920x1080 (TV) or default (PC).
    '        In ffdshow:
    '          - Set the active preset to TV (TV) or default (PC).
    '          
    '
    ' I've only ever tested this on my machine using:
    '   Vista 64 SP1
    '   nVidia Forceware 180.48
    '   UltraMon 3.0.3
    '   X-Fi Mode 1.7 build 22
    '   eVga 8800GTS 640mb (both in Sli mode and also with it disabled)
    '   LG L204WT PC Monitor
    '   Onkyo TX-SR875 HDMI receiver
    '
    ' I'm not responsible for any damage, or anything like that, use at your own risk.
    ' Don't count on me spending a lot of time on figuring out why it's not working on your machine.
    ' If it isn't working, you can always use Google to learn vbscript :)
    ' I'm not going to add any sort of new feature to this. I'm just too busy to do that sort of thing.
    '---------------------------------------------------------------------------------------------------
    
    
    
    REM Script Parameter One: 
    REM PC = set to at PC viewing
    REM TV = set to at TV viewing
    
    
    
    '---------------------------------------------------------------------------------------------------
    ' Parms
    '---------------------------------------------------------------------------------------------------
    
        '<SwitchUsingUltraMon> : 
        '     If 'True', will switch using UltraMon. In the past, UltraMon didn't appear to have a way 
        '               to switch monitors if SLI was enabled.
        '     If 'False', primary monitor will switch by bringing up and manipulating the 
        '               nVidia control panel. This will only function if you're using sli (enabled).
        '               Note that UltraMon will still be used if you specify a resolution to change to.
    SwitchUsingUltraMon=True
    
    If SwitchUsingUltraMon=False Then
          ' <monPCName> and <monTVName>: 
          '     Set to the first few characters of the name of the monitor for the PC and the TV as it 
          '     appears in the 'Set up multiple displays' page of the nVidia Control Panel.
      monPCName = "LG Electronics L204WT"                                                              '<-- EDIT THIS
      monTVName = "TX-SR875"                                                                           '<-- EDIT THIS
    Else      
          ' <monPCName> and <monTVName>:
          '     Set to the name of the monitor for the PC and the TV as it appears in 
          '     the Windows Device Manager in 'Monitors'. 
          '     (You only need to set this if SwitchUsingUltraMon=True)
          '     If the names of the monitors are identical, then there is a way around by editing the 
          '     Device Name in the registry, but I won't go in to that here.
      monPCName = "LG L204WT"
      monTVName = "Onkyo TX-SR875"
    End If
    
        '<monPCRes> and <monTVRes> :
        '     Uses ultramon to switch resolutions if specified.
    monPCRes  = ""  ' Example: "1680x1050x32"
    monTVRes  = ""  ' Example: "1768x992x32"
    
        '<AllowSetMPCandFFDShowSettings> : 
        '     If 'True', will do such things as set SPDIF settings in Media Player Classic,
        '     and set a 'TV' profile in FFDShow. You will need to have SetVideoLocation_PC.reg
        '     and SetVideoLocation_TV.reg for this.
    AllowSetMPCandFFDShowSettings=False
    
        '<AllowSetCreativeXFIMode> : 
        '     If 'True' will use the XFMC utility to set the Creative X-Fi mode 
        '     to 'ENTERTAINMENT' when switching to TV or 'GAME' when switching to PC
        '<CreativeXFIPath> :
        '     Set to the path of the XFMC utility. (Path must end in a backslash.)
    AllowSetCreativeXFIMode=False
    CreativeXFIPath = "C:\Drivers\Creative\XFMC\"
    
        '<gLogEnabled> : 
        '     Logging enabled if 'True', disabled if 'False'.
        '<LogFileName>'
        '     Name of the log file.
    gLogEnabled = True
    LogFileName = "SetVideoLocation.log"
    
    
        'Below are times (in milliseconds) that the script waits at certain points for things to load
        'So if the script isn't working for you, try increasing these numbers.
        'These are only used when SwitchUsingUltraMon=False.
    WaitTime_UntilControlPanelActive=10000
    WaitTime_AfterControlPanelActive=500
    WaitTime_AfterMonitorSelectionMade=500
    WaitTime_AfterApplyMonitorSelection=500
    WaitTime_UntilApplyChanges1Active=5000
    WaitTime_AfterApplyChanges1Active=500
    WaitTime_AfterApplyChanges1Accepted=500
    WaitTime_UntilApplyChanges2Active=10000  ' The actual monitor switching happens during this time.
    WaitTime_AfterApplyChanges2Active=500
    WaitTime_AfterApplyChanges2Accepted=500
    
    '---------------------------------------------------------------------------------------------------
    
    If WScript.Arguments.Count = 0 Then
      Config = "PC"
    Else
      Config = WScript.Arguments(0)
    End If
    
    '---------------------------------------------------------------------------------------------------
    ' Main Begin
    '---------------------------------------------------------------------------------------------------
    Set gobjLog = LogFileOpen(LogFileName)
    
    Set gobjShell = CreateObject("WScript.Shell")
    
    
      Log("Set location to: " & Config & "  SwitchUsingUltraMon: " & SwitchUsingUltraMon _
          & "  monPCName: " & monPCName & "  monTVName: " & monTVName _
          & "  monPCRes: " & monPCRes & "  monTVRes: " & monTVRes)
    
      REM - Switch primary monitor
    
    
      If SwitchUsingUltraMon=True Then
        SwitchMonitorUltraMon(Config)
      Else  
        SwitchMonitorNVidiaControlPanel(Config)
      End If
    
    
      REM - Set Media Player Classic & FFDShow settings
      If AllowSetMPCandFFDShowSettings=True Then SetMPCAndFFDShowSettings(Config)
    
    
      If AllowSetCreativeXFIMode=True Then
        REM - Set the Creative mode
        If Config = "PC" Then
          SetCreativeXFIMode "GAME", CreativeXFIPath
        End If
        If Config = "TV" Then
          SetCreativeXFIMode "ENTERTAINMENT", CreativeXFIPath
        End If
      End If
    
    
    Set gobjShell = Nothing
    
    Log("Done")
    
    If gLogEnabled = True Then LogFileClose()
    '---------------------------------------------------------------------------------------------------
    ' Main End
    '---------------------------------------------------------------------------------------------------
    
    
    
    '---------------------------------------------------------------------------------------------------
    'Switches monitors using the nVidia control panel.
    '
    'This causes the nVidia control panel to come up, but it should work even with SLI enabled.
    '---------------------------------------------------------------------------------------------------
    Sub SwitchMonitorNVidiaControlPanel(aConfig)
    
        'NVidia Control Panel UI Page Class GUIDs (at least for 174.74)
    
        '- 3D Settings (normally not reachable from UI?)
        '    CLASS_3DSettings = "{3156EC84-29BD-4EAA-AE0A-817ED606FA99}"
    
        '  - Adjust image settings with preview
        '      CLASS_AppSettingsBasic = "{9B5EC720-9A44-4811-8B9F-24BD53F2050D}"
        '      CLASS_AppSettingsAdv = "{EBF88566-91F5-4045-B7CA-426E59DDE635}"
        '  - Manage 3D settings
        '      CLASS_Manage3DSettings = "{BBB7D605-8639-49D0-849E-32C4A5DBB9C3}"
        '  - Set SLI configuration
              CLASS_SliBasic = "{DE0549BD-F34D-4748-AD94-0F2F22749F4F}"
    
    
        '- Display (normally not reachable from UI?)
        '    CLASS_Display = "{73BCA54E-6AEB-4597-8F27-E1284FF12722}"
    
      
        '  - Change resolution
        '      CLASS_ChangeRes = "{382AF4B5-7F74-4040-B1FE-A861AF2D7402}"
              CLASS_ChangeResAdv = "{5F9C8FEF-4352-43C0-AF63-88FF124C34F7}"
        '  - Change flat panel scaling
        '      CLASS_ScreenTimingDVI = "{51840041-B26F-4843-B358-22ABB067396C}"
        '  - Adjust desktop color settings
        '      CLASS_ColorSettings = "{AB866564-F241-49B2-B0A7-D6C537340728}"
        '      CLASS_ColorSettingsAdv = "{B53EBC0C-2251-4AE2-9818-FD6AAF843***}"
        '  - Rotate display
        '      CLASS_RotateDisplay = "{6017A978-93AD-4F2F-9E2D-07CF8C8DEBC4}"
        '  - Manage custom resolutions
        '      CLASS_CustomRez = "{49F585C0-CE12-4306-9100-B6A28857B10B}"
        '  - Set up multiple displays
        '      CLASS_NviewBasic = "{9090879C-1A43-43C0-B7A6-975A8ED5E0D6}"
        '      CLASS_NView = "{7945F814-7BFB-4506-A113-2BD66CDC713A}"
    
    
        '- Performance (normally not reachable from UI?)
        '    CLASS_MainPerfServer = "{FA7602F2-CC0D-4137-9831-D4606E9A2B52}"
    
        '  - Device settings
        '      CLASS_ClockCtrlPage = "{B0FB6FFE-42C5-4942-93ED-3467893F978D}"
        '  - Dynamic BIOS access
        '      CLASS_AdjustBiosSettingPage = "{3786D5BA-5038-4135-8878-91CA0C92393C}"
        '  - View system information
        '      CLASS_SystemInfoPage = "{31A73CC4-962E-4D15-90EC-7201688460D6}"
        '  - Profile policies
        '      CLASS_AdjustCustomRulesPage = "{72ADDC05-0B40-4B60-846A-674E4EDD151F}"
    
    
        '- System Update (normally not reachable from UI?)
        '    CLASS_MainUpdateServer = "{20486BE1-C1D1-4838-98FD-E9AF679AC701}"
    
        '  - Update your System BIOS
        '      CLASS_UpdateSBIOS = "{224CD9A4-DE80-4D9A-ACDD-E24204A1F039}"
        '  - Update your System Drivers
        '      CLASS_UpdateDrivers = "{04110D75-E5A4-4526-BE98-1108CA89EC44}"
    
        '- Video & Television (normally not reachable from UI?)
        '    CLASS_VideoTelevision = "{3E500C0C-5D15-4610-8095-7CEBD4C43F24}"
    
    
        '  - Adjust video color settings
        '      CLASS_VideoColorSettings = "{055A7699-EAFF-47DF-8E55-41F4C0612BF3}"
        '  - Adjust video image settings
        '      CLASS_VideoImageSettings = "{EF884939-F1EA-4EFB-B676-D2F802177C5F}"
        '  - Change the signal or HD format
        '      CLASS_TVFormat = "{89B53798-9A96-4758-9571-93B72CAA5381}"
    
    
      Log("  Open nVidia Control 'Set SLI and PhysX configuration' page")
      gobjShell.Run("nvcplui.exe /page:" & CLASS_SliBasic)
      ControlPanelActive = WaitForAppActivate("NVIDIA Control Panel", WaitTime_UntilControlPanelActive)
      KeepGoing = ControlPanelActive
    
      If KeepGoing = True Then 
        WScript.Sleep(WaitTime_AfterControlPanelActive)
    
        Log("    Changing Monitor Selection")
        gobjShell.SendKeys("%c")
        IF aConfig = "TV" Then
          monNew = monTVName
          monOld = monPCName
        Else
          monNew = monPCName
          monOld = monTVName
        End If
    
        REM Figure out the least keystrokes to uniquely select the monitor
        mon=""
        i=0
        Do
          i=i+1
          mon=mon+Mid(monNew,i,1)
        Loop Until i>Len(monOld) Or i>Len(monNew) Or Mid(monNew,i,1)<>Mid(monOld,i,1)
    
        gobjShell.SendKeys(mon)
        WScript.Sleep(WaitTime_AfterMonitorSelectionMade)
    
        Log("    Trigger Apply changes by switching to another nVidia Control Panel Page")
        gobjShell.Run("nvcplui.exe /page:" & CLASS_ChangeResAdv)
        KeepGoing = WaitForAppActivate("Apply Changes", WaitTime_UntilApplyChanges1Active)
    
      End If
    
      IF KeepGoing = True Then
        WScript.Sleep(WaitTime_AfterApplyChanges1Active)
    
        Log("    Applying Changes")
        gobjShell.SendKeys("%Y")
        WScript.Sleep(WaitTime_AfterApplyChanges1Accepted)
    
        KeepGoing = WaitForAppActivate("Apply Changes", WaitTime_UntilApplyChanges2Active)
      
      End If
    
      IF KeepGoing = True Then
        WScript.Sleep(WaitTime_AfterApplyChanges2Active)
    
        Log("    Accepting Changes")
        gobjShell.SendKeys("%Y")
        WScript.Sleep(WaitTime_AfterApplyChanges2Accepted)
    
      End If
    
      If ControlPanelActive Then
        Log("  Closing nVidia Control Panel")
        gobjShell.SendKeys("%{F4}")
      End If
    
      If KeepGoing = True Then
    
        IF aConfig = "TV" Then
          monRes = monTVRes
        Else
          monRes = monPCRes
        End If 
    
        If monRes<>"" Then
          SwitchResoltionUltraMon monRes, aConfig
        End If
    
      End If
    
    End Sub
    
    
    '---------------------------------------------------------------------------------------------------
    'Switches monitors using ultramon. ( http://realtimesoft.com/ultramon/ )
    '
    'This does not cause the nVidia control panel to come up, 
    'but in the past it didn't work with SLI enabled.
    '---------------------------------------------------------------------------------------------------
    Sub SwitchMonitorUltraMon(aConfig)
    
      Dim sys, mon1, mon2
      Set sys = CreateObject("UltraMon.System")
      Set monPC = sys.Monitors("1")
      Set monTV = sys.Monitors("2")
    
      Log("  Monitor 1: " & monPC.Name)
      Log("  Monitor 2: " & monTV.Name)
    
      REM - Ensure we have the right monitor
      If monTV.Name = monPCName Or monPC.Name = monTVName Then
        Log("Swapping PC and TV")
        Set monSwap = monTV
        Set monTV = monPC
        Set monPC = monSwap
        Set monSwap = Nothing
      End If
    
      Log("State before the switch:")
      Log("  PC Monitor (" & monPC.Name & ") Enabled: " & monPC.Enabled & " Primary: " & monPC.Primary)
      Log("  TV Monitor (" & monTV.Name & ") Enabled: " & monTV.Enabled & " Primary: " & monTV.Primary)
    
      IF aConfig = "PC" And monPC.Name <> "" Then
        
    Log("Set Changes for switch to PC")
    
        monPC.Enabled = -1
        monTV.Enabled = 0
      
        monTV.Primary = 0
        monPC.Primary = -1
      End If
      IF aConfig = "TV" And monTV.Name <> "" Then
        
    Log("Set Changes for switch to TV")
    
        monTV.Enabled = -1
        monPC.Enabled = 0
    
        monPC.Primary = 0
        monTV.Primary = -1
    
      End If
    
      sys.ApplyMonitorChanges
    
      Log("State after the switch:")
      Log("  PC Monitor (" & monPC.Name & ") Enabled: " & monPC.Enabled & " Primary: " & monPC.Primary)
      Log("  TV Monitor (" & monTV.Name & ") Enabled: " & monTV.Enabled & " Primary: " & monTV.Primary)
    
      Set MonTV = Nothing
      Set MonPC = Nothing
      Set sys = Nothing
    
      IF aConfig = "TV" Then
        monRes = monTVRes
      Else
        monRes = monPCRes
      End If 
    
      If monRes<>"" Then
        SwitchResoltionUltraMon monRes, aConfig
      End If
    
    End Sub
    
    '---------------------------------------------------------------------------------------------------
    'Switches resolutions using UltraMon. ( http://realtimesoft.com/ultramon/ )
    '
    '---------------------------------------------------------------------------------------------------
    Sub SwitchResoltionUltraMon(aResolution, aConfig)
    
      Log("  Changing resolution to: " & aResolution)
    
      Set sys = CreateObject("UltraMon.System")
      IF aConfig = "TV" Then
        Set mon = sys.Monitors("2")
      ELSE
        Set mon = sys.Monitors("1")
      END IF
    
      resArray = Split(aResolution, "x")
    
      mon.Width = resArray(0)
      mon.Height = resArray(1)
      If UBound(resArray)>=2 Then
        mon.Colordepth = resArray(2)
      End If
    
      sys.ApplyMonitorChanges
    
      Set Mon = Nothing
      Set sys = Nothing
    
    End Sub
    
    
    '---------------------------------------------------------------------------------------------------
    'Sets Media Player Classic and FFDShow settings
    '
    'All it does is enter a file name SetVideoLocation_PC.reg or SetVideoLocation_TV.reg in to the
    'registry, so theoretically you could mod the .reg files to do whatever you need it to with
    'other programs as well.
    '---------------------------------------------------------------------------------------------------
    Sub SetMPCAndFFDShowSettings(aConfig)
    
      Log("Media Player Classic & FFDShow - Activate the settings")
    
      REM - Registry - Media Player Classic & FFDShow - Activate the settings
      gobjShell.Run "%WINDIR%\regedit.exe /s SetVideoLocation_" & aConfig & ".reg", 8, true
    
    End Sub
    
    '---------------------------------------------------------------------------------------------------
    'Sets the Creative X-Fi mode
    '
    'Calls the XFiMode program. ( http://www.spectra9.com/xfmc/xfmc.html )
    '---------------------------------------------------------------------------------------------------
    Sub SetCreativeXFIMode(aCreativeMode, aXFMCPath)
    
      Log("Creative - Set X-Fi mode to: " & aCreativeMode)
    
      REM - Creative - Activate the mode settings
      gobjShell.Run aXFMCPath & "XFiMode.Exe /" & aCreativeMode, 8, true
    
    End Sub
    
    
    
    
    '---------------------------------------------------------------------------------------------------
    '---------------------------------------------------------------------------------------------------
    Function LogFileOpen(aLogFileName)
    
      If gLogEnabled = True Then 
          Set objFSO = CreateObject("scripting.filesystemobject")
        If objFSO.FileExists(logFileName) Then
          Set objLog = objFSO.OpenTextFile(aLogFileName, 8, True)
        Else
          Set objLog = objFSO.CreateTextFile(aLogFileName, True)
        End If
        Set objFSO = Nothing
    
        objLog.writeline ""
      Else
        Set objLog = Nothing
      End If
      Set LogFileOpen = objLog
    
    End Function
    
    
    '---------------------------------------------------------------------------------------------------
    Sub Log(aLogText)
    
      If gLogEnabled = True Then 
        gobjLog.writeline Now & "  " & aLogText
      End If
    
    End Sub
    
    
    '---------------------------------------------------------------------------------------------------
    Sub LogFileClose
    
      If gLogEnabled = True Then 
        gobjLog.Close
    
        Set gobjLog = Nothing
      End If
    
    End Sub
    
    
    '---------------------------------------------------------------------------------------------------
    Function WaitForAppActivate(aCaption, aTimeOut)
      
      maxLoop = aTimeOut / 100
    
      Do
        ret = gobjShell.AppActivate(aCaption)
        If ret = False Then
          WScript.Sleep(100)
          maxLoop = maxLoop - 1
        End If
      Loop Until ret = True Or maxLoop = 0
    
      If Ret = False Then
        Log("Failed to activate: " & aCaption & " in " & aTimeOut & " milliseconds.")
      End If
    
      WaitForAppActivate=ret
    
    End Function
    SetVideoLocation_TV.reg:
    Code:
    Windows Registry Editor Version 5.00
    
    [HKEY_CURRENT_USER\Software\Gabest\Filters\MPEG Audio Decoder]
    "Ac3SpeakerConfig"=dword:ffffffe9
    "DtsSpeakerConfig"=dword:ffffff77
    "AacSpeakerConfig"=dword:00000000
    
    [HKEY_CURRENT_USER\Software\Gabest\Media Player Classic\Settings]
    "FullscreenRes"=hex:01,80,07,00,00,38,04,00,00,20,00,00,00,3C,00,00,00
    "AudioRendererType"="@device:cm:{E0F158E1-CB04-11D0-BD4E-00A0C911CE86}\\SPDIF Out (Creative SB X-Fi)"
    
    [HKEY_CURRENT_USER\Software\GNU\ffdshow]
    "activePreset"="TV"
    SetVideoLocation_PC.reg:
    Code:
    Windows Registry Editor Version 5.00
    
    [HKEY_CURRENT_USER\Software\Gabest\Filters\MPEG Audio Decoder]
    "Ac3SpeakerConfig"=dword:00000017
    "DtsSpeakerConfig"=dword:00000089
    "AacSpeakerConfig"=dword:00000000
    
    [HKEY_CURRENT_USER\Software\Gabest\Media Player Classic\Settings]
    "FullscreenRes"=hex:00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00
    "AudioRendererType"=""
    
    [HKEY_CURRENT_USER\Software\GNU\ffdshow]
    "activePreset"="default"
    
     
    Last edited: Dec 20, 2008

Share This Page