Определите, работает ли приложение C++ как приложение UWP с устаревшей поддержкой

Моей первой мыслью было использовать GetPackageFamilyName() и искать ERROR_SUCCESS против APPMODEL_ERROR_NO_PACKAGE.

Но мне нужно поддерживать Windows 7, что делает GetPackageFamilyName() непригодным для использования.

Есть достойный альтернативный метод? Что-нибудь в реестре, может быть?


person William    schedule 06.09.2018    source источник
comment
Можно ли портировать приложения UWP в Windows 7? и ответ нет. Либо это приложение UWP, либо нет. Приложение не может работать как приложение UWP.   -  person Richard Chambers    schedule 06.09.2018
comment
@RichardChambers Я подозреваю, что это библиотека, и я хочу знать, живут ли они на земле UWP или нет?   -  person Yakk - Adam Nevraumont    schedule 06.09.2018
comment
@Yakk-AdamNevraumont, значит, в опубликованном вопросе отсутствует необходимая информация для ответа? Возможно, актуальный вопрос заключается в том, как библиотека может узнать, доступна ли определенная функциональность или нет? Например, может ли программный компонент использовать WinRT или нет, доступен или нет Win32 API?   -  person Richard Chambers    schedule 06.09.2018
comment
Извините, если было недостаточно информации! У меня есть приложение win32, которое я упаковываю двумя способами. Я использую WiX для создания .msi (который можно использовать на win7, win8.1 и win10). Я также отношу приложение к столетию, чтобы его можно было запускать как UWP и размещать в магазине Microsoft. Я не хочу иметь две фактически отдельные сборки, поэтому я изначально решил использовать GetPackageFamilyName(), чтобы узнать, пошли ли они по маршруту UWP или просто использовали WiX .msi... но это приводит к сбою приложения, если пользователь находится на Win7 (использовав .msi). Есть ли хорошая альтернатива, которая будет работать, но не крашит Win7?   -  person William    schedule 06.09.2018
comment
@William не ссылайтесь на GetPackageFamilyName() статически. Загружайте его динамически во время выполнения, либо явно через GetProcAddress(), либо неявно через функцию отложенной загрузки компоновщика. Тогда он не будет загружен до тех пор, пока вы не попытаетесь его вызвать в первый раз. Вы можете пропустить этот вызов в более старых версиях Windows.   -  person Remy Lebeau    schedule 06.09.2018
comment
FYI GetCurrentPackageFullName() немного более эффективен по двум причинам: 1: GetCurrent... немного более эффективен для проверки текущего пространства процесса, чем Get*, использующий дескриптор процесса (даже псевдодескриптор, такой как GetCurrentProcess) и 2: Get. ..PackageFullName немного эффективнее, чем Get...PackageFamilyName   -  person Howard Kapustein    schedule 15.08.2019


Ответы (3)


Используйте GetProcAddress() для динамической загрузки GetPackageFamilyName() во время выполнения, например:

typedef LONG WINAPI (*LPFN_GPFN)(HANDLE, UINT32*, PWSTR);
bool bIsUWP = false;

LPFN_GPFN lpGetPackageFamilyName = (LPFN_GPFN) GetProcAddress(GetModuleHandle(TEXT("kernel32")), "GetPackageFamilyName");
if (lpGetPackageFamilyName)
{
    UINT32 size = 0;
    if (lpGetPackageFamilyName(GetCurrentProcess(), &size, NULL) == ERROR_INSUFFICIENT_BUFFER)
        bIsUWP = true;
}

if (bIsUWP)
{
    //...
}
else
{
    //...
}

В качестве альтернативы рассмотрите возможность использования одной из GetCurentPackage...() функций (GetCurrentPackageFamilyName() , GetCurrentPackageId(), GetCurrentPackageInfo() и т. д.) вместо использования GetPackageFamilyName() с HANDLE для вызывающего процесса.

person Remy Lebeau    schedule 06.09.2018
comment
BTW bIsUWP является неправильным названием - IsPackagedProcess или HasPackageIdentity были бы более точными именами. - person Howard Kapustein; 15.08.2019

GetPackageFamilyName — правильный путь. Чтобы поддерживать Windows 7, вы можете сначала проверить, работаете ли вы на Win7. Если да, то вы знаете, что вы не упакованы. Только если вы используете версию> 7, вы вызываете GetPackageFamilyName, чтобы проверить, упакованы ли вы.

person Stefan Wick MSFT    schedule 06.09.2018
comment
Вам действительно не нужно проверять версию Windows. Просто загрузите функцию динамически во время выполнения, используя GetProcAddress(). Если его нет, пропустите его и двигайтесь дальше. Если он существует, вызовите его и действуйте соответственно. - person Remy Lebeau; 06.09.2018

Вот статья от Microsoft с примером, который тоже должен поддерживать Windows 7.

Мост рабочего стола — определите контекст приложения

person Bogdan Mitrache    schedule 07.09.2018
comment
В статье используется подход, аналогичный упомянутому в других ответах, но вместо этого используется GetCurrentPackageFullName. Однако в статье говорится Поэтому использование этого кода в Windows 7, Vista или даже XP всегда будет возвращать исключение для его примера C/C++, поскольку он связывается с GetCurrentPackageFullName статически, а не динамически, поэтому он не решает проблему Win7 OP. В приведенных в статье примерах C# используется PInvoke, который динамически загружает API. Автор предоставляет библиотеку-оболочку, но только для .NET. - person Remy Lebeau; 07.09.2018