Подтвердить что ты не робот

Windows 10 эквивалент LaunchAdvancedAssociationUI

Начиная с Windows 10, метод IApplicationAssociationRegistrationUI::LaunchAdvancedAssociationUI больше не работает.

В Windows Vista 7 и 8 она открывает панель управления на странице "Установить ассоциации программ" для указанного приложения.

На Windows 10 это ничего не делает.

Это даже задокументировано в документации Microsoft:

Начиная с Windows 10, это не запускает диалоговое окно ассоциации. Он отображает диалоговое окно для пользователя, информирующее их о том, что они могут изменить программы по умолчанию, используемые для открытия расширений файлов в своих настройках.

(Даже вторая часть утверждения больше не верна в текущей версии Windows 10)


И на самом деле в последних версиях Windows 10 эта панель управления больше не существует. Его функциональные возможности были перенесены в приложение "Настройки" в разделе "Приложения"> "Приложения по умолчанию"> "Установить значения по умолчанию для приложения"> [Имя приложения].

enter image description here

Можно ли программным способом открыть экран "Установить настройки по умолчанию для моего приложения" в приложении "Настройки Windows 10"?

Или для приложения рекомендуется другой подход, позволяющий пользователям настраивать ассоциации в Windows 10?

4b9b3361

Ответ 1

Изменение системных приложений по умолчанию больше не разрешено. Вот аннуляция в блоге Windows Insider:

Изменения в том, как Windows 10 обрабатывает приложения по умолчанию: "Приложения по умолчанию относятся к тому, как Windows сопоставляет типы файлов и протоколы (например, HTTP) с приложениями Windows, которые они открывают по умолчанию. Например, ваш любимый редактор фотографий может быть установлен как приложение по умолчанию для файлов .JPG, а это значит, что при двойном щелчке по файлу .JPG в File Explorer он открывается в этом редакторе фотографий. В Windows 8.1 приложения Classic Windows (Win32) могут вызывать приглашение с просьбой изменить ваши значения по умолчанию, поэтому вы можете увидеть несколько запросов во время установки и после их запуска. Однако приложения Windows Store не смогли вызвать это приглашение. Вместо этого после установки ваших приложений появится баннер уведомлений, сообщающий вам, что новые приложения доступны, и вы нажмете на этот баннер, чтобы изменить настройки по умолчанию.

Мы знаем, что ваш вопрос по умолчанию имеет значение для вас. В Windows 10 все приложения - как в приложениях Classic Windows, так и в приложениях Universal Windows - не смогут вызывать приглашение изменить ваши значения по умолчанию, только Windows. Вы по-прежнему полностью контролируете свой опыт по умолчанию, одновременно уменьшая некоторые нежелательные шумы, которые могут принести несколько подсказок.

Даже если есть способ запустить приложение настроек, вы больше не сможете делать.

Ответ 2

Чтобы открыть страницу "Установка программ по умолчанию":

%windir%\system32\control.exe /name Microsoft.DefaultPrograms /page pageDefaultProgram

Ссылка: https://msdn.microsoft.com/en-us/library/windows/desktop/ee330741.aspx

Примечание. Этот метод не работает с обновлением за апрель 2018 года.


Чтобы открыть страницу "Выбор приложений по умолчанию по типу файла":

Activator->ActivateApplication(
    L"windows.immersivecontrolpanel_cw5n1h2txyewy"
    L"!microsoft.windows.immersivecontrolpanel",
    L"page=SettingsPageAppsDefaults"
    L"&target=SettingsPageAppsDefaultsFileExtensionView", AO_NONE, &pid);

Версия 1709 или позже

Чтобы открыть страницу "Установить значения по умолчанию для приложения":

Activator->ActivateApplication(
    L"windows.immersivecontrolpanel_cw5n1h2txyewy"
    L"!microsoft.windows.immersivecontrolpanel",
    L"page=SettingsPageAppsDefaults"
    L"&target=SettingsPageAppsDefaultsDefaultAppsListView", AO_NONE, &pid);

