3

Even though there are command-line commands to start (most of?) the various Control Panel screens in Windows 10, a specific scenario seems to fail:

If the machine starts with Bluetooth turned off (not disabled), running the command which should open the Bluetooth settings screen, simply does nothing. The command could be either ms-settings:bluetooth, bthprops.cpl or ms-settings:Bluetooth.

I've also tried to directly launch the Bluetooth Devices screen (using the command %windir%\explorer.exe shell:::{28803F59-3A75-4058-995F-4EE5503B023C} as described here), but clicking on the "Bluetooth settings" in this window does nothing as well.

The only way to get directly to the Bluetooth settings screen without going through the main Control Panel window and without turning on Bluetooth first, is by right clicking on the relevant tile in Windows Action Center:

Right click on Bluetooth panel in Windows Action Center

Although this seems like a bug on the operating system level, I was wondering if there's any way to know when the launch fails from within C# code. So I've tried using the following code:

try
{
    var process = new Process();
    process.StartInfo.FileName = "control";
    process.StartInfo.Arguments = "bthprops.cpl";
    process.Exited += (s, e) =>
    {
        if (process.ExitCode != 0)
        {
            TurnOnBt();
        }
    };
    var res = process.Start();
    if (!res)
    {
        TurnOnBt();
    }
}
catch (System.Exception ex)
{
    int test = 6; // just for breakpoint
}

Problem is, no exception was ever thrown, and most of the time the Process.Exit event was never called.

Further more, calling Windows.Devices.Radios.Radio.GetRadiosAsync() returns an empty list!

Currently the only solution I've found is to manually turn on Bluetooth - it wouldn't change the Process.Start/Exit behavior, but it does allow to successfully lunch the command to directly open Bluetooth Settings window, and to get the list of the machine's Bluetooth/Radio devices. Still, when turning off Bluetooth and restarting the machine, same problem would happen all over again.

Any ideas for a code-based workaround?

