Search code examples
batch-filecmdwindows-installernsisresolution

NSIS - Refresh rate of a monitor to a variable from a CMD command


This is how I get the refresh rate of my primary monitor, by typing this command in CMD:

wmic PATH Win32_videocontroller get currentrefreshrate

Result:

CurrentRefreshRate
144
75

The second line is the refresh rate of my primary monitor. I would like to have this number assigned to a variable called $refreshrate. How to achieve this?


Solution

  • You don't have to rely on external tools, you can ask the system directly:

    For the entire screen:

    !include LogicLib.nsh
    Section
    !define /IfNDef VREFRESH 116
    System::Call USER32::GetDC(p0)p.r0
    System::Call GDI32::GetDeviceCaps(pr0,i${VREFRESH})i.r1
    System::Call USER32::ReleaseDC(p0,pr0)
    ${If} $1 < 5
        StrCpy $1 "Invalid"
    ${EndIf}
    DetailPrint "Refresh rate=$1"
    SectionEnd
    

    Current display where the application (thread) is:

    !include LogicLib.nsh
    Section
    !define /IfNDef ENUM_CURRENT_SETTINGS -1
    !define /IfNDef DM_DISPLAYFREQUENCY 0x00400000
    
    System::Call 'USER32::GetClientRect(p0,@r1)' ; Lazy allocation of a DEVMODE
    System::Call '*$1(&i68,&i2 68)'
    System::Call 'USER32::EnumDisplaySettingsW(p0, i${ENUM_CURRENT_SETTINGS}, pr1)i.r0'
    System::Call '*$1(&i72,i.r2)'
    ${If} $0 <> 0
    ${AndIf} $2 & ${DM_DISPLAYFREQUENCY}
        System::Call '*$1(&i184,i.r3)'
        DetailPrint "Current display=$3"
    ${EndIf}
    SectionEnd
    

    Primary adapter:

    !include LogicLib.nsh
    Section
    !define /IfNDef ENUM_CURRENT_SETTINGS -1
    !define /IfNDef DM_DISPLAYFREQUENCY 0x00400000
    !define /IfNDef DISPLAY_DEVICE_PRIMARY_DEVICE 4
    System::Call 'USER32::GetClientRect(p0,@r1)' ; Lazy allocation of a DISPLAY_DEVICE 
    StrCpy $4 0
    loop:
    System::Call '*$1(i840)'
    System::Call 'USER32::EnumDisplayDevicesW(p0, ir4, pr1, i0)i.r0'
    IntOp $4 $4 + 1
    ${If} $0 <> 0
        System::Call '*$1(i,&w32.r2,&w128,i.r3)'
        ${If} $3 & ${DISPLAY_DEVICE_PRIMARY_DEVICE}
            System::Call '*$1(&i68,&i2 68)' ; DEVMODE
            System::Call 'USER32::EnumDisplaySettingsW(wr2, i${ENUM_CURRENT_SETTINGS}, pr1)i.r0'
            System::Call '*$1(&i72,i.r2)'
            ${If} $0 <> 0
            ${AndIf} $2 & ${DM_DISPLAYFREQUENCY}
                System::Call '*$1(&i184,i.r3)'
                DetailPrint "Primary adapter=$3"
            ${EndIf}
        ${Else}
            Goto loop
        ${EndIf}
    ${EndIf}
    SectionEnd
    

    If you really really want to use WMI:

    !include "StrFunc.nsh"  
    ${Using:StrFunc} StrRep 
    !include LogicLib.nsh
    Section
    nsExec::ExecToStack '"wmic.exe" PATH Win32_videocontroller get  currentrefreshrate /all'
    Pop $0
    Pop $1
    ${StrRep} $1 $1 "currentrefreshrate" ""
    loop:
        StrCpy $2 $1 1
        ${If} $2 == "$\r"
        ${OrIf} $2 == "$\n"
        ${OrIf} $2 == " "
            StrCpy $1 $1 "" 1
            Goto loop
        ${EndIf}
    IntOp $2 $1 + 0 ; First number
    ${If} $0 = 0
        DetailPrint WMIC=$2
    ${EndIf}
    SectionEnd