Ответ 3

  • Откройте главное окно " Программы по умолчанию" в панели управления:

    %windir%\system32\control.exe/name Microsoft.DefaultPrograms

  • Откройте страницу " Установка программ по умолчанию":

    %windir%\system32\control.exe/name Microsoft.DefaultPrograms/page pageDefaultProgram

  • Откройте страницу Установить ассоциации для страницы программы:

    %windir%\system32\control.exe/name Microsoft.DefaultPrograms/page pageDefaultProgram\pageAdvancedSettings?pszAppName=YourAppRegName

    YourAppRegName - это имя вашего зарегистрированного приложения из HKEY_LOCAL_MACHINE (или HKEY_CURRENT_USER) \ SOFTWARE\RegisteredApplications, которые должны быть экранированы (используйте UrlEscape, Luke!) Перед использованием. Например:

    %windir%\system32\control.exe/name Microsoft.DefaultPrograms/page pageDefaultProgram\pageAdvancedSettings?pszAppName=Internet%20Explorer

  • Открыть Связать тип файла или протокол со страницей программы:

    %windir%\system32\control.exe/name Microsoft.DefaultPrograms/page pageFileAssoc

  • Откройте страницу " Изменить параметры автозапуска":

    %windir%\system32\control.exe/name Microsoft.AutoPlay

  • Открыть страницу доступа к программам и компьютерам по умолчанию:

    %windir%\system32\ComputerDefaults.exe

PS Также вы можете использовать IOpenControlPanel::Open чтобы вместо этого открыть элемент/страницу панели управления:

IOpenControlPanel * OpenControlPanel;

HRESULT Result =
  CoCreateInstance(CLSID_OpenControlPanel,
    NULL, CLSCTX_INPROC, __uuidof(IOpenControlPanel), (void**)&OpenControlPanel);
if (SUCCEEDED(Result))
{
  const wchar_t * Page = L"pageDefaultProgram\\pageAdvancedSettings?pszAppName=YourAppRegName";
  OpenControlPanel->Open(L"Microsoft.DefaultPrograms", Page, NULL);
  OpenControlPanel->Release();
}

Ответ 4

Set WshShell = WScript.CreateObject("WScript.Shell")
WshShell.Run "%windir%\system32\control.exe /name Microsoft.DefaultPrograms /page pageDefaultProgram\pageAdvancedSettings?pszAppName=Internet%20Explorer"
' Give Default Programs time to load
WScript.Sleep 1200
' WshShell.AppActivate "Set Program Associations to IE then end for Windows 10 enjoy! ~ The Dogs Trust Rich ~"
WshShell.SendKeys "{TAB}"
WshShell.SendKeys " "
WshShell.SendKeys "{TAB}"
WshShell.SendKeys "{TAB}"
WshShell.SendKeys " "
msgbox "Internet Explorer is now your default browser"
WScript.Quit

Ответ 5

Мне удалось сделать это с помощью автоматизации пользовательского интерфейса. Это не идеальное решение, но, похоже, оно работает. Вот код с комментариями:

#include <stdio.h>
#include <windows.h>
#include <atlbase.h>
#include <atlcom.h>
#include <UIAutomationCore.h>
#include <UIAutomationClient.h>

// the main function
HRESULT OpenSetDefaultsByApp(LPCWSTR appName);

// helpers
HRESULT FindFirstChild(IUIAutomation *automation, IUIAutomationElement *element, PROPERTYID pid, VARIANT value, IUIAutomationElement **child);
HRESULT FindFirstChildInList(IUIAutomation *automation, IUIAutomationElement *list, PROPERTYID pid, VARIANT value, IUIAutomationElement **child);
HRESULT OpenSetDefaultsByApp();

// some useful macros for error handling
// uses wprintf so you might want to change it, if running in a non-console context
#define WIDEN2(x) L ## x
#define WIDEN(x) WIDEN2(x)
#define __WFILE__ WIDEN(__FILE__)
#define HRCHECK(__expr) {hr=(__expr);if(FAILED(hr)){wprintf(L"FAILURE 0x%08X (%i)\n\tline: %u file: '%s'\n\texpr: '" WIDEN(#__expr) L"'\n",hr, hr, __LINE__,__WFILE__);goto cleanup;}}

