Search code examples
c#c++.netwindowsnaudio

Enabling recording devices programmatically


Enabling recording devices programmatically

I want to enable the disabled device in Sound - Recording devices list programmatically

enter image description here

I was able to get a list of disabled devices using Naudio

But there is no way to enable it using Naudio.

so I tried also using IMMDevice interface but I couldn't find out how to do this.

I tried also Registry Edit

//Computer\HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\MMDevices\Audio\Render\{87bd5990-b012-41f1-83f7-f267ed7780a7}
    RegistryKey root = Registry.LocalMachine.OpenSubKey("SOFTWARE", true).OpenSubKey("Microsoft", true).OpenSubKey("Windows", true).OpenSubKey("CurrentVersion", true).OpenSubKey("MMDevices", true).OpenSubKey("Audio", true).OpenSubKey("Render", true).OpenSubKey("{87bd5990-b012-41f1-83f7-f267ed7780a7}", true); //{87bd5990-b012-41f1-83f7-f267ed7780a7} any Playback Device ID
    MessageBox.Show($"Value Before {root.GetValue("DeviceState")}   { root.GetValueKind("DeviceState")}");
    root.SetValue("DeviceState", 0x10000001, RegistryValueKind.DWord);
    MessageBox.Show($"Value After {root.GetValue("DeviceState")}    { root.GetValueKind("DeviceState")}");

or

Registry.SetValue(@"HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\MMDevices\Audio\Render\{87bd5990-b012-41f1-83f7-f267ed7780a7}", "DeviceState", 0x10000001, RegistryValueKind.DWord);

but this will need Administrator Rights and I want it to work for any user.


Solution

  • I found this solution and I am not sure if there is any other solution :

    Using NAudio and TestStack.White you can open the Sounds List and enable and close it this will not need for admin privileges:

    using NAudio.CoreAudioApi;
    using System;
    using System.Diagnostics;
    using System.Linq;
    using System.Runtime.InteropServices;
    using System.Threading.Tasks;
    using System.Windows.Forms;
    
    namespace Enable_Device
    {
    class Program
    {
        [DllImport("User32.dll")]
        public static extern Int32 FindWindow(String lpClassName, String lpWindowName);
    
        [DllImport("user32.dll", SetLastError = true)]
        static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint processId);
    
        [DllImport("user32.dll", CharSet = CharSet.Auto)]
        private static extern IntPtr SendMessage(IntPtr hWnd, UInt32 Msg, IntPtr wParam, IntPtr lParam);
    
    
        private const UInt32 WM_CLOSE = 0x0010;
    
        static void CloseWindow(IntPtr hwnd)
        {
            SendMessage(hwnd, WM_CLOSE, IntPtr.Zero, IntPtr.Zero);
        }
        static void Main(string[] args)
        {
            string driverName = "Stereo Mix"; // any device name you want to enable
    
            MMDevice mMDevice;
            using (var enumerator = new NAudio.CoreAudioApi.MMDeviceEnumerator())
            {
                mMDevice = enumerator.EnumerateAudioEndPoints(DataFlow.Capture, DeviceState.Disabled).ToList().Where(d => d.FriendlyName.ToLower().Contains(driverName.ToLower())).FirstOrDefault();
            }
            if (mMDevice != null)
            {
                driverName = mMDevice.FriendlyName;
                int charLocation = driverName.IndexOf("(", StringComparison.Ordinal);
    
                if (charLocation > 0)
                {
                    driverName = driverName.Substring(0, charLocation);
                    driverName = driverName.Trim();
                }
            }
            else
            {
    
                MessageBox.Show($"{driverName} Coudn't Found as Disabled Device.");
    
                return;
            }
            TryEnable(driverName, mMDevice);
    
        
        }
    
        private static void TryEnable(string driverName, MMDevice mMDevice)
        {
            try
            {
                var hwnd = 0;
                hwnd = FindWindow(null, "Sound");
                Process soundProc;
                if (hwnd == 0)
                {
                    soundProc = Process.Start("control.exe", "mmsys.cpl,,1");
                }
                else
                {
                    CloseWindow((IntPtr)hwnd);
                    while (hwnd == 0)
                    {
                        Debug.WriteLine($"Waiting to Close ...");
                    
                        hwnd = FindWindow(null, "Sound");
                    }
                    soundProc = Process.Start("control.exe", "mmsys.cpl,,1");
                }
                hwnd = 0;
                hwnd = FindWindow(null, "Sound");
                while (hwnd == 0)
                {
                    Debug.WriteLine($"Waiting ...");
                    
                    hwnd = FindWindow(null, "Sound");
                }
                if (hwnd == 0)
                {
    
                    MessageBox.Show($"Couldnt find Sound Window.");
                    return;
                }
                var id = GetWindowThreadProcessId((IntPtr)hwnd, out uint i);
                TestStack.White.Application application = TestStack.White.Application.Attach((int)i);
                Debug.WriteLine($"{application.Name}");
                TestStack.White.UIItems.WindowItems.Window window = application.GetWindow("Sound");
    
                var exists = window.Exists(TestStack.White.UIItems.Finders.SearchCriteria.ByText(driverName));
                if (exists)
                {
                    TestStack.White.UIItems.ListBoxItems.ListItem listItem = window.Get<TestStack.White.UIItems.ListBoxItems.ListItem>(TestStack.White.UIItems.Finders.SearchCriteria.ByText(driverName));
    
                    listItem.Focus();
                    window.Keyboard.PressSpecialKey(TestStack.White.WindowsAPI.KeyboardInput.SpecialKeys.UP);
                    window.Keyboard.PressSpecialKey(TestStack.White.WindowsAPI.KeyboardInput.SpecialKeys.DOWN);
    
                    window.Keyboard.HoldKey(TestStack.White.WindowsAPI.KeyboardInput.SpecialKeys.SHIFT);
                    window.Keyboard.PressSpecialKey(TestStack.White.WindowsAPI.KeyboardInput.SpecialKeys.F10);
                    window.Keyboard.LeaveKey(TestStack.White.WindowsAPI.KeyboardInput.SpecialKeys.SHIFT);
                    window.Keyboard.Enter("E");
    
                }
                else
                {
                    window.Keyboard.HoldKey(TestStack.White.WindowsAPI.KeyboardInput.SpecialKeys.SHIFT);
                    window.Keyboard.PressSpecialKey(TestStack.White.WindowsAPI.KeyboardInput.SpecialKeys.F10);
                    window.Keyboard.LeaveKey(TestStack.White.WindowsAPI.KeyboardInput.SpecialKeys.SHIFT);
                    window.Keyboard.Enter("S");
                    window.Keyboard.PressSpecialKey(TestStack.White.WindowsAPI.KeyboardInput.SpecialKeys.RETURN);
                    TestStack.White.UIItems.ListBoxItems.ListItem listItem = window.Get<TestStack.White.UIItems.ListBoxItems.ListItem>(TestStack.White.UIItems.Finders.SearchCriteria.ByText(driverName));
    
                    listItem.Focus();
                    window.Keyboard.PressSpecialKey(TestStack.White.WindowsAPI.KeyboardInput.SpecialKeys.UP);
                    window.Keyboard.PressSpecialKey(TestStack.White.WindowsAPI.KeyboardInput.SpecialKeys.DOWN);
    
                    window.Keyboard.HoldKey(TestStack.White.WindowsAPI.KeyboardInput.SpecialKeys.SHIFT);
                    window.Keyboard.PressSpecialKey(TestStack.White.WindowsAPI.KeyboardInput.SpecialKeys.F10);
                    window.Keyboard.LeaveKey(TestStack.White.WindowsAPI.KeyboardInput.SpecialKeys.SHIFT);
                    window.Keyboard.Enter("E");
    
                }
                if (mMDevice != null)
                {
                    if (mMDevice.State == DeviceState.Active)
                    {
                        Debug.WriteLine($"{ mMDevice.FriendlyName}");
                        CloseWindow((IntPtr)hwnd);
                    }
                    else
                    {
    
                        MessageBox.Show("Please Enable the device ");
    
                    }
                }
            }
            catch (Exception)
            {
    
            }
    
        }
     }
      }
    

    If you have Admin privileges

     private void EnableAsAdmin()
            {
                string driverName = "Stereo Mix";
                string deviceId = "";
                
                
                MMDevice mMDevice;
                using (var enumerator = new NAudio.CoreAudioApi.MMDeviceEnumerator())
                {
                    mMDevice = enumerator.EnumerateAudioEndPoints(DataFlow.Capture, DeviceState.Disabled).ToList().Where(d => d.FriendlyName.ToLower().Contains(driverName.ToLower())).FirstOrDefault();
                }
                if (mMDevice != null)
                {
                    driverName = mMDevice.FriendlyName;
                    int charLocation = driverName.IndexOf("(", StringComparison.Ordinal);
    
                    if (charLocation > 0)
                    {
                        driverName = driverName.Substring(0, charLocation);
                        driverName = driverName.Trim();
                    }
    
                    deviceId = mMDevice.ID;
                    charLocation = deviceId.IndexOf(".{", StringComparison.Ordinal);
    
                    if (charLocation > 0)
                    {
                        deviceId = deviceId.Substring(charLocation + 1);
                        deviceId = deviceId.Trim();
                    }
    
                    if (!string.IsNullOrWhiteSpace(deviceId) && AdminHelper.IsRunAsAdmin())
                    {
                        if (Environment.Is64BitOperatingSystem)
                        {
    
                            RegistryKey localKey =
                                RegistryKey.OpenBaseKey(Microsoft.Win32.RegistryHive.LocalMachine,
                                    RegistryView.Registry64);
                            localKey = localKey.OpenSubKey(@"SOFTWARE\Microsoft\Windows\CurrentVersion\MMDevices\Audio\Capture\" + deviceId, RegistryKeyPermissionCheck.ReadWriteSubTree, RegistryRights.SetValue);
                            localKey.SetValue("DeviceState", 1, RegistryValueKind.DWord);
                        }
                        else
                        {
    
                            RegistryKey localKey32 =
                                RegistryKey.OpenBaseKey(Microsoft.Win32.RegistryHive.LocalMachine,
                                    RegistryView.Registry32);
                            localKey32 = localKey32.OpenSubKey(@"SOFTWARE\Microsoft\Windows\CurrentVersion\MMDevices\Audio\Capture\" + deviceId, RegistryKeyPermissionCheck.ReadWriteSubTree, RegistryRights.SetValue);
         localKey32.SetValue("DeviceState", 1, RegistryValueKind.DWord);
                        }
                    }
                    if (mMDevice != null)
                    {
                        if (mMDevice.State == DeviceState.Active)
                        {
                            App.Current.Dispatcher.Invoke(() =>
                            {
                                MessageBox.Show($"{driverName} Enabled ");
                            });
                        }
                    }
                }
                else
                {
                    App.Current.Dispatcher.Invoke(() =>
                    {
                        MessageBox.Show($"{driverName} Coudn't Found as Disabled Device.");
                    });
                    return;
                }
            }
    

    Is there any other solution?