Comments (17)
Yeah, I just did this. This kind of undocumented behavior is really hard to work with.
Thank you very much for your help.
from winsafe.
@michidk I changed this function to return an iterator, so the loop work is done internally. If you're still interested, I'd be glad to hear if it works for you.
New docs with example can be found here.
from winsafe.
As far as I could investigate, the enumeration ends when EnumDisplayDevices
returns zero and GetLastError
returns ERROR_PROC_NOT_FOUND
, therefore the foolproof implementation has to consider this. The check is necessary to rule out legitimate errors.
I changed the implementation to reflect this. Please let me know if this worked for you.
from winsafe.
Wow that was quick :D. I am not too familiar with winapi error handling stuff, but if I adjusted my code like mentioned in the example:
/// Returns a list of all displays.
pub fn discover_displays() -> Result<DisplaySet> {
let mut result = Vec::<Display>::new();
let mut dev_num: u32 = 0;
let mut display_device = DISPLAY_DEVICE::default();
loop {
let has_more = EnumDisplayDevices(
None,
dev_num,
&mut display_device,
EDD::GET_DEVICE_INTERFACE_NAME,
)?;
if has_more {
result.push(Display::from_winsafe(dev_num, &display_device)?);
dev_num += 1;
} else {
break;
}
}
Ok(DisplaySet { displays: result })
}
Then the fn returns early with the following Err: "[0x00cb 203] The system could not find the environment option that was entered.".
The following works fine:
let has_more = EnumDisplayDevices(
...
); // no `?`
if has_more.is_ok() { // `is_ok()` instead
result.push(Display::from_winsafe(dev_num, &display_device)?);
dev_num += 1;
} else {
break;
}
This might have to do with the fact that I have one display that is active: false
?
from winsafe.
Indeed, it seems that a display with active: false
returns an error for that specific index, and since this is meaningful to you, you'll have to treat that error specifically, and turn the active
into some sort of flag. Maybe something like this:
{
use winsafe as w;
let mut dev_num: u32 = 0;
let mut display_device = w::DISPLAY_DEVICE::default();
loop {
let (is_good, is_active) = match w::EnumDisplayDevices(
None,
dev_num,
&mut display_device,
w::co::EDD::GET_DEVICE_INTERFACE_NAME,
) {
Ok(r) => (r, true), // active
Err(e) => match e {
w::co::ERROR::ENVVAR_NOT_FOUND => (true, false), // inactive
_ => panic!("Actual error!"),
}
};
if is_good {
// result.push(Display::from_winsafe(dev_num, &display_device)?);
println!("{}, active: {}", display_device.DeviceName(), is_active);
dev_num += 1;
} else {
break;
}
}
}
from winsafe.
When I run your code, I get an infinite loop, because is_good
is always true
.
But it should stop after there is no display anymore right? I have three active displays and one inactive. This means it should iterate five times, and since the fifth display does not exist an error ("The system could not find the environment option that was entered.") will be thrown and the code should break. This is not the case with the code you just posted.
from winsafe.
I only have three displays attached to the four DisplayPort ports on my GPU (maybe the fourth one is also some kind of virtual display output device).
This is how the API calls look in APIMonitor:
While all other displays have the active flag there, my fourth "display" shows this flag:
from winsafe.
This is very unsettling... please run the code below and post back the results:
{
use winsafe as w;
for n in 0..8 {
let mut dide = w::DISPLAY_DEVICE::default();
let ret = w::EnumDisplayDevices(
None, n, &mut dide, w::co::EDD::GET_DEVICE_INTERFACE_NAME);
match ret {
Ok(b) => println!("{} Ok {}", n, b),
Err(e) => println!("{} Err {}", n, e),
}
}
}
from winsafe.
Results in an infinite loop with the following output
0 Ok true
1 Ok true
2 Ok true
3 Ok true
4 Err [0x00cb 203] The system could not find the environment option that was entered.
5 Err [0x00cb 203] The system could not find the environment option that was entered.
6 Err [0x00cb 203] The system could not find the environment option that was entered.
7 Err [0x00cb 203] The system could not find the environment option that was entered.
0 Ok true
1 Ok true
2 Ok true
3 Ok true
4 Err [0x00cb 203] The system could not find the environment option that was entered.
5 Err [0x00cb 203] The system could not find the environment option that was entered.
6 Err [0x00cb 203] The system could not find the environment option that was entered.
7 Err [0x00cb 203] The system could not find the environment option that was entered.
0 Ok true
1 Ok true
2 Ok true
3 Ok true
4 Err [0x00cb 203] The system could not find the environment option that was entered.
5 Err [0x00cb 203] The system could not find the environment option that was entered.
6 Err [0x00cb 203] The system could not find the environment option that was entered.
7 Err [0x00cb 203] The system could not find the environment option that was entered.
0 Ok true
1 Ok true
2 Ok true
3 Ok true
4 Err [0x00cb 203] The system could not find the environment option that was entered.
5 Err [0x00cb 203] The system could not find the environment option that was entered.
6 Err [0x00cb 203] The system could not find the environment option that was entered.
7 Err [0x00cb 203] The system could not find the environment option that was entered.
0 Ok true
1 Ok true
2 Ok true
3 Ok true
4 Err [0x00cb 203] The system could not find the environment option that was entered.
5 Err [0x00cb 203] The system could not find the environment option that was entered.
6 Err [0x00cb 203] The system could not find the environment option that was entered.
7 Err [0x00cb 203] The system could not find the environment option that was entered.
0 Ok true
1 Ok true
2 Ok true
3 Ok true
4 Err [0x00cb 203] The system could not find the environment option that was entered.
5 Err [0x00cb 203] The system could not find the environment option that was entered.
6 Err [0x00cb 203] The system could not find the environment option that was entered.
7 Err [0x00cb 203] The system could not find the environment option that was entered.
0 Ok true
1 Ok true
2 Ok true
3 Ok true
4 Err [0x00cb 203] The system could not find the environment option that was entered.
5 Err [0x00cb 203] The system could not find the environment option that was entered.
6 Err [0x00cb 203] The system could not find the environment option that was entered.
7 Err [0x00cb 203] The system could not find the environment option that was entered.
0 Ok true
1 Ok true
2 Ok true
3 Ok true
4 Err [0x00cb 203] The system could not find the environment option that was entered.
5 Err [0x00cb 203] The system could not find the environment option that was entered.
6 Err [0x00cb 203] The system could not find the environment option that was entered.
7 Err [0x00cb 203] The system could not find the environment option that was entered.
0 Ok true
1 Ok true
2 Ok true
3 Ok true
4 Err [0x00cb 203] The system could not find the environment option that was entered.
5 Err [0x00cb 203] The system could not find the environment option that was entered.
6 Err [0x00cb 203] The system could not find the environment option that was entered.
7 Err [0x00cb 203] The system could not find the environment option that was entered.
0 Ok true
1 Ok true
2 Ok true
3 Ok true
4 Err [0x00cb 203] The system could not find the environment option that was entered.
from winsafe.
It's just a for
iterating from 0 to 7... it can't be an infinite loop.
Are you running this code inside something else?
from winsafe.
Agh sorry. Wanted to get back to you ASAP and got sloppy: I had another loop {} around this from code before. This code actually doesn't loop. Output is just:
0 Ok true
1 Ok true
2 Ok true
3 Ok true
4 Err [0x00cb 203] The system could not find the environment option that was entered.
5 Err [0x00cb 203] The system could not find the environment option that was entered.
6 Err [0x00cb 203] The system could not find the environment option that was entered.
7 Err [0x00cb 203] The system could not find the environment option that was entered.
The code snippet you posted earlier (before the last one) still leads to endless looping.
from winsafe.
What about this example in the docs? Does it still loop?
from winsafe.
No, it does not loop on the latest commit. However, an error is thrown:
0: \\.\DISPLAY1 - NVIDIA GeForce GTX 1080
1: \\.\DISPLAY2 - NVIDIA GeForce GTX 1080
2: \\.\DISPLAY3 - NVIDIA GeForce GTX 1080
3: \\.\DISPLAY4 - NVIDIA GeForce GTX 1080
Error:
0: [0x00cb 203] The system could not find the environment option that was entered.
0:
Location:
src\display.rs:462
The error occurs on the following line:
let is_good = EnumDisplayDevices(None, dev_num, &mut dide, co::EDD::NoValue)?;
from winsafe.
This means that when the loop ends, GetLastError
returns code 203
, which should be the stop condition.
However... on my computer, it returns code 127
instead. That's odd.
I'm on Windows 10 x64, what's yours?
from winsafe.
Win 10 Pro x64
from winsafe.
OK, so I completely removed the internal error checking, and the zero is always considered the "done" state now.
Let me know if this works for you.
from winsafe.
Output now is:
0: \\.\DISPLAY1 - NVIDIA GeForce GTX 1080
1: \\.\DISPLAY2 - NVIDIA GeForce GTX 1080
2: \\.\DISPLAY3 - NVIDIA GeForce GTX 1080
3: \\.\DISPLAY4 - NVIDIA GeForce GTX 1080
So it works!
We could also handle just 127 as well as 203 as codes for Ok(false)
.
from winsafe.
Related Issues (20)
- validate_retrieved_reg_val always fails
- [Question] - Calling windows APIs twice best practice HOT 3
- RegQueryValueEx returning TRANSACTION_REQUEST_NOT_VALID for valid data HOT 6
- nm_custom_draw should provide a mutable reference? HOT 6
- How do you envision WM_USER being used? HOT 1
- `WC::NoValue`? HOT 1
- Wrong GetAsyncKeyState return type. HOT 4
- SetLayeredWindowAttributes HOT 3
- GetTokenInformation missing HOT 2
- Panic when add empty strings in listview HOT 2
- How to display rich text such as superscript/subscript? HOT 3
- [Feature Request] Message only window support HOT 3
- [Feature Request] Implement Ord, PartialOrd, Eq and PartialEq for WString
- Public access ot LocalFreeGuard::new or LocalFree HOT 2
- [BUG?QUESTION?]SendInput example not working HOT 1
- [Question] How can I set the pszText into NMLVDISPINFO correctly when handling lvn_get_disp_info event? HOT 19
- [Question] Using MutFn as WinApi callback
- WString pointers cause issues on stack for certain API calls HOT 5
- Build fails for the i686-pc-windows-(msvc/gnu) targets HOT 8
- winsvc.h HOT 2
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from winsafe.