int main()
{
  CoInitialize(NULL);
  OpenSetDefaultsByApp(L"Google Chrome"); // pass the app name as it displayed in app settings
  CoUninitialize();
}

HRESULT OpenSetDefaultsByApp(LPCWSTR appName)
{
  HRESULT hr = S_OK;
  CComBSTR name = appName;
  CComPtr<IUIAutomation> automation;
  CComPtr<IUIAutomationElement> root;
  CComPtr<IUIAutomationElement> settingsWindow;
  CComPtr<IUIAutomationElement> coreWindow;
  CComPtr<IUIAutomationElement> content;
  CComPtr<IUIAutomationElement> list;
  CComPtr<IUIAutomationElement> scrollViewer;
  CComPtr<IUIAutomationElement> appNameListItem;
  CComPtr<IUIAutomationElement> manageButton;
  CComPtr<IUIAutomationSelectionItemPattern> selection;
  CComPtr<IUIAutomationInvokePattern> invoke;

  // because setting windows and content are completely refreshed, we need two rounds
  // one to open the list of apps
  HRCHECK(OpenSetDefaultsByApp());

  // another one to select the app that starts now...
  // create UIA COM server and get root
  HRCHECK(automation.CoCreateInstance(CLSID_CUIAutomation8));
  HRCHECK(automation->GetRootElement(&root));

  // get hierarchy one by one. This is so it doesn't take too much time
  HRCHECK(FindFirstChild(automation, root, UIA_ClassNamePropertyId, CComVariant("ApplicationFrameWindow"), &settingsWindow));
  HRCHECK(FindFirstChild(automation, settingsWindow, UIA_ClassNamePropertyId, CComVariant("Windows.UI.Core.CoreWindow"), &coreWindow));
  HRCHECK(FindFirstChild(automation, coreWindow, UIA_AutomationIdPropertyId, CComVariant("pageContent"), &content));
  HRCHECK(FindFirstChild(automation, content, UIA_AutomationIdPropertyId, CComVariant("ItemsControlScrollViewer"), &scrollViewer));

  // now the list of app should be shown, get it
  HRCHECK(FindFirstChild(automation, scrollViewer, UIA_AutomationIdPropertyId, CComVariant("SystemSettings_DefaultApps_DefaultAppsList_ListView"), &list));

  // find the item by it name
  // the list is virtualized so we use a helper method
  // note for some reason, the name is the name plus a space... 
  name.Append(" ");
  HRCHECK(FindFirstChildInList(automation, list, UIA_NamePropertyId, CComVariant(name), &appNameListItem));

  // we got the app item, select it so the 'Manage' button can appear
  HRCHECK(appNameListItem->GetCurrentPatternAs(UIA_SelectionItemPatternId, IID_PPV_ARGS(&selection)));
  if (!selection) HRCHECK(E_FAIL);
  HRCHECK(selection->Select());

  // get the 'Manage' button
  HRCHECK(FindFirstChild(automation, scrollViewer, UIA_ClassNamePropertyId, CComVariant("Button"), &manageButton));

  // press the 'Manage' button
  HRCHECK(manageButton->GetCurrentPatternAs(UIA_InvokePatternId, IID_PPV_ARGS(&invoke)));
  if (!invoke) HRCHECK(E_FAIL);
  HRCHECK(invoke->Invoke());

cleanup:
  return hr;
}

