How to detect Windows 10 light/dark mode in Win32 application? - windows

A bit of context: Sciter (pure win32 application) is already capable to render UWP alike UIs:
in dark mode:
in light mode:
Windows 10.1803 introduces Dark/Light switch in Settings applet as seen here for example.
Question: how do I determine current type of that "app mode" in Win32 application?

Well, it looks like this option is not exposed to regular Win32 applications directly, however it can be set / retrieved through the AppsUseLightTheme key at the HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Themes\Personalize registry path.

The Microsoft.Windows.SDK.Contracts NuGet package gives .NET Framework 4.5+ and .NET Core 3.0+ applications access to Windows 10 WinRT APIs, including Windows.UI.ViewManagement.Settings mentioned in the answer by jarjar. With this package added to a .NET Core 3.0 console app that consists of this code:
using System;
using Windows.UI.ViewManagement;
namespace WhatColourAmI
{
class Program
{
static void Main(string[] args)
{
var settings = new UISettings();
var foreground = settings.GetColorValue(UIColorType.Foreground);
var background = settings.GetColorValue(UIColorType.Background);
Console.WriteLine($"Foreground {foreground} Background {background}");
}
}
}
The output when the theme is set to Dark is:
Foreground #FFFFFFFF Background #FF000000
When the theme is set to Light it's:
Foreground #FF000000 Background #FFFFFFFF
As this is exposed via a Microsoft provided package that states:
This package includes all the supported Windows Runtime APIs up to Windows 10 version 1903
It's a pretty safe bet that it's intentional that this API is accessible!
Note: This isn't explicitly checking whether the theme is Light or Dark but checking for a pair of values that suggest that the theme in use is one of the two, so,.. the correctness of this method is mildly questionable but it's at least a "pure" C# way of achieving what's been outlined elsewhere with C++

EDIT: Calling out that this works in all Win32 projects as long as you're building with c++17 enabled.
If you're using the latest SDK, this worked for me.
#include <winrt/Windows.UI.ViewManagement.h>
using namespace winrt::Windows::UI::ViewManagement;
if (RUNNING_ON_WINDOWS_10) {
UISettings settings;
auto background = settings.GetColorValue(UIColorType::Background);
auto foreground = settings.GetColorValue(UIColorType::Foreground);
}

To add to the solution suggested by #user7860670, i.e: checking the registry key AppsUseLightTheme, I think it is worth having some code example.
To read from the registry Win32 has RegGetValue.
C++
bool is_light_theme() {
// based on https://stackoverflow.com/questions/51334674/how-to-detect-windows-10-light-dark-mode-in-win32-application
// The value is expected to be a REG_DWORD, which is a signed 32-bit little-endian
auto buffer = std::vector<char>(4);
auto cbData = static_cast<DWORD>(buffer.size() * sizeof(char));
auto res = RegGetValueW(
HKEY_CURRENT_USER,
L"Software\\Microsoft\\Windows\\CurrentVersion\\Themes\\Personalize",
L"AppsUseLightTheme",
RRF_RT_REG_DWORD, // expected value type
nullptr,
buffer.data(),
&cbData);
if (res != ERROR_SUCCESS) {
throw std::runtime_error("Error: error_code=" + std::to_string(res));
}
// convert bytes written to our buffer to an int, assuming little-endian
auto i = int(buffer[3] << 24 |
buffer[2] << 16 |
buffer[1] << 8 |
buffer[0]);
return i == 1;
}
Rust
Using the windows-rs projection crate:
pub fn is_light_theme() -> bool {
// based on https://stackoverflow.com/a/51336913/709884
let mut buffer: [u8; 4] = [0; 4];
let mut cb_data: u32 = (buffer.len()).try_into().unwrap();
let res = unsafe {
RegGetValueW(
HKEY_CURRENT_USER,
r#"Software\Microsoft\Windows\CurrentVersion\Themes\Personalize"#
.to_wide()
.as_pwstr(),
"AppsUseLightTheme".to_wide().as_pwstr(),
RRF_RT_REG_DWORD,
std::ptr::null_mut(),
buffer.as_mut_ptr() as _,
&mut cb_data as *mut _,
)
};
assert_eq!(
res,
ERROR_SUCCESS,
format!("failed to read key from registry: err_code={}", res).as_str(),
);
// REG_DWORD is signed 32-bit, using little endian
let light_mode = i32::from_le_bytes(buffer) == 1;
light_mode
}
pub fn is_dark_theme() -> bool {
!is_light_theme()
}
// convert &str to Win32 PWSTR
#[derive(Default)]
pub struct WideString(pub Vec<u16>);
pub trait ToWide {
fn to_wide(&self) -> WideString;
}
impl ToWide for &str {
fn to_wide(&self) -> WideString {
let mut result: Vec<u16> = self.encode_utf16().collect();
result.push(0);
WideString(result)
}
}
impl ToWide for String {
fn to_wide(&self) -> WideString {
let mut result: Vec<u16> = self.encode_utf16().collect();
result.push(0);
WideString(result)
}
}
impl WideString {
pub fn as_pwstr(&self) -> PWSTR {
PWSTR(self.0.as_ptr() as *mut _)
}
}

