Open sgeraldes opened 6 months ago
Hi, oh, wow, you did hit a hard one. This error is returned when the Windows OS functions return "generic failure", likely as last resort, because "something" did not work out. Sadly, the Windows function does not provide me with any means to get more information.
Does this call fail for all/any monitors, only the Display5
/ MPI5001
?
Can you enable the display manually, and then try to disable it with ToggleDisplay? And, if that would work, the question is if you then could reable the display via ToggleDisplay?
My idea is, ToggleDisplay calls SetDisplayConfig
, and according to Microsoft's documentation:
If the active paths that the caller supplies do not have an entry in the persistence database, SetDisplayConfig fails.
If you enable the display via Windows User Interface, it should make sure that a matching database entry exists.
I am a bit confused that list
returned multiple entries for \.\DISPLAY2
which also should be \\.\DISPLAY2
starting with two backslashes. I have not seen this before, that a GDI Device name is listed multiple times. Can you switch on more displays and post the output of list
again?
Which version of Windows are you running?
What kind of graphics card do you use? (Please, check that you use the newest graphics card drivers.)
Note: the tool should work just fine in an non-admin Powershell.
Windows 11 up-to-date. Nvidia RTX 4090 with the latest drivers. BIOS is updated, and every thing else is up to date. Manually enabling it, via display or with Win+p works fine. When it's enabled, it can be disabled with ToggleDisplay. I found out however that it fails when mannually setting it to single monitor in display settings, and after that, the only way to enable it using displaytoggle is to use win+p to set it in extended mode, then it can be disabled. When back at home I'll try a few other things. I didn't realize all other displays where set to display 2. I thing I know what this could be thou. It may be related to another tool I use to set and restore multi-monitor setups. I'll keep you posted.
Interesting. I only ever used ToggleDisplay myself to enable/disable additional monitors, extending my desktop. The stored data entries seem different when you previously only "switched" single display modes between monitors.
Can you tell me which other tool you have set up?
I will try some setup changes myself later. The "Single Display"-thing sounds like a promising details to hunt this down.
When I switch (Win+P) to one display only:
ToggleDisplay.exe list
\\.\DISPLAY1 -> DELL P2415Q (\\?\DISPLAY#DELA0BE#5&8fda59d&0&UID257#{e6f07b5f-ee97-4a90-b076-33f57bf4eaa7}) [enabled]
(w: 3840; h: 2160; x: 0; y: 0)
\\.\DISPLAY2 -> DELL P2415Q (\\?\DISPLAY#DELA0BE#5&8fda59d&0&UID261#{e6f07b5f-ee97-4a90-b076-33f57bf4eaa7}) [disabled]
\\.\DISPLAY2 -> VSX-2020 (\\?\DISPLAY#PIO0000#5&8fda59d&0&UID265#{e6f07b5f-ee97-4a90-b076-33f57bf4eaa7}) [disabled]
I get the same effect of seeing multiple entries for \\.\DISPLAY2
. So, that's where that comes from.
I then switched between single displays back and forth using Win+P. (Primary only, secondary only) The output of "ToggleDisplay List" was as expected.
Then I switch on the off display by:
ToggleDisplay.exe enable "\\?\DISPLAY#DELA0BE#5&8fda59d&0&UID261#{e6f07b5f-ee97-4a90-b076-33f57bf4eaa7}"
and it works.
Note, that I had to use the internal device name, as both the GDI device name \\.\DISPLAY2
and monitor name DELL P2415Q
were not unique in my setup. Which identifier you use will not make a difference. If it's non-unique or if it does not match any display, you will get another (more specific) error message.
I assume, it works because that setup was active some time in the past, and therefore has an entry in this ominous "persistence database" the Microsoft documentation talks about.
I use https://sourceforge.net/projects/monitorswitcher/ I have 5 monitors that I share with my work's macbook, all of them connected with multiple inputs. So I use MonitorProfileSwitcher to switch between setups using a stream deck. Looks something like this: I toggle between all these setups as needed, and when I do, the monitors that are off, autoswitch to the other input (the macbook's). That paired with Synergy (kvm share), and I can seamlessly switch between both win-mac. So lastly, I added a small touchscreen to my setup, which makes the combinations too many, so I'm using ToggleDisplay to actually toggle it on and off. So, to sum it up:
Maybe you can add a check to see if the displays are in Single Monitor? Or even turn on extended before switching on the second monitor?
Oh! By the way!!!! I forgot that I have that touchscreen (MPI5001 connected to my motherboard's (AMD IGD) hdmi port! So that's maybe why it's DISPLAY5 instead of all other DISPLAY2s.
@sgeraldes, since I cannot reproduce the behavior on my system, I created a version of ToggleDisplay with extended logging capability. Can you please download and run this one: https://github.com/sgrottel/tiny-tools-collection/actions/runs/9084736899#artifacts
Functionality is the same, so ToggleDisplay will (hopefully) still fail in your scenario.
Run a command that fails for you, e.g.: .\ToggleDisplay.exe enable \\.\Display5
Directly afterwards go to the directory with the ToggleDisplay log files.
It's in: %AppData%\..\LocalLow\sgrottel_simplelog
(for me that is C:\Users\###\AppData\LocalLow\sgrottel_simplelog
with ### being my username)
There you should find a file ToggleDisplay.log
Please, send me that file, preferrably attached to your next post and not as the post's text, since the file will be large.
@sgrottel I know why this occurs, at least I'm about 90% sure. How do I know this? I've been working with this API today and yesterday and I've been facing a similar error. Not in this codebase, but my own. Anyhow, let me try and explain the issue here.
If you have multiple displays and they're all attached to the same adapter (GPU). Their sourceInfo.id
s will be incremental for each. If you query the displays with QueryDisplayConfig
, you'll that any given display has multiple DISPLAYCONFIG_PATH_INFO
, one for each of the possible source ids available in the adapter. Example:
LG TV - \\?\DISPLAY#GSMC0A0#7&289ec95a&0&UID268#{e6f07b5f-ee97-4a90-b076-33f57bf4eaa7}
+---------+--------+----------+----------+------+----------+--------------+--------+----------+----------+
| enabled | source | adapter | mode idx | size | position | pixel format | target | adapter | mode idx |
+=========+========+==========+==========+======+==========+==============+========+==========+==========+
| false | 0 | 70517, 0 | None | | | | 268 | 70517, 0 | None |
+---------+--------+----------+----------+------+----------+--------------+--------+----------+----------+
| false | 1 | 70517, 0 | None | | | | 268 | 70517, 0 | None |
+---------+--------+----------+----------+------+----------+--------------+--------+----------+----------+
| false | 2 | 70517, 0 | None | | | | 268 | 70517, 0 | None |
+---------+--------+----------+----------+------+----------+--------------+--------+----------+----------+
| false | 3 | 70517, 0 | None | | | | 268 | 70517, 0 | None |
+---------+--------+----------+----------+------+----------+--------------+--------+----------+----------+
| false | 4 | 70517, 0 | None | | | | 268 | 70517, 0 | None |
+---------+--------+----------+----------+------+----------+--------------+--------+----------+----------+
| false | 5 | 70517, 0 | None | | | | 268 | 70517, 0 | None |
+---------+--------+----------+----------+------+----------+--------------+--------+----------+----------+
| false | 6 | 70517, 0 | None | | | | 268 | 70517, 0 | None |
+---------+--------+----------+----------+------+----------+--------------+--------+----------+----------+
In this example the adapter has the source IDs 0-6. I have 3 other displays attached and those are using IDs 0, 1, and 2. You will find that if you try to enable 0, 1, or 2 of this currently disabled (unactive) "LG TV", you'll get an ERROR_GEN_FAILURE
. Though if you select 3, it'll work.
In short, you need to use a source id on the adapter that is unused.
So how to fix this in your code? (I've only given your code a quick glance so forgive me any mistakes.) You're currently selecting the first available display that matches what the user wants to enable and then subsequently enabling that. You need to make sure here that the one you're enabling, has its source id available.
Let me know if you have any questions, though I cannot guarantee I'll know the answer myself. I really wish this API was documented better. 🙃
Thank you for the hint. I will take a look.
Hi, I'm getting ERROR_GEN_FAILURE when trying to toggle, enable, or disable a single monitor in a quad monitor setup.
PS > .\ToggleDisplay.exe list
\.\DISPLAY1 -> DELL U2412M (\?\DISPLAY#DELA07A#5&18724ba8&0&UID4358#{e6f07b5f-ee97-4a90-b076-33f57bf4eaa7}) [enabled] (w: 1920; h: 1200; x: 0; y: 0) \.\DISPLAY5 -> MPI5001 (\?\DISPLAY#MPI5001#5&5c7276&0&UID524#{e6f07b5f-ee97-4a90-b076-33f57bf4eaa7}) [disabled] \.\DISPLAY2 -> SAMSUNG (\?\DISPLAY#SAM720D#5&18724ba8&0&UID4352#{e6f07b5f-ee97-4a90-b076-33f57bf4eaa7}) [disabled] \.\DISPLAY2 -> DELL U2412M (\?\DISPLAY#DELA07A#5&18724ba8&0&UID4354#{e6f07b5f-ee97-4a90-b076-33f57bf4eaa7}) [disabled] \.\DISPLAY2 -> AORUS FI27Q (\?\DISPLAY#GBT2706#5&18724ba8&0&UID4355#{e6f07b5f-ee97-4a90-b076-33f57bf4eaa7}) [disabled]
PS > .\ToggleDisplay.exe enable \.\Display5 Enabling display Failed to apply changed display config: ERROR_GEN_FAILURE
PS > .\ToggleDisplay.exe TOGGLE MPI5001 Selected display is disabled... enabling Failed to apply changed display config: ERROR_GEN_FAILURE
I'm running the binary release on an administrator powershell terminal.