2

My first thought was to use GetPackageFamilyName() and look for ERROR_SUCCESS vs APPMODEL_ERROR_NO_PACKAGE.

But, I need to support Windows 7, which makes GetPackageFamilyName() unusable.

Is there a decent alternative method? Anything in the Registry, perhaps?

Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
William
  • 31
  • 1
  • 1
    [Can UWP apps be ported to Windows 7?](https://stackoverflow.com/questions/34059267/can-uwp-apps-be-ported-to-windows-7) and the answer is no. Its either a UWP app or it's not. An application can't run as a UWP app. – Richard Chambers Sep 06 '18 at 15:41
  • 1
    @RichardChambers I suspect they are a library and want to know if they are living UWP land or not? – Yakk - Adam Nevraumont Sep 06 '18 at 15:41
  • 1
    @Yakk-AdamNevraumont so the question posted is lacking the necessary information to provide an answer? Perhaps the actual question is how can a library know whether particular functionality is available or not? As in can the software component use WinRT or not or if the Win32 API is available or not? – Richard Chambers Sep 06 '18 at 15:47
  • 1
    Sorry if that wasn't enough information! I have a win32 app that I package two ways. I use WiX to generate an .msi (which can be used on win7, win8.1, and win10). I also centennialize the app so that it can be run as a UWP and put through the microsoft store. I don't want to have to have two actually separate builds, so I originally opted into using GetPackageFamilyName() to tell if they'd gone the UWP route, or just used the WiX .msi... but this crashes the app if the user is on Win7 (having used the .msi). Is there a good alternative that will work, but not crash Win7? – William Sep 06 '18 at 16:01
  • 5
    @William dont link to `GetPackageFamilyName()` statically. Load it dynamically at runtime, either explicitly via `GetProcAddress()`, or implicitly via the linker's delay-load feature. Then it won't be loaded until the first time you try to call it. You can skip that call on older Windows versions. – Remy Lebeau Sep 06 '18 at 17:03
  • FYI GetCurrentPackageFullName() is slightly more efficient, for 2 reasons: 1: GetCurrent... is slightly more efficient to test the current process space than Get* taking a process handle (even a pseudo-handle like GetCurrentProcess) and 2: Get...PackageFullName is slightly more efficient than Get...PackageFamilyName – Howard Kapustein Aug 15 '19 at 04:03
  • The confusion in this question is the phrase "UWP with legacy support". There's no such thing. What you are asking about is a "Desktop Bridge" application that's packaged both as a Windows Store app and as a classic Win32 desktop app. UWP doesn't have anything to do with that, or rather implies a bunch of API restrictions that don't apply. – Chuck Walbourn Feb 26 '23 at 20:32

3 Answers3

6

Use GetProcAddress() to load GetPackageFamilyName() dynamically at runtime, eg:

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
{
    //...
}

Alternatively, consider using one of the GetCurentPackage...() functions (GetCurrentPackageFamilyName(), GetCurrentPackageId(), GetCurrentPackageInfo(), etc) instead of using GetPackageFamilyName() with a HANDLE to the calling process.

Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
2

GetPackageFamilyName is the right way. In order to support Windows 7, you can first check if you are running on Win7. If you are, then you know you are not packaged. Only if you are on version >7 then you call GetPackageFamilyName to check whether or not you are packaged.

Stefan Wick MSFT
  • 13,600
  • 1
  • 32
  • 51
  • 2
    You don't really need to check the Windows version. Simply load the function dynamically at runtime using `GetProcAddress()`. If it doesn't exist, skip it and move on. If it does exist, call it and act accordingly – Remy Lebeau Sep 06 '18 at 17:01
0

Here is an article from Microsoft with an example, which should support Windows 7 too.

Desktop Bridge – Identify the application’s context

Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
Bogdan Mitrache
  • 10,536
  • 19
  • 34
  • The article takes a similar approach as mentioned in other answers, but using `GetCurrentPackageFullName` instead. However, the article says "*As such, using this code on Windows 7, Vista or even XP will always return an exception*" for its C/C++ example, as it links to `GetCurrentPackageFullName` statically, not dynamically, so it doesn't address the OP's Win7 issue. In the article's C# examples, PInvoke is used, which loads APIs dynamically. The author provides a wrapper library, but only for .NET. – Remy Lebeau Sep 07 '18 at 15:38