Как включить api windows

Обновлено: 03.07.2024

Иногда вы можете столкнуться с ошибкой отсутствия api-ms-win-crt-runtime-l1-1-0.dll при попытке запустить или открыть программу или файл на вашем компьютере с Windows 10, что мешает вам открывать определенные программы и выполнять определенные задачи.

Что делать если запуск невозможен api-ms-win-crt

Давайте сначала проверим, установлен ли распространяемый пакет Microsoft Visual C++ 2015 на вашем компьютере.

Скачайте api-ms-win-crt-runtime-l1–1–0.dll через Центр обновления Windows.

  • Нажмите клавишу Windows + I, чтобы открыть настройки,
  • Щелкните Обновить и безопасность, затем проверьте наличие обновлений,
  • Это проверит наличие последних обновлений Windows, загрузит и установит их, если они доступны.

После этого перезагрузите компьютер, чтобы применить обновления Windows и проверьте, исправлена ​​ли ошибка, когда отсутствует api-ms-win-crt-runtime.

Загрузите и установите Visual C++ Redistributable вручную

Если на вашем устройстве уже установлен Microsoft Visual C++ Redistributable, и он по-прежнему показывает, что запуск невозможен api-ms-win-crt, сделайте следующее:

  • Запустите vc_redist.x64.exe, установите флажок Я согласен, затем нажмите установить,
  • На этот раз нажмите «Восстановить», это заменит поврежденный api-ms-win-crt-stdio-l1-1-0.dll на правильный.
  • После этого перезагрузите компьютер и попробуйте запустить приложение, которое ранее выдавало ошибку.

запуск невозможен api ms win crt

Если предыдущие решения вам не помогли, перейдите к следующему варианту:

  • Сначала загрузите файл .dll отсюда,
  • Загрузите как 64-разрядную, так и 32-разрядную версию

Теперь скопируйте и вставьте 64-битный файл api-ms-win-crt-stdio-l1-1-0.dll в папку по пути C:\Windows\System32, а 32-битный файл в C:\Windows\SysWOW64

скачать api ms win crt convert

Если вам помогла статья или не помогла, вы всегда сможете задать свой вопрос ниже в комментариях.

В этой статье описывается, как настроить в проектах классических приложений использование API-интерфейсов среды выполнения Windows (WinRT), предоставляемых в ОС Windows, и добавить в классические приложения современные возможности Windows 11 и Windows 10.

Некоторые API среды выполнения Windows (WinRT) не поддерживаются в классических приложениях. Дополнительные сведения см. в статье API среды выполнения Windows не поддерживаются в классических приложениях.

В Visual Studio щелкните правой кнопкой мыши проект в Обозревателе решений и выберите Изменить файл проекта. Файл проекта будет выглядеть примерно так.

В приведенном ниже примере показан параметр OutputType средства WinExe, который указывает на исполняемый файл графического пользовательского интерфейса Windows (и не позволяет открыть окно консоли при запуске приложения). Если в вашем приложении нет графического пользовательского интерфейса, значение OutputType будет другим. API-интерфейсы WinRT можно вызывать из приложений с графическим пользовательским интерфейсом, консольных приложений и библиотек для Windows. Кроме того, значение TargetFramework может не совпадать с примером ниже.

Замените значение элемента TargetFramework одной из указанных ниже строк, оставив все остальные значения без изменений.

  • net5.0-windows10.0.17763.0 — если приложение предназначено для Windows 10, версия 1809.
  • net5.0-windows10.0.18362.0 — если приложение предназначено для Windows 10, версия 1903.
  • net5.0-windows10.0.19041.0 — если приложение предназначено для Windows 10, версия 2004.
  • net5.0-windows10.0.22000.0 — если приложение предназначено для Windows 11.

Например, следующий элемент используется для проекта, предназначенного для Windows 10 версии 2004.

Сохраните изменения и закройте файл проекта.

Поддержка нескольких версий ОС Windows

