tagger tag software metadatos files best windows winforms winapi monitor edid

windows - tag - Buscando un mapeo confiable de Forms.Screen.DeviceName para monitorear información EDID



tag editor music pc (1)

Estoy desarrollando una aplicación que mostrará información derivada de los bloques EDID (modelo de monitor, ID, S / N, etc.) en un diálogo en el monitor correspondiente.

Este código funciona para encontrar la información EDID para pantallas. Extrae la información EDID al enumerar las teclas DISPLAY bajo HKLM / SYSTEM / CurrentControlSet / Enum / DISPLAY / [Monitor] / [PnPID] / Device Parameters / EDID .

Actualización: El código anterior se basa en los "efectos secundarios" del uso de PnP del registro. Ahora estoy usando SetupAPI para enumerar monitores, que maneja correctamente los monitores que se adjuntan / eliminan (a diferencia del código del enlace anterior).

Estoy tratando de correlacionar cada pantalla en Windows.Forms.Screen.AllScreens [] (//. / DISPLAY1, //. / DISPLAY2, etc.) con las entradas devueltas desde la inspección de registro anterior.

Nota: en el bloque de código siguiente, DisplayDetails.GetMonitorDetails () ahora se ha reemplazado por un código de enumeración de registro más robusto utilizando SetupAPI, pero los datos devueltos son los mismos.

p.ej

private void Form1_Load(object sender, EventArgs e) { Console.WriteLine("Polling displays on {0}:", System.Environment.MachineName); int i = 0; foreach ( DisplayDetails dd in DisplayDetails.GetMonitorDetails()) { Console.WriteLine( "Info: Model: {0}, MonitorID: {1}, PnPID: {2}, Serial#:{3}", dd.Model, dd.MonitorID, dd.PnPID, dd.SerialNumber ); Console.WriteLine( "Does this correlate to Screen: {0}?", Screen.AllScreens[i++].DeviceName ); } }

Salida:

Información: Modelo: DELL P2411H, MonitorID: DELA06E, PnPID: 5 y 2e2fefea & 0 y UID1078018, Número de serie: F8NDP0C ... PU

¿Esto se correlaciona con la pantalla: //. / DISPLAY1?

Información: Modelo: DELL P2411H, MonitorID: DELA06E, PnPID: 5 y 2e2fefea & 0 y UID1078019, Número de serie: F8NDP0C ... AU

¿Esto se correlaciona con la pantalla: //. / DISPLAY2?

Respuesta: NO

En las pruebas, he encontrado que estos no se correlacionan de manera confiable (tengo un sistema en el que la primera pantalla enumerada es //. / DISPLAY2).

Mi pregunta: ¿Hay alguna forma de obtener de manera confiable la información EDID para una Forms.Screen determinada? Puedo obtener el bloque EDID, pero no he encontrado ninguna ruta para correlacionar esto con el Formulario de nivel superior de la interfaz de usuario. Inducir al usuario no es deseable, ya que en mi caso de uso los dos (o más) monitores probablemente serán del mismo modelo y resolución, y solo difieren en unos pocos dígitos en el S / N.

He buscado rutas siguiendo Forms.Screen API, Win32 EnumDisplay, otros GUID de registro (PnP y relacionados con el controlador), pero no he encontrado ninguna ruta prometedora.

También investigué la API WMI Win32_DesktopMonitor (Windows 7), sin embargo, no parece tener más información que me ayude a correlacionarla con las entradas de Windows.Forms.Screen.AllScreens [].

Sospecho que si hay una manera de hacer esto, es a través de la API de instalación, pero aún no la he encontrado.


Un método para resolver el GDI a SetupAPI está disponible en la API EnumDisplayDevices . Si pasa el EDD_GET_DEVICE_INTERFACE_NAME en dwFlags, la enumeración del monitor devolverá la información del ID de dispositivo del formulario:

Monitor 0 info: DeviceName: //./DISPLAY1 MonitorInfo: Dell P2411H(Digital) DeviceID: //?/DISPLAY#DELA06E#5&2e2fefea&0&UID1078018#{e6f07b5f-ee97-4a90-b076-3 3f57bf4eaa7} Monitor 1 info: DeviceName: //./DISPLAY2 MonitorInfo: Dell P2411H(Digital) DeviceID: //?/DISPLAY#DELA06E#5&2e2fefea&0&UID1078019#{e6f07b5f-ee97-4a90-b076-3 3f57bf4eaa7}

Los campos DeviceID ahora coinciden con los resultados de didd.DevicePath , como se recupera en el fragmento C # a continuación:

Guid MonitorGUID = new Guid(Win32.GUID_DEVINTERFACE_MONITOR); // We start at the "root" of the device tree and look for all // devices that match the interface GUID of a monitor IntPtr h = Win32.SetupDiGetClassDevs(ref MonitorGUID, IntPtr.Zero, IntPtr.Zero, (uint)(Win32.DIGCF_PRESENT | Win32.DIGCF_DEVICEINTERFACE)); if (h.ToInt64() != Win32.INVALID_HANDLE_VALUE) { bool Success = true; uint i = 0; while (Success) { // create a Device Interface Data structure Win32.SP_DEVICE_INTERFACE_DATA dia = new Win32.SP_DEVICE_INTERFACE_DATA(); dia.cbSize = (uint)Marshal.SizeOf(dia); // start the enumeration Success = Win32.SetupDiEnumDeviceInterfaces(h, IntPtr.Zero, ref MonitorGUID, i, ref dia); if (Success) { // build a DevInfo Data structure Win32.SP_DEVINFO_DATA da = new Win32.SP_DEVINFO_DATA(); da.cbSize = (uint)Marshal.SizeOf(da); // build a Device Interface Detail Data structure Win32.SP_DEVICE_INTERFACE_DETAIL_DATA didd = new Win32.SP_DEVICE_INTERFACE_DETAIL_DATA(); didd.cbSize = (uint)(4 + Marshal.SystemDefaultCharSize); // trust me :) // now we can get some more detailed information uint nRequiredSize = 0; uint nBytes = Win32.BUFFER_SIZE; if (Win32.SetupDiGetDeviceInterfaceDetail(h, ref dia, ref didd, nBytes, out nRequiredSize, ref da)) { // Now we get the InstanceID IntPtr ptrInstanceBuf = Marshal.AllocHGlobal((int)nBytes); Win32.CM_Get_Device_ID(da.DevInst, ptrInstanceBuf, (int)nBytes, 0); string InstanceID = Marshal.PtrToStringAuto(ptrInstanceBuf); Console.WriteLine("InstanceID: {0}", InstanceID ); Marshal.FreeHGlobal(ptrInstanceBuf); Console.WriteLine("DevicePath: {0}", didd.DevicePath ); } i++; } } } Win32.SetupDiDestroyDeviceInfoList(h); }

Muestra de salida:

InstanceID: DISPLAY/DELA06E/5&2E2FEFEA&0&UID1078018 DevicePath: //?/display#dela06e#5&2e2fefea&0&uid1078018#{e6f07b5f-ee97-4a90-b076-33f57bf4eaa7}

DeviceName de EnumDisplayDevices original coincide con la propiedad Forms.Screen.DeviceName.

Con estas dos piezas de información, ahora es posible leer el bloque EDID durante el recorrido SetupDIEnumDeviceInterface usando un fragmento como el siguiente:

private static byte[] GetMonitorEDID(IntPtr pDevInfoSet, SP_DEVINFO_DATA deviceInfoData) { IntPtr hDeviceRegistryKey = SetupDiOpenDevRegKey(pDevInfoSet, ref deviceInfoData, DICS_FLAG_GLOBAL, 0, DIREG_DEV, KEY_QUERY_VALUE); if (hDeviceRegistryKey == IntPtr.Zero) { throw new Exception("Failed to open a registry key for device-specific configuration information"); } IntPtr ptrBuff = Marshal.AllocHGlobal((int)256); try { RegistryValueKind lpRegKeyType = RegistryValueKind.Binary; int length = 256; uint result = RegQueryValueEx(hDeviceRegistryKey, "EDID", 0, ref lpRegKeyType, ptrBuff, ref length); if (result != 0) { throw new Exception("Can not read registry value EDID for device " + deviceInfoData.ClassGuid); } } finally { RegCloseKey(hDeviceRegistryKey); } byte[] edidBlock = new byte[256]; Marshal.Copy(ptrBuff, edidBlock, 0, 256); Marshal.FreeHGlobal(ptrBuff); return edidBlock; }

Que, finalmente, se puede analizar para los bloques del descriptor VESA, como se muestra en el método DisplayDetails.GetMonitorDetails () en este código.