I'm getting a REALLY annoying DisconectContext exception. I know my computer supports the WMI function, because someone else's application that does the same thing works.
Basically, this is a program that sets the brightness of the screen when Fn+Up or Fn+Down is pressed.
All the code runs in the same thread, and the program is WinForms, but I compile it as a console application so I can see the debug messages. I have tried making it Windows Application, but it doesn't fix the issue, so I don't think it's the console.
The exception occurs in SetBrightness(int) at the comment...
HiddenForm.cs:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace ComputerControl
{
public partial class HiddenForm : Form
{
public HiddenForm()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
WindowState = FormWindowState.Minimized;
Utils.SetHook();
if (Utils._hook.ToInt32() <= 0)
{
MessageBox.Show("The application failed to hook the keyboard and will now exit.", "Application Initialization Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
Application.Exit();
}
bool supports = Utils.LoadBrightnessLevels();
if (!supports)
{
MessageBox.Show("The computer does not support WMI. The application will now exit.", "Application Initialization Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
Application.Exit();
}
}
}
}
Utils.cs:
using System;
using System.Diagnostics;
using System.Management;
using System.Runtime.InteropServices;
using System.Threading;
namespace ComputerControl
{
public class Utils
{
public static int index;
static byte[] supportedBrightness;
public static void IncrementBrightness()
{
if (index == supportedBrightness.Length - 1)
return;
SetBrightness(++index);
}
public static void DecrementBrightness()
{
if (index == 0)
return;
SetBrightness(--index);
}
public static void SetBrightness(int index)
{
ManagementScope ms = new ManagementScope("root\\WMI");
SelectQuery sq = new SelectQuery("WmiMonitorBrightnessMethods");
ManagementObjectSearcher mos = new ManagementObjectSearcher(ms, sq);
ManagementObjectCollection moc = mos.Get(); // Context <id> is disconnected. No proxy will be used to service the request on the COM component. This may cause corruption or data loss. To avoid this problem, please ensure that all contexts/apartments stay alive until the application is completely done with the RuntimeCallableWrappers that represent COM components that live inside them.
foreach (ManagementObject mo in moc)
{
mo.InvokeMethod("WmiSetBrightness", new object[] { 60, supportedBrightness[index] });
break;
}
moc.Dispose();
mos.Dispose();
}
public static int GetCurrentBrightness()
{
ManagementScope ms = new ManagementScope("root\\WMI");
SelectQuery sq = new SelectQuery("WmiMonitorBrightness");
ManagementObjectSearcher mos = new ManagementObjectSearcher(ms, sq);
ManagementObjectCollection moc = mos.Get();
byte currentBrightness = 0;
foreach(ManagementObject mo in moc)
{
currentBrightness = (byte)mo.GetPropertyValue("CurrentBrightness");
break;
}
moc.Dispose();
mos.Dispose();
return (int)currentBrightness;
}
public static bool LoadBrightnessLevels()
{
supportedBrightness = GetBrightnessLevels();
if (supportedBrightness.Length > 0)
{
int current = GetCurrentBrightness();
index = Array.IndexOf(supportedBrightness, (byte)current);
}
return supportedBrightness.Length != 0;
}
public static byte[] GetBrightnessLevels()
{
ManagementScope ms = new ManagementScope("root\\WMI");
SelectQuery sq = new SelectQuery("WmiMonitorBrightness");
ManagementObjectSearcher mos = new ManagementObjectSearcher(ms, sq);
byte[] levels = new byte[0];
try
{
ManagementObjectCollection moc = mos.Get();
foreach (ManagementObject o in moc)
{
levels = (byte[])o.GetPropertyValue("Level");
break;
}
moc.Dispose();
}
catch { }
mos.Dispose();
return levels;
}
[StructLayout(LayoutKind.Sequential)]
struct KeyboardHookStruct
{
public int VirtualKeyCode;
public int ScanCode;
public int Flags;
public int Time;
public IntPtr ExtraInfo;
}
public static IntPtr _hook = IntPtr.Zero;
public static void SetHook()
{
_hook = SetWindowsHookEx(13, HookCallback, GetModuleHandle(Process.GetCurrentProcess().MainModule.ModuleName), 0);
}
public static void Unhook()
{
UnhookWindowsHookEx(_hook);
}
public delegate IntPtr LowLevelKeyBoardProc(int nCode, IntPtr wParam, IntPtr lParam);
public static IntPtr HookCallback(int nCode, IntPtr wParam, IntPtr lParam)
{
Console.WriteLine(Thread.CurrentThread.ManagedThreadId);
if (nCode >= 0 && wParam == (IntPtr)0x0100)
{
KeyboardHookStruct khs = (KeyboardHookStruct)Marshal.PtrToStructure(lParam, typeof(KeyboardHookStruct));
// up is SC:8, VK:255, down is SC:9, VK:255
if (khs.VirtualKeyCode == 255)
{
if (khs.ScanCode == 8)
{
IncrementBrightness();
Console.WriteLine("Brightness up! {0}", supportedBrightness[index]);
}
else if (khs.ScanCode == 9)
{
DecrementBrightness();
Console.WriteLine("Brightness down! {0}", supportedBrightness[index]);
}
}
}
return CallNextHookEx(_hook, nCode, wParam, lParam);
}
[DllImport("user32.dll")]
public static extern IntPtr SetWindowsHookEx(int idHook, LowLevelKeyBoardProc lpfn, IntPtr hMod, uint dwThreadId);
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool UnhookWindowsHookEx(IntPtr hhk);
[DllImport("user32.dll")]
private static extern IntPtr CallNextHookEx(IntPtr hhk, int nCode, IntPtr wParam, IntPtr lParam);
[DllImport("user32.dll")]
private static extern uint MapVirtualKeyEx(uint uCode, uint uMapType, IntPtr dwhkl);
[DllImport("kernel32.dll")]
private static extern IntPtr GetModuleHandle(string lpModuleName);
}
}
Program.cs:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Forms;
namespace ComputerControl
{
static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new HiddenForm());
// Check if the hook is set, and if it is, unhook it.
if (Utils._hook.ToInt32() > 0)
Utils.Unhook();
}
}
}
All help is appreciated! Thanks!