Свойство TargetFramework для конкретной версии ОС Windows определяет версию пакета Windows SDK, с которым компилируется приложение. Это свойство определяет набор доступных API-интерфейсов во время сборки и предоставляет значения по умолчанию для TargetPlatformVersion и TargetPlatformMinVersion (если они не заданы явно). Свойство TargetPlatformVersion не нужно явно определять в файле проекта, так как оно автоматически задается версией ОС TargetFramework.

Значение TargetPlatformMinVersion можно переопределить, чтобы оно было меньше значения TargetPlatformVersion (определяется версией в свойстве TargetFramework). Благодаря этому приложение сможет работать в более ранних версиях ОС. Например, в файле проекта можно задать приведенные ниже значения, чтобы обеспечить для приложения поддержку Windows 10 версии 1809.

Обратите внимание, что при установке в качестве значения TargetPlatformMinVersion версии ниже, чем значение TargetPlatformVersion, есть вероятность того, что будут вызваны недоступные API-интерфейсы. При вызове API-интерфейсов WinRT, которые доступны не во всех поддерживаемых версиях ОС, рекомендуется защищать эти вызовы с помощью проверок ApiInformation. Дополнительные сведения см. в статье Приложения с адаптивным к версии кодом.

Убедитесь, что ссылки на пакеты активны:

  1. В Visual Studio выберите элементы Сервис -> Диспетчер пакетов NuGet -> Параметры диспетчера пакетов.
  2. Убедитесь, что для формата управления пакетами по умолчанию установлено значение PackageReference.

В Visual Studio щелкните правой кнопкой мыши проект в обозревателе решений и выберите элемент Управление пакетами NuGet.

В окне диспетчера пакетов NuGet выберите вкладку Обзор и найдите Microsoft.Windows.SDK.Contracts .

Когда пакет Microsoft.Windows.SDK.Contracts будет найден, выберите на правой панели диспетчера пакетов NuGet нужную версию пакета в зависимости от версии Windows 10, на которую нужно ориентировать приложение:

  • 10.0.19041.xxxx — вариант для Windows 10 версии 2004;
  • 10.0.18362.xxxx — вариант для Windows 10 версии 1903;
  • 10.0.17763.xxxx — вариант для Windows 10 версии 1809;
  • 10.0.17134.xxxx — вариант для Windows 10 версии 1803.

В приведенном ниже примере показан параметр OutputType средства WinExe, который указывает на исполняемый файл графического пользовательского интерфейса Windows (и не позволяет открыть окно консоли при запуске приложения). Если в вашем приложении нет графического пользовательского интерфейса, значение OutputType будет другим. API-интерфейсы WinRT можно вызывать из приложений с графическим пользовательским интерфейсом, консольных приложений и библиотек для Windows. Кроме того, значение TargetFramework может не совпадать с примером ниже.

По завершении файл проекта должен выглядеть примерно так.

Сохраните изменения и закройте файл проекта.

Настройка проекта классических приложений C++ (Win32) для использования API среды выполнения Windows

Воспользоваться API-интерфейсами WinRT позволяет библиотека C++/WinRT. C++/WinRT — это полностью стандартная современная проекция языка C++17 для API-интерфейсов WinRT, реализованная как библиотека на основе файлов заголовков и предназначенная для предоставления первоклассного доступа к современным API Windows.

Чтобы настроить C++/WinRT для проекта, сделайте следующее:

  • Для новых проектов можно установить расширение C++/WinRT Visual Studio (VSIX) и использовать один из шаблонов проектов C++/WinRT, входящих в это расширение.
  • Для существующих проектов можно установить в проект пакет NuGet Microsoft.Windows.CppWinRT.

Дополнительные сведения об этих вариантах см. в разделе Поддержка Visual Studio для C++/WinRT и VSIX .

Добавление возможностей Windows 10

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

✅ Сначала определите, какие возможности нужно добавить

Выбор огромен. Например, можно упростить оформление покупки с помощью API монетизации либо привлечь внимание к приложению, когда вы можете предложить что-либо интересное, например новую фотографию, добавленную другим пользователем.

Всплывающее уведомление

Дополнительные сведения см. в документации по UWP.

✅ Выберите путь улучшения: дополнить или расширить

Вам часто будут встречаться термины дополнить и расширить, поэтому сейчас мы поясним, какой именно смысл вкладываем в них.

