2

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!

4

0 回答 0