Here is a C# solution for the answer of #user7860670
using Microsoft.Win32;
try
{
int res = (int)Registry.GetValue("HKEY_CURRENT_USER\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Themes\\Personalize", "AppsUseLightTheme", -1);
}
catch
{
//Exception Handling
}
res contains the value for the default theme on windows
0 : dark theme
1 : light theme
-1 : AppsUseLightTheme could not be found

Related

Linking fails with undefined references to wgl functions of the Windows API for OpenGL in Kotlin

When I was trying out OpenGL context-creation with the Windows API and Kotlin, an error occurred when the linking task was executed. I posted the output of that task on pastebin (expires in a month) and these two lines of the output stand out:
... undefined reference to '__imp_wglCreateContext'
... undefined reference to '__imp_wglMakeCurrent'
For every wgl function I use, clang (the LLVM compiler frontend) prints such lines. Compiling works fine, but when it comes to linking, the task either fails (Kotlin 1.3.71) or never ends with nothing happening (Kotlin 1.4-M1).
Note that this is not a runtime problem and any other Windows API function works correctly and also that Kotlin provides bindings for the wgl functions.
If all wgl functions get removed, the following code I made compiles and links fine and a blank window gets produced as expected (comment out wgl functions):
import kotlinx.cinterop.*
import platform.windows.*
#OptIn(ExperimentalUnsignedTypes::class)
fun main() {
memScoped {
val className = "OpenGLLinkErrorDemo"
// create an instance of the window class
val wc = cValue<WNDCLASS> {
lpfnWndProc = staticCFunction { hwnd, uMsg, wParam, lParam ->
when (uMsg) {
WM_DESTROY.toUInt() -> {
PostQuitMessage(0)
0
}
WM_PAINT.toUInt() -> {
memScoped {
val ps = alloc<PAINTSTRUCT>()
val hdc = BeginPaint(hwnd, ps.ptr)
val brush = alloc<HBRUSH__> {
unused = COLOR_WINDOW + 1
}
FillRect(hdc, ps.rcPaint.ptr, brush.ptr)
EndPaint(hwnd, ps.ptr)
}
0
}
else -> DefWindowProc!!(hwnd, uMsg, wParam, lParam)
}
}
hInstance = GetModuleHandle!!(null)
lpszClassName = className.wcstr.ptr
}
// register the window class instance
RegisterClass!!(wc.ptr)
val hwnd = CreateWindowEx!!(
0u, // optional window styles
className.wcstr.ptr, // window class
className.wcstr.ptr, // window text
CS_OWNDC.toUInt(), // window style (this one in particular is needed for OpenGL)
// size and position
CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
null, // parent window
null, // menu
GetModuleHandle!!(null), // instance handle
null // additional application data
)
?: throw RuntimeException("Failed to create window")
// create a pixelformat descriptor with opengl compatible settings
val pfd = alloc<PIXELFORMATDESCRIPTOR> {
nSize = sizeOf<PIXELFORMATDESCRIPTOR>().toUShort()
nVersion = 1u
dwFlags = (PFD_DRAW_TO_WINDOW or PFD_SUPPORT_OPENGL or PFD_DOUBLEBUFFER).toUInt()
iPixelType = PFD_TYPE_RGBA.toUByte()
cColorBits = 32u
cRedBits = 0u; cRedShift = 0u; cGreenBits = 0u; cGreenShift = 0u; cBlueBits = 0u; cBlueShift = 0u; cAlphaBits = 0u; cAlphaShift = 0u
cAccumBits = 0u
cAccumRedBits = 0u; cAccumGreenBits = 0u; cAccumBlueBits = 0u; cAccumAlphaBits = 0u
cDepthBits = 24u
cStencilBits = 8u
cAuxBuffers = 0u
iLayerType = PFD_MAIN_PLANE.toUByte()
bReserved = 0u
dwLayerMask = 0u; dwVisibleMask = 0u; dwDamageMask = 0u
}
SetPixelFormat(GetDC(hwnd), ChoosePixelFormat(GetDC(hwnd), pfd.ptr), pfd.ptr)
// the source of evil. using the function to create an opengl context, but the linker doesn't know the wgl functions
val openGLContext = wglCreateContext(GetDC(hwnd)) ?: throw RuntimeException("Failed to create OpenGL context")
wglMakeCurrent(GetDC(hwnd), openGLContext)
ShowWindow(hwnd, 1)
// run the message loop
val msg = alloc<MSG>()
while (GetMessage!!(msg.ptr, null, 0u, 0u) == 1) {
TranslateMessage(msg.ptr)
DispatchMessage!!(msg.ptr)
}
}
}
So I checked the documentations and of course this requires the OpenGL library to work. But any other OpenGL function from the platform.opengl32 package works and because Kotlin checks at compilation which libraries are used and includes them automatically, everything should have worked fine. However, clang still didn't like it and couldn't find the implementations for the wgl functions.
Then I searched the internet for any solutions, and a few people had the same output, but their cases weren't entirely like mine and I didn't find anyone who tried OpenGL context-creation with Kotlin at all
(I know it might not be the best choice to use a high-level language for something like this and that I could have used another library for what I'm trying to accomplish, but I want to see how much Kotlin is able to do).
Next I checked if the Kotlin issue tracker has something about this already (nope) and the LLVM version Kotlin uses and the LLVM changelogs if they say anything about that (nope, and I know it doesn't make much sense, but you never know), so I figured that the problem must be on my side.
I came up with the following possible causes:
I am using the wrong version of OpenGL (should be the latest one for my graphics card, I updated my graphics driver)
I need to do something extra with dependencies
I am using deprecated API
I am too dumb
I am out of luck, and it just doesn't work on my PC
Those are all the things I didn't check yet because I couldn't, so of course I don't know if any them are true. I've been trying to get this to work for a couple of days now, so now I seek help or advice. Maybe someone could try to compile this too. The following script is the necessary build script for gradle:
#file:Suppress("UNUSED_VARIABLE")
plugins {
kotlin("multiplatform") version "1.3.71"
}
repositories {
mavenCentral()
}
kotlin {
mingwX64("openGLErrorDemo") {
binaries {
executable {
entryPoint = "main"
}
}
val main by compilations.getting {
kotlinOptions {
freeCompilerArgs = listOf("-Xopt-in=kotlin.RequiresOptIn")
}
}
}
sourceSets {
val commonMain by getting {
dependencies {
implementation(kotlin("stdlib-common"))
}
}
}
}
Put that script in a file called build.gradle.kts, then create the following folder structure next to it:
src
\- openGLErrorDemoMain
\- kotlin
and put a *.kt file in the kotlin folder with the first code shown. Then run the :runReleaseExecutableOpenGLErrorDemo task and see if it compiles and links, then try commenting the wgl function calls out and running it again. This was built using the latest versions of IntelliJ and Gradle.
Of course if anyone knows what the problem is, let me know, or comment if you need more information. And please also tell me what the result of compiling the above code was.
Thanks in advance!

Does the Phoenix framework support Windows authentication?

Our web apps are currently in C# running on Windows and IIS. We rely heavily on the Windows authentication scheme that is included in this environment. With Windows authentication enabled we can detect the identity of the connected user and perform authorization on what screens and operation they are able to use.
If I set up a Phoenix web application will it be possible to detect the identity of the connected user based on their current Windows login? If not is there an easy to use replacement for the Windows authentication?
I just did this over the weekend. Yes, it is possible. You have to use the HttpPlatformHandler add-on for IIS to make it work. HttpPlatformHandler has the forwardWindowsAuthToken configuration setting that you can use to forward the Windows user token for the authenticated user from IIS to your Phoenix application which is running as a child process. You have to use NIFs to process the token and get the Windows username or SID. As you'll note from the docs, you need to call CloseHandle to release the Windows user token for each request.
(I apologize in advance if the code below is not up to best practices. I'm new to Elixir and am actively trying to learn how to write better code. This was also from a hacking session trying to figure out the solution this weekend, so it's also not necessarily polished either.)
To do this, I packaged everything into a custom plug that I could put into the pipeline (I removed Logger statements to compress the size of the example):
defmodule MyApp.WindowsAuthentication do
import Plug.Conn
require Logger
#on_load :load_nifs
def load_nifs do
if match? {:win32, _}, :os.type do
:erlang.load_nif("./priv/windows_authentication", 0)
else
:ok
end
end
def init(options), do: options
def call(conn, _options) do
if match? {:win32, _}, :os.type do
case get_req_header(conn, "x-iis-windowsauthtoken") do
[token_handle_string] ->
# token_handle_string is a hex string
token_handle = String.to_integer(token_handle_string, 16)
case do_get_windows_username(token_handle) do
{:ok, {domain_name, username}} ->
conn = assign(conn, :windows_user, {domain_name, username})
error ->
Logger.error IO.inspect(error)
end
do_close_handle(token_handle)
[] ->
Logger.debug "X-IIS-WindowsAuthToken was not present"
end
end
conn
end
def do_get_windows_username(_token_handle) do
raise "do_get_windows_username/1 is only available on Windows"
end
def do_close_handle(_handle) do
raise "do_close_handle/1 is only available on Windows"
end
end
The C source code for the NIFs is below:
#include <Windows.h>
#include <erl_nif.h>
static const char* error_atom = "error";
static const char* invalid_token_handle_atom = "invalid_token_handle";
static const char* ok_atom = "ok";
static const char* win32_error_atom = "win32_error";
#define MAX_NAME 256
static HANDLE get_user_token(ErlNifEnv *env, ERL_NIF_TERM token) {
HANDLE token_handle;
if (!enif_get_ulong(env, token, (unsigned long *)&token_handle)) {
return NULL;
}
return token_handle;
}
static ERL_NIF_TERM make_win32_error_tuple(ErlNifEnv* env, DWORD error_code) {
return enif_make_tuple2(
env,
enif_make_atom(env, error_atom),
enif_make_ulong(env, error_code)
);
}
static ERL_NIF_TERM make_invalid_token_handle_error(ErlNifEnv* env) {
return enif_make_tuple2(
env,
enif_make_atom(env, error_atom),
enif_make_atom(env, invalid_token_handle_atom)
);
}
static ERL_NIF_TERM do_get_windows_username(ErlNifEnv* env, int argc, ERL_NIF_TERM argv[]) {
HANDLE token_handle;
DWORD token_user_length;
PTOKEN_USER token_user;
DWORD last_error;
WCHAR username[MAX_NAME];
DWORD username_length = MAX_NAME;
WCHAR domain_name[MAX_NAME];
DWORD domain_name_length = MAX_NAME;
size_t converted_chars;
char converted_username[MAX_NAME * 2];
char converted_domain_name[MAX_NAME * 2];
errno_t err;
BOOL succeeded;
SID_NAME_USE sid_name_use;
token_handle = get_user_token(env, argv[0]);
if (!token_handle) {
return make_invalid_token_handle_error(env);
}
if (!GetTokenInformation(token_handle, TokenUser, NULL, 0, &token_user_length)) {
last_error = GetLastError();
if (ERROR_INSUFFICIENT_BUFFER != last_error) {
return make_win32_error_tuple(env, last_error);
}
}
token_user = (PTOKEN_USER)malloc(token_user_length);
if (!GetTokenInformation(token_handle, TokenUser, token_user, token_user_length, &token_user_length)) {
free(token_user);
return make_win32_error_tuple(env, GetLastError());
}
succeeded = LookupAccountSidW(
NULL,
token_user->User.Sid,
username,
&username_length,
domain_name,
&domain_name_length,
&sid_name_use);
if (!succeeded) {
free(token_user);
return make_win32_error_tuple(env, GetLastError());
}
err = wcstombs_s(&converted_chars, converted_username, 512, username, username_length);
err = wcstombs_s(&converted_chars, converted_domain_name, 512, domain_name, domain_name_length);
free(token_user);
return enif_make_tuple2(
env,
enif_make_atom(env, ok_atom),
enif_make_tuple2(
env,
enif_make_string(env, converted_domain_name, ERL_NIF_LATIN1),
enif_make_string(env, converted_username, ERL_NIF_LATIN1)
)
);
}
static ERL_NIF_TERM do_close_handle(ErlNifEnv* env, int argc, ERL_NIF_TERM argv[]) {
HANDLE token_handle;
token_handle = get_user_token(env, argv[0]);
if (!token_handle) {
return make_invalid_token_handle_error(env);
}
if (!CloseHandle(token_handle)) {
return make_win32_error_tuple(env, GetLastError());
}
return enif_make_atom(env, ok_atom);
}
static ErlNifFunc nif_functions[] = {
{ "do_close_handle", 1, do_close_handle },
{ "do_get_windows_username", 1, do_get_windows_username }
};
ERL_NIF_INIT(
Elixir.MyApp.WindowsAuthentication,
nif_functions,
NULL,
NULL,
NULL,
NULL
)
You can compile the C code using the 64-bit Visual Studio C++ tools (open the x64 VS command prompt). I tried this out with the new VS2017 tools. Put the DLL in the priv directory of your application.
cl /LD /I "C:\Program Files\erl-8.2\erts-8.2\include" /DDEBUG windows_authentication.c advapi32.lib
To run the plug, add it to your pipeline in web/router.ex:
pipeline :browser do
plug :accepts, ["html"]
plug MyApp.WindowsAuthentication
plug :fetch_session
plug :fetch_flash
plug :protect_from_forgery
plug :put_secure_browser_headers
end
The end result of this is that conn.assigns.windows_user will contain a tuple of the form {domain_name, username} that has the Windows domain username for the authenticated user.
Note: When I was trying this, I found CPU and memory leak issues from erl.exe when running as a child process of IIS. I'm still trying to figure that out in case you see it. I posted a question about it here.
I'll probably release this as a library on hex.pm when I've cleaned it up and fixed the memory/CPU issue, but for now, here's the code that will let you use Windows authentication with Phoenix.

Developing iTunes like application in c#

I need to develop an application in c# that could automatically detect an iPhone when it is connected to the system and read a particular file for the iPhone file system. I basically want this file to be downloaded automatically from device to the PC. I used USBpcap tool that suggests that iTunes connects to phone using some XML format. Any help or insight greatly appreciated. Is there any documentation of Third party APIs that can get me started? There are some applications that can replicate iTunes functionality e.g Copytrans
Is there any protocol or APIs provided by Apple?
I have been digging the internet and found this link Layered communication for iPhone.
Also I am using the LibUsbDotNet libraries for communicating to the usb device(Example). Can any one suggest which EndPoints should be used.
It seems to me that I have to implement usbmuxd in windows application. It is a multilayer protocol. There must be some libraries that implement usbmuxd(I dont think I have to implement the protocol all by my self)
I dont have much idea about iTunes communication as well as USB communication. I am adding as much information as I can(of course with the things I come up with in my R&D). Any help is highly appreciated.
public static DateTime LastDataEventDate = DateTime.Now;
public static UsbDevice MyUsbDevice;
#region SET YOUR USB Vendor and Product ID!
public static UsbDeviceFinder MyUsbFinder = new UsbDeviceFinder(1452, 4768);
#endregion
private void LibUSB()
{
ErrorCode ec = ErrorCode.None;
try
{
// Find and open the usb device.
MyUsbDevice = UsbDevice.OpenUsbDevice(MyUsbFinder);
// If the device is open and ready
if (MyUsbDevice == null)
throw new Exception("Device Not Found.");
// If this is a "whole" usb device (libusb-win32, linux libusb)
// it will have an IUsbDevice interface. If not (WinUSB) the
// variable will be null indicating this is an interface of a
// device.
IUsbDevice wholeUsbDevice = MyUsbDevice as IUsbDevice;
if (!ReferenceEquals(wholeUsbDevice, null))
{
// This is a "whole" USB device. Before it can be used,
// the desired configuration and interface must be selected.
// Select config #1
wholeUsbDevice.SetConfiguration(1);
// Claim interface #0.
wholeUsbDevice.ClaimInterface(0);
}
// open read endpoint 1.
UsbEndpointReader reader = MyUsbDevice.OpenEndpointReader(ReadEndpointID.Ep03);
// open write endpoint 1.
UsbEndpointWriter writer = MyUsbDevice.OpenEndpointWriter(WriteEndpointID.Ep02);
int bytesWritten;
ec = writer.Write(usbmux_header.GetBytes(), 2000, out bytesWritten);
if (ec != ErrorCode.None)
throw new Exception(UsbDevice.LastErrorString);
byte[] readBuffer = new byte[1024];
while (ec == ErrorCode.None)
{
int bytesRead;
// If the device hasn't sent data in the last 100 milliseconds,
// a timeout error (ec = IoTimedOut) will occur.
ec = reader.Read(readBuffer, 10000, out bytesRead);
if (ec == ErrorCode.Win32Error)
throw new Exception("port not open");
if (bytesRead == 0)
throw new Exception("No more bytes!");
// Write that output to the console.
Console.Write(Encoding.Default.GetString(readBuffer, 0, bytesRead));
}
}
catch (Exception ex)
{
Console.WriteLine();
Console.WriteLine((ec != ErrorCode.None ? ec + ":" : String.Empty) + ex.Message);
}
finally
{
if (MyUsbDevice != null)
{
if (MyUsbDevice.IsOpen)
{
// If this is a "whole" usb device (libusb-win32, linux libusb-1.0)
// it exposes an IUsbDevice interface. If not (WinUSB) the
// 'wholeUsbDevice' variable will be null indicating this is
// an interface of a device; it does not require or support
// configuration and interface selection.
IUsbDevice wholeUsbDevice = MyUsbDevice as IUsbDevice;
if (!ReferenceEquals(wholeUsbDevice, null))
{
// Release interface #0.
wholeUsbDevice.ReleaseInterface(0);
}
MyUsbDevice.Close();
}
MyUsbDevice = null;
// Free usb resources
UsbDevice.Exit();
}
}
}
class usbmux_header
{
public static UInt32 length = 10; // length of message, including header
public static UInt32 reserved = 0; // always zero
public static UInt32 type = 3; // message type
public static UInt32 tag = 2; // responses to this query will echo back this tag
public static byte[] GetBytes()
{
byte[] lgth = BitConverter.GetBytes(length);
byte[] res = BitConverter.GetBytes(reserved);
byte[] tpe = BitConverter.GetBytes(type);
byte[] tg = BitConverter.GetBytes(tag);
byte[] retArray = new byte[16];
lgth.CopyTo(retArray, 0);
res.CopyTo(retArray, 4);
tpe.CopyTo(retArray, 8);
tg.CopyTo(retArray, 12);
return retArray;
}
};
I have been trying to send hello packet bytes to iPhone but I am not able to read any response from phone.
To play with ipod you can use SharePodLib
As I understand it, only one client can use the USB connection to iOS at one time. On both macOS and Windows, that one client is usbmux. That library multiplexes TCP connections with higher-level clients, including iTunes, Photos, and (on macOS) the open-source peertalk library.
So on Windows, you wouldn't want to implement your own usbmux, but rather a client that sits on top of that, analogous to peertalk. I haven't seen anything open-source that does this, but a number of developers have accomplished it with their own proprietary software.
If anybody else has pointers about using usbmux on Windows, I'd love to hear about it.
—Dave
You can use imobiledevice-net. It provides a C# API to connect to iOS devices using your PC.
For example, to list all iOS devices connected to your PC, you would run something like this:
ReadOnlyCollection<string> udids;
int count = 0;
var idevice = LibiMobileDevice.Instance.iDevice;
var lockdown = LibiMobileDevice.Instance.Lockdown;
var ret = idevice.idevice_get_device_list(out udids, ref count);
if (ret == iDeviceError.NoDevice)
{
// Not actually an error in our case
return;
}
ret.ThrowOnError();
// Get the device name
foreach (var udid in udids)
{
iDeviceHandle deviceHandle;
idevice.idevice_new(out deviceHandle, udid).ThrowOnError();
LockdownClientHandle lockdownHandle;
lockdown.lockdownd_client_new_with_handshake(deviceHandle, out lockdownHandle, "Quamotion").ThrowOnError();
string deviceName;
lockdown.lockdownd_get_device_name(lockdownHandle, out deviceName).ThrowOnError();
deviceHandle.Dispose();
lockdownHandle.Dispose();
}

Looking for a reliable mapping of Forms.Screen.DeviceName to Monitor EDID info

I'm developing an application which will display information derived from the EDID blocks (monitor model, ID, S/N, etc.) on a dialog on the corresponding monitor.
This code works for finding the EDID information for displays. It extracts the EDID information by enumerating the DISPLAY keys under HKLM\SYSTEM\CurrentControlSet\Enum\DISPLAY\[Monitor]\[PnPID]\Device Parameters\EDID.
Update: The above code is relying on "side effects" of PnP use of the registry. I am now using the SetupAPI to enumerate monitors, which correctly handles monitors being attached/removed (unlike the code from the link above.)
I am trying to correlate each Screen in Windows.Forms.Screen.AllScreens[] (\\.\DISPLAY1, \\.\DISPLAY2, etc.) with the entries returned from the above registry inspection.
Note: In the code block below, DisplayDetails.GetMonitorDetails() has now been replaced with more robust registry enumeration code using the SetupAPI, but the data returned is the same.
e.g.
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 );
}
}
Output:
Info: Model: DELL P2411H, MonitorID: DELA06E, PnPID: 5&2e2fefea&0&UID1078018, Serial#:F8NDP0C...PU
Does this correlate to Screen: \\.\DISPLAY1?
Info: Model: DELL P2411H, MonitorID: DELA06E, PnPID: 5&2e2fefea&0&UID1078019, Serial#:F8NDP0C...AU
Does this correlate to Screen: \\.\DISPLAY2?
Answer: NO
In testing, I've found these don't reliably correlate (I have a system in which the first display enumerated is \\.\DISPLAY2).
My Question:
Is there a way to reliably get the EDID information for a given Forms.Screen? I can get the EDID block, but have found no path to correlate this up to the UI top-level Form. Prompting the user is undesirable, as in my use case the two (or more) monitors will likely be the same model and resolution, and only differ by a few digits in the S/N.
I've looked for paths following the Forms.Screen API, Win32 EnumDisplay, other registry GUIDs (PnP and driver-related), but haven't found any promising paths.
I have also investigated the WMI Win32_DesktopMonitor API (Windows 7), however it doesn't appear to have any more information that would help me correlate it to the Windows.Forms.Screen.AllScreens[] entries.
I suspect if there is a way to do this, it's through the SetupAPI, however I haven't found it yet.
A method to resolve the GDI to SetupAPI is available in the EnumDisplayDevices API. If you pass in the EDD_GET_DEVICE_INTERFACE_NAME in for dwFlags, the monitor enumeration will return DeviceID information of the form:
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}
The DeviceID fields now match the results from the didd.DevicePath, as retrieved in the C# fragment below:
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);
}
Sample Output:
InstanceID: DISPLAY\DELA06E\5&2E2FEFEA&0&UID1078018
DevicePath: \\?\display#dela06e#5&2e2fefea&0&uid1078018#{e6f07b5f-ee97-4a90-b076-33f57bf4eaa7}
The DeviceName from the original EnumDisplayDevices matches the Forms.Screen.DeviceName property.
With these two pieces of information, it is now possible to read the EDID block during the SetupDIEnumDeviceInterface traversal using a fragment like the below:
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;
}
Which, finally, can be parsed for the VESA descriptor blocks, as shown in the DisplayDetails.GetMonitorDetails() method in this code.