Термин дополнить относится к API-интерфейсам WinRT, которые вы можете вызывать напрямую из классического приложения (независимо от того, применяете ли вы для приложения упаковку в пакет MSIX). При выборе новой возможности Windows 10 определите API-интерфейсы, которые вам необходимы для ее реализации, а затем проверьте, входит ли нужный API в этот список. Это список API-интерфейсов, которые можно вызывать непосредственно из классического приложения. Если выбранный API не входит в этот список, значит, связанные с этим API функции могут работать только в рамках процесса UWP. Сюда часто входят API-интерфейсы, которые отображают элементы XAML UWP, например элемент управления картой UWP или запрос безопасности Windows Hello.

API, которые отображают XAML UWP, обычно нельзя напрямую вызывать из классического приложений. Но иногда для них доступны альтернативные подходы. Если вы хотите разместить элементы управления XAML UWP или другие пользовательские визуальные объекты, попробуйте применить XAML Islands (доступны в Windows 10 с версии 1903) и (или) визуальный уровень (доступен в Windows 10 с версии 1803). Эти возможности можно использовать в упакованных и неупакованных классических приложениях.

Если вы решили упаковать классическое приложение в пакет MSIX, у вас есть возможность расширить это приложение, добавив к нему проект UWP. Проект классического приложения по-прежнему остается точкой входа для вашего приложения. Но проект UWP предоставляет доступ ко всем API-интерфейсам, которые не входят в этот список. Классические приложения могут взаимодействовать с процессами UWP с помощью службы приложений. У нас есть множество рекомендаций по настройке этой функции. Если вы хотите добавить возможность, для которой требуется проект UWP, см. раздел Расширение возможностей с помощью компонентов UWP.

✅ Добавьте ссылки на контракты API

Если вы можете вызывать API непосредственно из классического приложения, откройте браузер и найдите справочный раздел для этого API-интерфейса. Под общей информацией об API там представлена таблица с описанием контракта для этого API. Пример такой таблицы приведен ниже.

Таблица контракта API

✅ Вызовите API-интерфейсы для добавления возможности

Ниже приведен код для отображения окна уведомлений, которое мы уже видели ранее. Эти API-интерфейсы внесены в этот список, а значит, вы можете добавить этот код в классическое приложение и запустить его прямо сейчас.

Поддержка установочных баз Windows XP, Windows Vista, Windows 7 и Windows 8

Вы можете модернизировать приложение для Windows 10, не создавая новую ветвь и не поддерживая раздельные базы кода.

Если вы хотите создать отдельные двоичные файлы для пользователей Windows 10, используйте условную компиляцию. Если вы предпочитаете создать один набор двоичных файлов, которые развертываются для всех пользователей Windows, используйте проверки во время выполнения.

Давайте вкратце рассмотрим эти варианты.

Условная компиляция

Можно вести одну базу кода и компилировать набор двоичных файлов только для пользователей Windows 10.

Для этого добавьте новую конфигурацию сборки в проект.

Конфигурация сборки

Создайте константу для этой конфигурации сборки, чтобы определить код, который будет вызывать API-интерфейсы WinRT.

Константа условной компиляции

Для проектов на основе C++ эта константа называется описанием препроцессора.

Константа описания препроцессора

Добавьте эту константу до всех блоков кода UWP.

Компилятор выполнит сборку этого кода, только если соответствующая константа определена в активной конфигурации сборки.

Проверки во время выполнения

Можно скомпилировать один набор двоичных файлов для всех пользователей Windows независимо от того, какую версию Windows они используют. В этом случае приложение будет обращаться к API-интерфейсам WinRT, только если пользователь выполняет его как упакованное приложение в среде Windows 10.

Для добавления в код проверок во время выполнения проще всего установить пакет NuGet Desktop Bridge Helpers (Вспомогательные элементы моста для классических приложений), а затем использовать метод IsRunningAsUWP() для отсеивания всего кода, который вызывает API-интерфейсы WinRT. Дополнительные сведения см. в записи блога Мост для классических приложений — определение контекста приложения.

Связанные примеры

