I'm interested in developing an AHK
display brightness meter. I've been using the
console app that's part of Samuel Lai's
Display Brightness Vista Gadget. However, I get errors when the console app is triggered when the display is unavailable (during resume from sleep). I was wondering if it would be better to recode the C# code straight into the AHK script, but I don't know anything about C# or querying WMI. I really am only interested 2 parts: GetBrightness and GetBrightnessLevels. (I'm also interested in avoiding crashes that affect DisplayBrightnessConsole.exe-- maybe some clever task scheduling is required?) I was thinking the problem might be related to having it be a 32-bit program on a 64-bit OS. I was going to try to incorporate the GetBrightness and GetBrightnessLevels into a new AHK script and compile it with AutoHotkey_L x64.
Code:
using System;
using System.Collections.Generic;
using System.Text;
namespace DisplayBrightnessConsole
{
class Program
{
static void Main(string[] args)
{
if (args.Length == 0)
{
Console.WriteLine(GetBrightness());
}
else if (args[0] == "-getlevels")
{
byte[] BrightnessLevels = GetBrightnessLevels();
foreach (byte b in BrightnessLevels)
{
Console.WriteLine(b.ToString());
}
}
else
{
//parse switch value
byte targetBrightness = byte.Parse(args[0]);
SetBrightness(targetBrightness);
Console.WriteLine("0"); //success value
}
}
static byte GetBrightness()
{
//define scope (namespace)
System.Management.ManagementScope s = new System.Management.ManagementScope("root\\WMI");
//define query
System.Management.SelectQuery q = new System.Management.SelectQuery("WmiMonitorBrightness");
//output current brightness
System.Management.ManagementObjectSearcher mos = new System.Management.ManagementObjectSearcher(s, q);
System.Management.ManagementObjectCollection moc = mos.Get();
//store result
byte curBrightness = 0;
foreach (System.Management.ManagementObject o in moc)
{
curBrightness = (byte)o.GetPropertyValue("CurrentBrightness");
break; //only work on the first object
}
moc.Dispose();
mos.Dispose();
return curBrightness;
}
static byte[] GetBrightnessLevels()
{
//define scope (namespace)
System.Management.ManagementScope s = new System.Management.ManagementScope("root\\WMI");
//define query
System.Management.SelectQuery q = new System.Management.SelectQuery("WmiMonitorBrightness");
//output current brightness
System.Management.ManagementObjectSearcher mos = new System.Management.ManagementObjectSearcher(s, q);
System.Management.ManagementObjectCollection moc = mos.Get();
//store result
byte[] BrightnessLevels = new byte[0];
foreach (System.Management.ManagementObject o in moc)
{
BrightnessLevels = (byte[])o.GetPropertyValue("Level");
break; //only work on the first object
}
moc.Dispose();
mos.Dispose();
return BrightnessLevels;
}
static void SetBrightness(byte targetBrightness)
{
//define scope (namespace)
System.Management.ManagementScope s = new System.Management.ManagementScope("root\\WMI");
//define query
System.Management.SelectQuery q = new System.Management.SelectQuery("WmiMonitorBrightnessMethods");
//output current brightness
System.Management.ManagementObjectSearcher mos = new System.Management.ManagementObjectSearcher(s, q);
System.Management.ManagementObjectCollection moc = mos.Get();
foreach (System.Management.ManagementObject o in moc)
{
o.InvokeMethod("WmiSetBrightness", new Object[] { UInt32.MaxValue, targetBrightness }); //note the reversed order - won't work otherwise!
break; //only work on the first object
}
moc.Dispose();
mos.Dispose();
}
}
}
Here is my AHK code as it is now. As you can see, I'm trying to reduce the frequency of crashes brought on by DisplayBrightnessConsole.exe when the display isn't ready.
Code:
#NoEnv ; Recommended for performance and compatibility with future AutoHotkey releases.
SendMode Input ; Recommended for new scripts due to its superior speed and reliability.
SetWorkingDir %A_ScriptDir% ; Ensures a consistent starting directory.
#Persistent
#SingleInstance Force
#Include StdoutToVar.ahk
width := A_ScreenWidth
test := StdoutToVar_CreateProcess("DisplayBrightnessConsole.exe")
StringReplace, test, test, `r`n
If test not between 0 and 100
{
MsgBox, Display Brightness is not compatible with your system. It is only for laptops with integrated displays running Windows Vista or Windows 7 (with display brightness programmable via WMI).
ExitApp
}
Menu, Tray, DeleteAll
Menu, Tray, Add, Windows Mobility Center (Win-X), MblCtr
Menu, Tray, Default, Windows Mobility Center (Win-X)
Menu, Tray, Standard
abl := StdoutToVar_CreateProcess("DisplayBrightnessConsole.exe -getlevels")
StringReplace, abl, abl, `r`n, `n, UseErrorLevel
StringTrimRight, abl, abl, 1
Sort, abl, N R Z
Loop, default\*.ico
icons .= A_LoopFileName . "`n"
Sort, icons, N R Z
StringTrimRight, icons, icons, 1
StringSplit, icon, icons, `n
Loop, Parse, abl, `n
FileCopy, % "default\" . icon%A_Index%, %A_LoopField%.ico, 1
SetTimer, GetCurrentLevel, 500 ; Will this value determine if DisplayBrightnessConsole.exe crashes? Was 500 previously.
SetTimer, CloseError
GetCurrentLevel:
IfNotEqual, A_ScreenWidth, %width%
{
Sleep 2000
Goto, GetCurrentLevel
}
cbl := StdoutToVar_CreateProcess("DisplayBrightnessConsole.exe")
StringReplace, cbl, cbl, `r`n
IfNotExist, %cbl%.ico
{
Sleep 800
Goto, GetCurrentLevel
}
Menu, Tray, Icon, %cbl%.ico
Menu, Tray, Tip, Display Brightness: %cbl%`%
Return
CloseError:
WinWait, DisplayBrightnessConsole
WinClose
Return
MblCtr:
Send, #x
Return