Search code examples
vb.netpowercfg

Weird behavior of powercfg.exe when I execute it programatically


To programtically set display brightness I had two options :

  • Use PowerWriteACValueIndex and PowerWriteDCValueIndex API
  • Use PowerCfg.exe

Now, I tried both, and both gave me the same (weird) result. Here's the code I'm using :

                With psiInfo
                    .FileName = "powercfg"
                    .UseShellExecute = True
                    .WindowStyle = ProcessWindowStyle.Hidden
                    .Arguments = "-setacvalueindex " & guidCurScheme.ToString() & " " & SUBGROUP_GUID.GUID_VIDEO_SUBGROUP & " " & SETTING_GUID.GUID_DISPBRIGHTNESS & " " & psValue.ValueAC
                End With
                pProc = Process.Start(psiInfo)

Where :

Public Const GUID_VIDEO_SUBGROUP As String = "7516b95f-f776-4464-8c53-06167f40cc99"
Public Const GUID_DISPBRIGHTNESS As String = "aded5e82-b909-4619-9949-f5d71dac0bcb"

Public Structure POWERSETTING
    Public ValueAC As String
    Public ValueDC As String
End Structure

Dim psValue As POWERSETTING

And guidCurScheme is the GUID of the active power scheme, as returned by PowerGetActiveScheme API function. I do the samething for DC part, with "-setdcvalueindex".

Now the weird behavior is as follow :

  1. If I call this code in a button click handler event, it will set these values, but not the "general" screen brightness slider (and for that matter, the display brightness). (somebody edits the pictures links inside the post please)
  2. If I the user clicks the button a second time, it will only then apply the setting.
  3. If i put the code in a loop for it to run twice when the user click the button, it will still behave as in (1)
  4. If I try to run the same command but manually from command-line, it will run work just fine.

This is totally unexpected, I don't know what I'm doing wrong. It gives the exact same result when I use the PowerWriteACValueIndex and PowerWriteDCValueIndex functions from Windows API.


Solution

  • maybe double-check the syntax of your argument by letting the app copy the string to clipboard. Sometimes just a tiny typo ruins it for me.

    Also i'd check if the application that gets called is the one from syswow or from system32 (that depends on how you compile your app) You can also check the exitcode or look at the error-output you get. The error-output can be captured like this:

    Dim so As System.IO.StreamReader
            Dim se As System.IO.StreamReader
            se = myproc.StandardError
            so = myproc.StandardOutput
            myproc.WaitForExit()
            MsgBox(so.ReadToEnd & vbcrlf & se.ReadToEnd)