Есть вопросы? Задайте их на Stack Overflow. Наша команда следит за этими тегами. Вы также можете задавать вопросы на наших форумах.

Вот вопрос, который порождает много путаницы. Может ли программное обеспечение для ПК написанное в WPF, WinForms или MFC иметь доступ к Windows 10 API, используемым универсальной платформой Windows (UWP)?

Ответ: да. Есть некоторые исключения из этого правила (и мы попытаемся их найти), но в целом вы можете получить доступ к API Windows 10. Или, выражаясь по-другому, нет никаких секретных API, которые закрыты от Windows разработчиков.

Скажем, я хочу, чтобы моему WPF приложению было известно местоположение, вызвав класс Geolocator в Windows 10 Windows.Devices.Geolocation API. Теперь я могу это сделать, и даже использовать асинхронный шаблон присущий для UWP. Классы и методы, которые мы обычно ассоциируем как UWP код, теперь переплетены с классами и методами из WPF. В примере показано ниже, я беру свою широту и долготу из Geolocator и отображаю их в MessageBox WPF.

private async void Button_Click ( object sender, RoutedEventArgs e ) var locator = new Windows . Devices . Geolocation . Geolocator ( ) ; var position = location . Coordinate . Point . Position ;

Разблокирование еще большего объёма API
На самом деле есть способ обеспечить настольное программное обеспечение идентификационными данными пакета. Desktop Bridge позволяет упаковать настольное программное обеспечение для развертывания в Windows Store. В рамках этого процесса, вы создаете файл манифеста для приложения, фактически давая ему идентификаторы пакета.

Если вы создаёте пакет настольного программного обеспечения для Windows Store с помощью Desktop Bridge, то большинство API, которые вы ранее не могли использовать, потому что они требуют идентификаторов пакетов, будут доступны для вас. API-интерфейсы, которые зависят от CoreWindow по-прежнему будут проблемой. Однако, как только у вас есть пакет созданный с помощью Desktop Bridge, вы можете добавить UWP компонент (который работает в отдельном процессе контейнера приложения), и вызвать буквально любой UWP API из него.

Более быстрый способ получить эти Windows 10 API
Но допустим, что вы не хотите развертывать приложение в Windows Store на данный момент и просто хотите использовать некоторые из этих Windows 10 API. Как получить доступ к ним из приложения?
Для этого есть специальный NuGet пакет. Он называется UwpDesktop и написан Владимиром Постелом и Лучиана Вищик. Если вы хотите изучить исходный код, он размещён на GitHub.
Для демонстрационных целей, давайте создадим консольное приложение, основываясь на статью 2012 года Скота Хансельмана об использовании WinRT API-интерфейсов (частично, чтобы показать, насколько легче это сделать сегодня). После создания нового настольного консольного приложения, вставьте исходный код 2012 года в метод Main в Program.cs.

uint minReportInterval = light . MinimumReportInterval ; uint reportInterval = minReportInterval > 16 ? minReportInterval : 16 ;


Вот как мы это исправим. Установим пакет UWPDesktop в свой проект с помощью диспетчера NuGet пакетов.

Вернемся в Program.cs, добавим следующую строку с директивой using в верхней части файла:

Как получить доступ к Windows 10 APIs из C++
Вызов Windows 10 API-интерфейсов возможен не только для управляемого кода. Вы также всегда в состоянии вызывать их из нативных C++ приложений.

Начните с создания нового проекта приложения C ++ Win32. В качестве альтернативы, откройте предварительно существующий проект C++ Windows приложения. Щелкните правой кнопкой мыши на проекте и выберите Properties, чтобы открыть окно настроек. Всего четыре шага необходимо для настройки приложения для осуществления вызовов Windows 10 API.

Добавьте следующие директивы using в верхнюю часть главного файла CPP вашего проекта:

Казалось бы, что WinAPI уходит в прошлое. Давно уже существует огромное количество кросс-платформенных фреймфорков, Windows не только на десктопах, да и сами Microsoft в свой магазин не жалуют приложения, которые используют этого монстра. Помимо этого статей о том, как создать окошки на WinAPI, не только здесь, но и по всему интернету, исчисляется тысячами по уровню от дошколят и выше. Весь этот процесс разобран уже даже не по атомам, а по субатомным частицам. Что может быть проще и понятнее? А тут я еще…