check internet connection in cocoa application

How do I check internet connection in an OS X cocoa application?
Can Apple's iOS Reachability example code be reused for this purpose?
Thanks,
Nava
The current version of Reachability code (2.2) listed on Apple's site and referenced above does NOT compile as-is for a Mac OS X Cocoa application. The constant kSCNetworkReachabilityFlagsIsWWAN is only available when compiling for TARGET_OS_IPHONE and Reachability.m references that constant. You will need to #ifdef the two locations in Reachability.m that reference it like below:
#if TARGET_OS_IPHONE
(flags & kSCNetworkReachabilityFlagsIsWWAN) ? 'W' : '-',
#else
0,
#endif
and
#if TARGET_OS_IPHONE
if ((flags & kSCNetworkReachabilityFlagsIsWWAN) == kSCNetworkReachabilityFlagsIsWWAN)
{
// ... but WWAN connections are OK if the calling application
// is using the CFNetwork (CFSocketStream?) APIs.
retVal = ReachableViaWWAN;
}
#endif
This code will help you to find if internet is reachable or not:
-(BOOL)isInternetAvail
{
BOOL bRet = FALSE;
const char *hostName = [#"google.com" cStringUsingEncoding:NSASCIIStringEncoding];
SCNetworkConnectionFlags flags = 0;
if (SCNetworkCheckReachabilityByName(hostName, &flags) && flags > 0)
{
if (flags == kSCNetworkFlagsReachable)
{
bRet = TRUE;
}
else
{
}
}
else
{
}
return bRet;
}
For more information you can look at the iphone-reachability
Unicorn's solution is deprecated, but you can get equivalent results using the following code:
SCNetworkReachabilityRef target;
SCNetworkConnectionFlags flags = 0;
Boolean ok;
target = SCNetworkReachabilityCreateWithName(NULL, hostName);
ok = SCNetworkReachabilityGetFlags(target, &flags);
CFRelease(target);
Apple has a nice code which does it for you. You can check if your connection is WiFi for instnace or just cell/WiFi.
link text
I know this is an old thread but for anyone running into this in 2018, there's an simpler and quicker solution using a Process and the ping command.
Swift 4 example:
func ping(_ host: String) -> Int32 {
let process = Process.launchedProcess(launchPath: "/sbin/ping", arguments: ["-c1", host])
process.waitUntilExit()
return process.terminationStatus
}
let internetAvailable = ping("google.com") == 0
print("internetAvailable \(internetAvailable)")

Resources