Yoav Feuerstein
  • 1,765
  • 2
  • 20
  • 47
  • The appropriate tool to have the shell display its dialogs is [ShellExecuteEx](https://msdn.microsoft.com/en-us/library/windows/desktop/bb762154.aspx). As an added bonus, this API call returns error codes. – IInspectable Aug 01 '17 at 10:11
  • `control bthprops.cpl` successfully start (so you and not got any errors) launch `rundll32.exe Shell32.dll,Control_RunDLL bthprops.cpl,` and and exit without errors. the `Control_RunDLL` load `bthprops.cpl` and call [`CPlApplet( 0, CPL_INIT, 0, 0)`](https://msdn.microsoft.com/en-us/library/windows/desktop/bb787978(v=vs.85).aspx). the `CPlApplet` query status of service `bthserv` - if it not running - false returning and story end. the `bthprops.cpl` not want work if `bthserv` not running – RbMm Aug 01 '17 at 11:06
  • @RbMm thanks! could you please share which tools you've used to get this flow? Also, how is that different from what happens when clicking on the Action Center? – Yoav Feuerstein Aug 01 '17 at 11:15
  • @IInspectable I've tried adding **process.StartInfo.UseShellExecute = true;** as explained [here](https://stackoverflow.com/a/258420/997940), but that didn't affect anything. I'm not sure if using Dllimport (like [here](https://social.msdn.microsoft.com/Forums/vstudio/en-US/1c96756b-ea5a-4dc7-8aca-543cd7c7eddb/shellexecute-in-c?forum=csharpgeneral))would make a difference? – Yoav Feuerstein Aug 01 '17 at 11:17
  • i use debugger. unfortunately even if you direct call `Control_RunDLLW(HWND_DESKTOP, (HINSTANCE)&__ImageBase, L"bthprops.cpl", SW_SHOWDEFAULT);` from own process (this is what happens, but inside rundll32 when you exec `control bthprops.cpl` ) - you not got any errors. nothing. `bthprops.cpl` when got `CPL_INIT` message check are `BTHSERV` running (via `BthpIsbluetoothServiceRunning`) and if service not running return 0 (fail) – RbMm Aug 01 '17 at 11:29
  • @RbMm thanks again! Still, there should be another way, as I said in the original post - could you perhaps track the way the Action Center is launching the same BT-settings window? Or tell me which exact tools you've used to track down this flow so I could do it myself? Thanks :) – Yoav Feuerstein Aug 02 '17 at 08:11

1 Answers1

0

note - all this based only on my debugging research, nothing from this is documented


i look how BT-settings window is open via Action Center (win8.1, win 10):

the IApplicationActivationManager interface created and called ActivateApplication method with:

appUserModelId = L"windows.immersivecontrolpanel_cw5n1h2txyewy!microsoft.windows.immersivecontrolpanel"

arguments = L"page=SettingsPagePCSystemBluetooth"

code on c++ can be look like:

if (0 <= CoInitialize(0))
{
    IApplicationActivationManager* pAppAct;
    if (0 <= CoCreateInstance(__uuidof(ApplicationActivationManager), 0, CLSCTX_ALL, IID_PPV_ARGS(&pAppAct)))
    {
        ULONG dwProcessId;
        pAppAct->ActivateApplication(
            L"windows.immersivecontrolpanel_cw5n1h2txyewy!microsoft.windows.immersivecontrolpanel", 
            L"page=SettingsPagePCSystemBluetooth", 
            AO_NONE , 
            &dwProcessId);
        pAppAct->Release();
    }
    CoUninitialize();
}

the processId (if all ok) reference to "X:\Windows\ImmersiveControlPanel\SystemSettings.exe" -ServerName:microsoft.windows.immersivecontrolpanel

for c# - look IApplicationActivationManager::ActivateApplication in C#?

the "windows.immersivecontrolpanel_cw5n1h2txyewy!microsoft.windows.immersivecontrolpanel" and "page=SettingsPagePCSystemBluetooth" strings not documented anywhere and I not sure are it is "persist" - but currently it used to open manage Bluetooth page in system settings. as is.


in case we run control.exe bthprops.cpl - the process ( control.exe ) launched without any error - as result you and not got any errors when you call this code.

then control.exe bthprops.cpl exec new process rundll32.exe Shell32.dll,Control_RunDLL bthprops.cpl, and exit

the rundll32.dll call Control_RunDLLW(HWND_DESKTOP, (HINSTANCE)&__ImageBase, L"bthprops.cpl", SW_SHOWDEFAULT);

we can and direct call void WINAPI Control_RunDLLW(HWND hwndParent, HINSTANCE hInst, PCWSTR cplName, int nCmdShow ); this api exported from shell32.dll

internally Control_RunDLLW load "bthprops.cpl" (3-rd argument - cplName), find CPlApplet entry point, and send CPL_INIT message. the bthprops.cpl on this message check are bthserv is running via OpenService(L"BTHSERV", ) + QueryServiceStatus (in function BthpIsbluetoothServiceRunning) and if "BTHSERV" not running - it return zero (fail code)

RbMm
  • 25,803
  • 2
  • 21
  • 40
  • Please provide links to reference documentation, or explicitly mark the respective constants and function calls as *"inofficial"* and/or *"unsupported"*. – IInspectable Aug 03 '17 at 00:27
  • @IInspectable - you mean `Control_RunDLLW` ? it not formal documented. however in this part I only explain what happens when we run `control bthprops.cpl` - why this can have no visible effect (if `bthserv` not running) and no errors returned. about `windows.immersivecontrolpanel_cw5n1h2txyewy!microsoft.windows.immersivecontrolpanel` - it also of course not documented. but I wrote - `i look how BT-settings window is open via Action Center:` - so this is only my debugging research – RbMm Aug 03 '17 at 00:40