Но не все так просто, как кажется.

Почему о WinAPI сейчас?

В один прекрасный момент, изучая потроха одной из игр в весьма неплохом эмуляторе NES, я подумал: Вроде неплохой такой эмуль, а в отладчике нет такой простой вещи, как навигация по кнопкам клавиатуры, которая есть в любом нормальном отладчике.

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

О чем это я? А вот об этом кусочке кода:

Ответ такой: так делать нельзя!

И, возвращаясь, к изначальному вопросу о WinAPI: очень много популярных, и не очень, проектов продолжают его использовать и в настоящее время, т.к. лучше, чем на чистом API многие вещи не сделать (тут можно бесконечно приводить аналогии вроде сравнения высокоуровневых языков и ассемблера, но сейчас не об этом). Да и мало ли почему? Просто используют и все тут.

О проблеме

Обойти такие мелкие неприятности просто. Есть, как минимум, два вполне легальных способа:

Tutorials?


Здесь действительно все просто:

Because the return value can be nonzero, zero, or -1, avoid code like this:

И ниже приводится пример правильного цикла.

Стоит сказать, что в шаблонах VS для Win32 приложений, написан именно такой неправильный цикл. И это очень печально. Ведь мало кто будет вникать в то, что сделали сами авторы, ведь это априори правильно. И неправильный код множится вместе с багами, которые очень сложно отловить.

После этого фрагмента кода, как правило, следует рассказ про акселераторы, и добавляется пара новых строчек (учитывая замечание в MSDN, предлагаю сразу писать правильный цикл):


Этот вариант я видел чаще всего. И он (та-дам) снова неправильный!

Сперва о том, что изменилось (потом о проблемах этого кода):

Ясно, что TranslateAccelerator надо вызывать для нашего созданного окна:


И вроде все хорошо и замечательно теперь: мы разобрали все детально и все должно работать идеально.

И снова нет. :-) Это будет работать правильно, пока у нас ровно одно окно — наше. Как только появится немодальное новое окно (диалог), все клавиши, которые будут в нем нажаты оттранслируются в WM_COMMAND и отправляться куда? И опять же правильно: в наше главное окно.

На этом этапе предлагаю не городить костылей по решению этой тупиковой ситуации, а предлагаю рассмотреть вещи, которые уже реже (или почти не встречаются) в туториалах.

IsDialogMessage

На самом деле, делает она чуть больше, чем следует из названия. А именно:

  • Осуществляет навигацию по дочерним контролам кнопками Tab/Shift+Tab/вверх/вниз/вправо/влево. Плюс еще кое-что, но этого нам достаточно
  • По нажатии на ESC формирует WM_COMMAND( IDCANCEL )
  • По нажатии на Enter формирует WM_COMMAND( IDOK ) или нажатие на текущую кнопку по умолчанию
  • Переключает кнопки по умолчанию (рамочка у таких кнопок чуть ярче остальных)
  • Ну и еще разные штуки, которые облегчают пользователю работу с диалогом

Во-вторых, она нам облегчит жизнь по всем остальным пунктам, перечисленным в списке (и даже немного больше).

Вообще, она используется где-то в недрах Windows для обеспечения работы модальных диалоговых окон, а программистам дана, чтобы вызывать ее для немодальных диалогов. Однако мы ее можем использовать где угодно:

Although the IsDialogMessage function is intended for modeless dialog boxes, you can use it with any window that contains controls, enabling the windows to provide the same keyboard selection as is used in a dialog box.

Т.е. теперь, если мы оформим цикл так:


То наше окошко будет иметь навигацию, как в родном диалоге Windows. Но теперь мы получили два недостатка:

Пора поговорить о том, чего нет в туториалах и ответах.

Как правило (как правило! Если кому-то захочется большего, то можно регистрировать свой класс для диалогов и работать так. И, если же, кому-то это интересно, я могу дополнить этим статью) WM_KEYDOWN хотят тогда, когда хотят обработать нажатие на клавишу, которая выполнит функцию в независимости от выбранного контрола в окне — т.е. некая общая функция для всего данного конкретного диалога. А раз так, то почему бы не воспользоваться богатыми возможностями, которые нам сама WinAPI и предлагает: TranslateAccelerator.

