I am using NAudio to play an mp3 file in my WinForms app. However, the file needs to be played to user-selected device, not the windows default one. So, what I am doing now is loading all available devices using this code:
{
ManagementObjectSearcher mo =
new ManagementObjectSearcher("select * from Win32_SoundDevice");
foreach (ManagementObject soundDevice in mo.Get())
{
String name = soundDevice.GetPropertyValue("Name").ToString();
comboBox1.Items.Add(name);
}
}
Now, NAudio requires some Device ID to change the active device. How do I get this ID, using the input from the comboBox (the device name)?
If you're using NAudio and with WaveOut, you can get the device names like this:
for (int deviceId = 0; deviceId < WaveOut.DeviceCount; deviceId++)
{
var capabilities = WaveOut.GetCapabilities(deviceId);
comboBoxWaveOutDevice.Items.Add(capabilities.ProductName);
}
The one caveat is that the old waveOut APIs don't allow for product names with more than 31 characters so they can appear truncated. If this turns out to be a problem for you, then DirectSoundOut or WasapiOut might be a good alternative.
Related
My C# application sits on the embedded box which has Intel motherboard and graphics chipset. ATI graphics card is put on to PCI express. Generally graphics card drives the video, but if ATI card fails then the video comes out from graphics chipset.
I have to detect the failure of ATI graphics card for diagnostic purposes.
Any ideas/sample code on how to do this.
Thanks in advance
Raju
This should hopefully get you started.
Add a reference to System.Management, then you can do this:
ManagementObjectSearcher searcher
= new ManagementObjectSearcher("SELECT * FROM Win32_DisplayConfiguration");
string graphicsCard = string.Empty;
foreach (ManagementObject mo in searcher.Get())
{
foreach (PropertyData property in mo.Properties)
{
if (property.Name == "Description")
{
graphicsCard = property.Value.ToString();
}
}
}
In my case, graphicsCard is equal to
NVIDIA GeForce 8400 GS (Microsoft
Corporation - WDDM v1.1)
I'm not a fan of how the selected answer only returns the first video controller. Also, there's no need to loop over all the properties. Just get the ones you need. If CurrentBitsPerPixel is not null, then you're looking at one of the active controllers. I'm using Win32_VideoController as suggested by #bairog, instead of the deprecated Win32_DisplayConfiguration.
ManagementObjectSearcher searcher =
new ManagementObjectSearcher("SELECT * FROM Win32_VideoController");
foreach (ManagementObject mo in searcher.Get())
{
PropertyData currentBitsPerPixel = mo.Properties["CurrentBitsPerPixel"];
PropertyData description = mo.Properties["Description"];
if (currentBitsPerPixel != null && description != null)
{
if (currentBitsPerPixel.Value != null)
System.Console.WriteLine(description.Value);
}
}
My machine has 3 video controllers. The first one is not active (ShoreTel). The second one is active, but is not the video card (Desktop Authority). The third one is my NVidia. This code will print out both the DA controller and the NVidia controller.
Promoted answer works only for single video card system. When I have ATI and Nvidia cards - WMI query returns ATI even if that monitor is plugged into Nvidia card, dxdiag shows Nvidia and games runs on that card (usage).
The only way I could determine right video card was using SlimDX to create DX device and examine what card it used. However that .dll weights over 3Mb.
var graphicsCardName = new Direct3D().Adapters[0].Details.Description;
Your question isn't entirely clear, so I'm not sure if the follwing idea will help or not.
Perhaps something very simple would suffice:
If the two graphics cards run different resolutions check the monitor resolution using:
System.Windows.Forms.SystemInformation.PrimaryMonitorSize
Similarly, if one card supports more than one monitor, check the number of monitors using SystemInformation.MonitorCount.
I tried all the approaches in this question but none gives me a correct answer. However I found it possible to get your current using the Win32_DisplayControllerConfiguration class. Although according to MSDN this class is obsolete, it's the only one returning a correct answer:
using System;
using System.Management;
using System.Windows.Forms;
namespace WMISample
{
public class MyWMIQuery
{
public static void Main()
{
try
{
ManagementObjectSearcher searcher =
new ManagementObjectSearcher("root\\CIMV2",
"SELECT * FROM Win32_DisplayControllerConfiguration");
foreach (ManagementObject queryObj in searcher.Get())
{
Console.WriteLine("----------------------------------- ");
Console.WriteLine("Win32_DisplayControllerConfiguration instance");
Console.WriteLine("-----------------------------------");
Console.WriteLine("Name: {0}", queryObj["Name"]);
}
}
catch (ManagementException e)
{
MessageBox.Show("An error occurred while querying for WMI data: " + e.Message);
}
}
}
}
(Code generated by WMI Code Creator, a great tool if you are messing with WMI.)
This gives GeForce GTX 1080 on my Windows 10 (RS2) + Intel(R) HD Graphics 4600 + NVIDIA GeForce GTX 1080 system.
Sometimes I need to switch between the Nvidia GPU and onboard GPU. To know which is connected to the monitor, I use the property MinRefreshRate. It works reliably for me, not CurrentBitsPerPixel.
public static void UpdateActiveGpu()
{
ManagementObjectSearcher searcher = new ManagementObjectSearcher("SELECT * FROM Win32_VideoController");
foreach (ManagementObject mo in searcher.Get())
{
PropertyData minRefreshRate = mo.Properties["MinRefreshRate"];
PropertyData description = mo.Properties["Description"];
if (minRefreshRate != null && description != null && minRefreshRate.Value != null)
{
Global.Instance.activeGpu = description.Value.ToString();
break;
}
}
}
I want to get the same hardware id in windows forms application that i get when i use UnityEngine.SystemInfo.deviceUniqueIdentifier in my game.
How can I get the same hardware id?
I know I'm late but Unity's SystemInfo::deviceUniqueIdentifier is built like this:
Requires: using System.Management; in System.Management.dll (.NET Framework)
private string GetDeviceUniqueIdentifier() {
string ret = string.Empty;
string concatStr = string.Empty;
try {
using ManagementObjectSearcher searcherBb = new ManagementObjectSearcher("SELECT * FROM Win32_BaseBoard");
foreach (var obj in searcherBb.Get()) {
concatStr += (string)obj.Properties["SerialNumber"].Value ?? string.Empty;
}
using ManagementObjectSearcher searcherBios = new ManagementObjectSearcher("SELECT * FROM Win32_BIOS");
foreach (var obj in searcherBios.Get()) {
concatStr += (string)obj.Properties["SerialNumber"].Value ?? string.Empty;
}
using ManagementObjectSearcher searcherOs = new ManagementObjectSearcher("SELECT * FROM Win32_OperatingSystem");
foreach (var obj in searcherOs.Get()) {
concatStr += (string)obj.Properties["SerialNumber"].Value ?? string.Empty;
}
using var sha1 = SHA1.Create();
ret = string.Join("", sha1.ComputeHash(Encoding.UTF8.GetBytes(concatStr)).Select(b => b.ToString("x2")));
} catch (Exception e) {
Console.WriteLine(e.ToString());
}
return ret;
}
I reverse engineered the Unity Editor to find out what it actually queries in the WMI.
This is obviously the Windows Implementation.
https://docs.unity3d.com/ScriptReference/SystemInfo-deviceUniqueIdentifier.html
SystemInfo.deviceUniqueIdentifier
Leave feedback
public static string deviceUniqueIdentifier;
Description
A unique device identifier. It is guaranteed to be unique for every device (Read Only).
iOS: on pre-iOS7 devices it will return hash of MAC address. On iOS7 devices it will be UIDevice identifierForVendor or, if that fails for any reason, ASIdentifierManager advertisingIdentifier.
Android: SystemInfo.deviceUniqueIdentifier always returns the md5 of ANDROID_ID. (See https://developer.android.com/reference/android/provider/Settings.Secure.html#ANDROID_ID). Note that since Android 8.0 (API level 26) ANDROID_ID depends on the app signing key. That means "unsigned" builds (which are by default signed with a debug keystore) will have a different value than signed builds (which are signed with a key provided in the player settings). Also when allowing Google Play to sign your app, this value will be different when testing locally built app which is signed with the upload key and app downloaded from the Google Play which will be signed with the "final" key.
Windows Store Apps: uses AdvertisingManager::AdvertisingId for returning unique device identifier, if option in 'PC Settings -> Privacy -> Let apps use my advertising ID for experiences across apps (turning this off will reset your ID)' is disabled, Unity will fallback to HardwareIdentification::GetPackageSpecificToken().Id.
Windows Standalone: returns a hash from the concatenation of strings taken from Computer System Hardware Classes (https://msdn.microsoft.com/en-us/library/windows/desktop/aa389273(v=vs.85).aspx):
Win32_BaseBoard::SerialNumber
Win32_BIOS::SerialNumber
Win32_Processor::UniqueId
Win32_DiskDrive::SerialNumber
Win32_OperatingSystem::SerialNumber
I would like to Read the name of USB camera (i.e., HD USB camera) attached to Windows 10 and store the name as a variable in C#.
You can try to filter the items in the Win32_PnPEntity class to only show items referring to the IMAGE or MEDIA category, which usually list items referring to the webcam connected to usb.
In the SQL command you can change the category.
using System.Management;
private static void GetUSBDevices()
{
var searcher = new ManagementObjectSearcher("SELECT * FROM Win32_PnPEntity WHERE (PNPClass = 'Image' OR PNPClass = 'Camera')");
foreach (var device in searcher.Get())
{
Console.WriteLine($"Device: {device["PNPClass"]} / {device["Caption"]}");
}
}
You will need to add the System.Management dependency to the project.
I'd like to get full name of all connected microphones. I was googling to find out an answer but there was no answer that satisfies me.
Let me show some examples:
1.
ManagementObjectSearcher mo = new ManagementObjectSearcher("select * from Win32_SoundDevice");
foreach (ManagementObject soundDevice in mo.Get())
{
MessageBox.Show(soundDevice.GetPropertyValue("Caption").ToString());
// or
MessageBox.Show(soundDevice.GetPropertyValue("Description").ToString());
//or
MessageBox.Show(soundDevice.GetPropertyValue("Manufacturer").ToString());
//or
MessageBox.Show(soundDevice.GetPropertyValue("Name").ToString());
//or
MessageBox.Show(soundDevice.GetPropertyValue("ProductName").ToString());
}
All of these getters shows: "Device Audio USB" or "Device compatible with High Definition standard".
2.
WaveInCapabilities[] devices = GetAvailableDevices();
foreach(device in devices)
{
MessageBox.Show(device.ProductName);
}
The same answer: "Device Audio USB" or "Device compatible with High Definition standard".
I want to get the full name. I mean, something like: "Sennheiser microphone USB". Is it even possible? I found: Get the full name of a waveIn device but a link in it is broken and I don't see any dsound.lib for c# (to use DirectSoundCaptureEnumerate).
Am I missing anything? Or is there any other option?
#AnkurTripathi answer is correct but it returns a name that contains up to 32 characters. If anyone doesn't want this restriction then the best idea is to use an enumarator:
using NAudio.CoreAudioApi;
MMDeviceEnumerator enumerator = new MMDeviceEnumerator();
var devices = enumerator.EnumerateAudioEndPoints(DataFlow.Capture, DeviceState.Active);
foreach (var device in devices)
MessageBox.Show(device.friendlyName);
It works perfect for me.
Try Naudio https://naudio.codeplex.com/
for (int n = 0; n < WaveIn.DeviceCount; n++)
{
this.recordingDevices.Add(WaveIn.GetCapabilities(n).ProductName);
comboBoxAudio.Items.Add(WaveIn.GetCapabilities(n).ProductName);
}
for get Full Name(FriendlyName):
MMDeviceEnumerator enumerator = new MMDeviceEnumerator();
foreach (MMDevice device in enumerator.EnumerateAudioEndPoints(DataFlow.Capture, DeviceState.Active))
{
this.recordingDevices.Add(device.FriendlyName);
}
My company developed a device that communicates with a PC via Bluetooth using a virtual COM port.
Now we need a user to pair a device with a PC (MS Windows OS) first and then enter it's com port number manually into our application(I bet 95% of users will fail on this taks).
So I'd like my application to present a user with a list of paired bluetooth devices (a list of their "friendly names") and after that I'd like to find out the selecded device's COM port number automatically.
How can I do it in c#? (a solution independent of installed bluetooth stack is appreciated).
Thanks in advance.
See my answer at Widcomm bluetooth : how to open the virtual COM for my understanding of the licence: using the binary version is free for commercial use. And, also that I'm maintainer of the library.
So a brief slight digression. I'm not a big fan of virtual COM ports. It always seems much easier to use a direct 'sockets' connection, rather than attempt to setup a COM port, and try to find what name it was created as (see below!), and then have to open a SerialPort to use it, and then if the connection is lost one doesn't know and have simply to keep retrying... With the library its so much easier to just to create and use that direct Bluetooth connection!
However you may want a solution to your current task at the moment. :-) So, use WMI to find the current COM ports in place and see if any of them are for your device. For example in PowerShell:
C:\> Get-WmiObject -query "select DeviceID,PNPDeviceID from Win32_SerialPort"
...
...
DeviceID : COM66
PNPDeviceID : BTHENUM\{00001101-0000-1000-8000-00805F9B34FB}\7&1D80ECD3&0&00803A686519_C00000003
In that big long string one sees the address of the target device: 00803A686519. One can use WMI from .NET, run that query, filter the ones with "BTHENUM", and then parse out the address.
If you the do need to create a new Bluetooth virtual COM port, use 32feet.NET's BluetoothDeviceInfo.SetServiceState(BluetoothService.SerialPort) API. See the "Bluetooth Serial Ports" section in the User Guide e.g. at http://www.alanjmcf.me.uk/comms/bluetooth/32feet.NET%20--%20User%20Guide.html, and the class documentation in the release.
Unfortunately the native Win32 API we call does not tell what name of COM port it created! :-( So run the WMI query before and after the call to see what new name appeared (or use System.IO.Ports.SerialPort.GetPortNames as its simpler).
That's all specific to the Microsoft Bluetooth stack. I haven't investigated how other stacks behave in this regard. After a brief check Widcomm's serial ports appear in SerialPort.GetPortNames but not in the WMI query...
First, create a Management Object Searcher to search the WMI database:
ManagementObjectSearcher serialSearcher =
new ManagementObjectSearcher("root\\CIMV2",
"SELECT * FROM Win32_SerialPort");
Next, use LINQ to get all the serial ports into a query:
var query = from ManagementObject s in serialSearcher.Get()
select new { Name = s["Name"], DeviceID = s["DeviceID"], PNPDeviceID = s["PNPDeviceID"] }; // DeviceID -- > PNPDeviceID
You can now print all the COM ports, their friendly names and you can even filter through their PNPDeviceID's to find the bluetooth device address. Here's an example:
foreach (var port in query)
{
Console.WriteLine("{0} - {1}", port.DeviceID, port.Name);
var pnpDeviceId = port.PNPDeviceID.ToString();
if(pnpDeviceId.Contains("BTHENUM"))
{
var bluetoothDeviceAddress = pnpDeviceId.Split('&')[4].Split('_')[0];
if (bluetoothDeviceAddress.Length == 12 && bluetoothDeviceAddress != "000000000000")
{
Console.WriteLine(" - Address: {0}", bluetoothDeviceAddress);
}
}
}
I manage to get the bluetooth name and the COM port by fiddling the registry key
The pseudo code to obtain the bluetooth information is below:
enumerate all the COM port available in the PNP
obtain the device classGuid
search the bluetooth address from the classGuid
when the bluetooth address is known, the bluetooth name can be obtained from the this registry SYSTEM\CurrentControlSet\Services\BTHPORT\Parameters\Devices
The code is below, just call the GetBluetoothPort(), it will return a list of bluetooth devices, and you could connect them by passing the COM port number to the SerialPort class
public static string[] GetBluetoothPort()
{
Regex regexPortName = new Regex(#"(COM\d+)");
List<string> portList = new List<string>();
ManagementObjectSearcher searchSerial = new ManagementObjectSearcher("SELECT * FROM Win32_PnPEntity");
foreach (ManagementObject obj in searchSerial.Get()) {
string name = obj["Name"] as string;
string classGuid = obj["ClassGuid"] as string;
string deviceID = obj["DeviceID"] as string;
if (classGuid != null && deviceID != null) {
if (String.Equals(classGuid, "{4d36e978-e325-11ce-bfc1-08002be10318}", StringComparison.InvariantCulture)) {
string[] tokens = deviceID.Split('&');
if (tokens.Length >= 4) {
string[] addressToken = tokens[4].Split('_');
string bluetoothAddress = addressToken[0];
Match m = regexPortName.Match(name);
string comPortNumber = "";
if (m.Success) {
comPortNumber = m.Groups[1].ToString();
}
if (Convert.ToUInt64(bluetoothAddress, 16) > 0) {
string bluetoothName = GetBluetoothRegistryName(bluetoothAddress);
portList.Add(String.Format("{0} {1} ({2})", bluetoothName, bluetoothAddress, comPortNumber));
}
}
}
}
}
return portList.ToArray();
}
private static string GetBluetoothRegistryName(string address)
{
string deviceName = "";
string registryPath = #"SYSTEM\CurrentControlSet\Services\BTHPORT\Parameters\Devices";
string devicePath = String.Format(#"{0}\{1}", registryPath, address);
using (RegistryKey key = Registry.LocalMachine.OpenSubKey(devicePath)) {
if (key != null) {
Object o = key.GetValue("Name");
byte[] raw = o as byte[];
if (raw != null) {
deviceName = Encoding.ASCII.GetString(raw);
}
}
}
return deviceName;
}
Maybe it is not what you are looking for, and maybe you already found your answer...
I just found a question not exactly like yours but worked for me.. With this one you can find out which one of your COM Ports are from a Bluetooth device:
StackOverflow - Determine if serial port is normal COM or SPP
I hope it helps somehow. If you find out how to do what you wanted, please let me know. Thanks.
So, to get the information about a remote device including its name, using 32feet.NET do:
BluetoothAddress addr = ... ...
BluetoothDeviceInfo info = new BluetoothDeviceInfo(addr);
string name = info.DeviceName;
If not using the library you'll have to P/Invoke Win32's BluetoothGetDeviceInfo.
private static string FindSerialPortForRFIDReaderCore()
{
string serialPort = "";
List<string> ports = new List<string>();
System.Management.ManagementObjectSearcher Searcher = new System.Management.ManagementObjectSearcher("Select * from WIN32_SerialPort");
foreach (System.Management.ManagementObject Port in Searcher.Get())
{
if (Port["PNPDeviceID"].ToString().ToUpper().Contains("MacAddress"))
ports.Add(Port["DeviceID"].ToString());
}
if (ports.Count > 1) // There are more than one Serial Ports created for the bluetooth device.
serialPort = ports.OrderByDescending(p => p).FirstOrDefault();
else if(ports.Count == 1)
serialPort = ports[0];
return serialPort;
}