HRESULT OpenSetDefaultsByApp()
{
  HRESULT hr = S_OK;
  CComPtr<IUIAutomation> automation;
  CComPtr<IUIAutomationElement> root;
  CComPtr<IUIAutomationElement> settingsWindow;
  CComPtr<IUIAutomationElement> coreWindow;
  CComPtr<IUIAutomationElement> content;
  CComPtr<IUIAutomationElement> setDefaultsByAppLink;
  CComPtr<IUIAutomationInvokePattern> invoke;

  // create UIA COM server and get root
  HRCHECK(automation.CoCreateInstance(CLSID_CUIAutomation8));
  HRCHECK(automation->GetRootElement(&root));

  // show up to the deepest we can
  WinExec("control.exe /name Microsoft.DefaultPrograms /page pageDefaultProgram", SW_NORMAL);

  // find the 'Set defaults by app' link (button).
  HRCHECK(FindFirstChild(automation, root, UIA_ClassNamePropertyId, CComVariant("ApplicationFrameWindow"), &settingsWindow));
  HRCHECK(FindFirstChild(automation, settingsWindow, UIA_ClassNamePropertyId, CComVariant("Windows.UI.Core.CoreWindow"), &coreWindow));
  HRCHECK(FindFirstChild(automation, coreWindow, UIA_AutomationIdPropertyId, CComVariant("pageContent"), &content));
  HRCHECK(FindFirstChild(automation, content, UIA_AutomationIdPropertyId, CComVariant("SettingsPageAppsDefaultsDefaultAppsListView_HyperlinkButton"), &setDefaultsByAppLink));

  // yes, so press this button
  HRCHECK(setDefaultsByAppLink->GetCurrentPatternAs(UIA_InvokePatternId, IID_PPV_ARGS(&invoke)));
  if (!invoke) HRCHECK(E_FAIL);
  HRCHECK(invoke->Invoke());

cleanup:
  return hr;
}

// this method has retries with timeouts included, so it much better than a raw call to FindFirst
HRESULT FindFirstChild(IUIAutomation *automation, IUIAutomationElement *element, PROPERTYID pid, VARIANT value, IUIAutomationElement **child)
{
  HRESULT hr = S_OK;
  int timeout = 5000; // max timeout is defined here as 5 sec. This should be ok for most machines
  int slice = 100; // time between too retries, defined as 100 ms.
  int time = 0;
  CComPtr<IUIAutomationCondition> condition;
  HRCHECK(automation->CreatePropertyCondition(pid, value, &condition));

  do
  {
    // I used SubTree here, this may not be appropriate in all context
    // for performance issues. In fact, this could be passed as a parameter...
    hr = element->FindFirst(TreeScope_Subtree, condition, child);
    if (*child) break;
    time += slice;
    if (time >= timeout) HRCHECK(E_FAIL);
    Sleep(slice);
  } while (TRUE);

cleanup:
  return hr;
}

// this helper supports virtualized list
HRESULT FindFirstChildInList(IUIAutomation *automation, IUIAutomationElement *list, PROPERTYID pid, VARIANT value, IUIAutomationElement **child)
{
  HRESULT hr = S_OK;
  CComBSTR lastName;
  int lastNameCount = 0;
  CComPtr<IUIAutomationCondition> trueCondition;
  HRCHECK(automation->CreateTrueCondition(&trueCondition));

  do
  {
    // get all children
    CComPtr<IUIAutomationElementArray> all;
    HRCHECK(list->FindAll(TreeScope_Children, trueCondition, &all));

    int count;
    HRCHECK(all->get_Length(&count));
    if (count == 0) continue; // there shouldn't be zero element, so go on scanning

    for (int i = 0; i < count; i++)
    {
      // test each element for the searched property
      CComPtr<IUIAutomationElement> element;
      HRCHECK(all->GetElement(i, &element));

      CComVariant v;
      HRCHECK(element->GetCurrentPropertyValue(pid, &v));
      if (VarCmp(&v, &value, 0) == 1)
      {
        HRCHECK(element.QueryInterface(child));
        goto cleanup;
      }
    }

    // not found in the current page/set, go to last element and scroll it into view to force list to load the next
    CComPtr<IUIAutomationElement> last;
    CComPtr<IUIAutomationScrollItemPattern> pattern;
    HRCHECK(all->GetElement(count - 1, &last));

    // check if we didn't progress (same name for 20 rounds)
    CComBSTR name;
    HRCHECK(last->get_CurrentName(&name));
    if (name == lastName)
    {
      lastNameCount++;
      if (lastNameCount > 20) HRCHECK(E_FAIL); // not found!
    }
    else
    {
      lastNameCount = 0;
    }
    lastName = name;

    HRCHECK(last->GetCurrentPatternAs(UIA_ScrollItemPatternId, IID_PPV_ARGS(&pattern)));
    if (!pattern) HRCHECK(E_FAIL);
    HRCHECK(pattern->ScrollIntoView());
  } while (TRUE);

cleanup:
  return hr;
}