Везде используют ровно одну таблицу акселераторов, и только для главного окна. Ну действительно: цикл GetMessage-loop один, значит и таблица одна. Куда еще их девать?

На самом деле, циклы GetMessage-loop могут быть вложенными. Давайте еще раз посмотрим описание PostQuitMessage:

The PostQuitMessage function posts a WM_QUIT message to the thread's message queue and returns immediately; the function simply indicates to the system that the thread is requesting to quit at some time in the future.
If the function retrieves the WM_QUIT message, the return value is zero.

Таким образом, выход из GetMessage-loop осуществится, если мы вызовем PostQuitMessage в процедуре окна. Что это значит?

Мы можем для каждого немодального окна в нашей программе создавать свой собственный подобный цикл. В данном случае DialogBoxParam нам не подходит, т.к. оно крутит свой собственный цикл и повлиять мы на него не можем. Однако если создадим диалог через CreateDialogBoxParam или окно через CreateWindow, то можно закрутить еще один цикл. При этом в каждом таком окне и диалоге мы должны вызывать PostQuitMessage:


Обратите внимание: теперь для каждого нового окна в нашей программе мы можем добавить в обработку собственную таблицу акселераторов. WM_QUIT будет выхватывать GetMessage из цикла для диалога, а внешний цикл его даже не увидит. Почему так происходит?

Дело в том, что внешний цикл «встал» на вызове DispatchMessage, который вызвал нашу процедуру, которая крутит свой собственный внутренний цикл GetMessage с таким же DispatchMessage. Классический вложенный вызов (в данном случае DispatchMessage). Посему внешний цикл не получит WM_QUIT и не завершится на этом этапе. Все будет работать стройно.

Делаем красиво

Т.к. правильная постановка задачи является половиной решения, то сперва надо эту самую задачу правильно же и поставить.

Создадим простой std::map, который будет мапить дескриптор окна в дескриптор таблицы акселераторов. Вот так:


И по мере создания окон будем в него добавлять новые окна с дескриптором на свою любимую таблицу (или нуль, если такая обработка не требуется).


Ну и после закрытия окна удалять. Вот так:


Теперь, как создаем новый диалог/окно, вызываем AddAccelerators( hNewDialog, IDR_MY_ACCEL_TABLE ). Как закрываем: DelAccel( hNewDialog ).


Значительно лучше! Что же там в HandleAccelArray и зачем там GetActiveWindow()?

Есть две функции, возвращающих дескриптор активного окна GetForegroundWindow и GetActiveWindow. Отличие первой от второй вполне доходчиво описано в описании второй:

The return value is the handle to the active window attached to the calling thread's message queue. Otherwise, the return value is NULL.


Теперь каждое дочернее окно вправе добавить себе любимую таблицу акселераторов и спокойно ловить и обрабатывать WM_COMMAND с нужным кодом.

А что там еще об одной строчке в коде обработчика WM_COMMAND?

To differentiate the message that this function sends from messages sent by menus or controls, the high-order word of the wParam parameter of the WM_COMMAND or WM_SYSCOMMAND message contains the value 1.

Обычно код обработки WM_COMMAND выглядит так:


Теперь можно написать так:

P.S.: Мало кто знает, но можно создавать свою собственную таблицу акселераторов, а теперь и применять ее прямо налету.

P.P.S.: Т.к. DialogBox/DialogBoxParam крутит собственный цикл, то от при вызове диалога через них акселераторы работать не будут и наш цикл (или циклы) будет «простаивать».

P.P.P.S.: После вызова HandleAccelWindow мап l_mAccelTable может измениться, т.к. TranslateAccelerator или IsDialogMessage вызывают DispatchMessage, а там может встретиться AddAccelerators или DelAccel в наших обработчиках! Поэтому лучше его после этой функции не трогать.

Пощупать код можно здесь. За основу был взят код, генерируемый из стандартного шаблона MS VS 2017.

Читайте также: