Anse
Anse

Reputation: 1658

How to detect Universal Windows Platform (UWP) in Delphi

To get an application written in Delphi to the Windows Store, I have to disable internal update mechanisms. For example things like "Check for updates" and such things are forbidden via Store policies 10.2.5

So, I found the C# helper function IsRunningAsUwp() in the DesktopBridgeHelpers project code. My plan is to convert that helper to Delphi code, but the packageFullName string is always empty here, even if I run the app through a DesktopBridge converted project:

[DllImport("kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
static extern int GetCurrentPackageFullName(ref int packageFullNameLength, StringBuilder packageFullName);

public bool IsRunningAsUwp()
{
    if (IsWindows7OrLower)
    {
        return false;
    }
    else
    {
        int length = 0;
        StringBuilder sb = new StringBuilder(0);
        int result = GetCurrentPackageFullName(ref length, sb);
        sb = new StringBuilder(length);
        result = GetCurrentPackageFullName(ref length, sb);

        return result != APPMODEL_ERROR_NO_PACKAGE;
    }
}

My current (not working) Delphi conversion looks like this:

function GetCurrentPackageFullName(out Length: DWORD; out fullName: String): DWORD; stdcall; external kernel32 delayed;

function RunningAsUwp: Boolean;
const
  APPMODEL_ERROR_NO_PACKAGE = 15700;
var
  PackageName: String;
  PackageLen, PackageResult: DWORD;
begin
  if (Win32MajorVersion < 6) or ((Win32MajorVersion = 6) and (Win32MinorVersion <= 1)) then begin
    // Windows 7 or older
    Result := False;
  end else begin
    // Windows 10, but not necessarily a Store App
    PackageLen := 0;
    SetLength(PackageName, 1024);
    PackageResult := GetCurrentPackageFullName(PackageLen, PackageName);
    showmessage(PackageName); // <= always empty
    if PackageResult = APPMODEL_ERROR_NO_PACKAGE then begin
      Result := False;
    end else if not String(PackageName).IsEmpty then begin
      Result := True;
    end else begin
      Result := False;
    end;
  end;
end;

I get no other errors, just that empty PackageName, when running through an installed appx package.

Upvotes: 4

Views: 980

Answers (1)

David Heffernan
David Heffernan

Reputation: 612804

The function import is incorrect. It should be

function GetCurrentPackageFullName(
    out Len: Cardinal; 
    Name: PWideChar
): Integer; stdcall; external kernel32 delayed;

And then to call it you do this:

var
  Len: Cardinal;
  Name: string;
  ErrorCode: Integer;
....
Len := 0;
ErrorCode := GetCurrentPackageFullName(Len, nil);
if ErrorCode <> ERROR_INSUFFICIENT_BUFFER then
  RaiseLastOSError(ErrorCode);
SetLength(Name, Len-1);
ErrorCode := GetCurrentPackageFullName(Len, PChar(Name));
if ErrorCode <> ERROR_SUCCESS then
  RaiseLastOSError(ErrorCode);

You might want to handle errors differently, but I'm sure you can work it out.

Note that the C# code has some errors which I have not reproduced.

Upvotes: 7

Related Questions