3

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.

Anse
  • 1,573
  • 12
  • 27

1 Answers1

6

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.

David Heffernan
  • 601,492
  • 42
  • 1,072
  • 1,490
  • The first call to `GetCurrentPackageFullName(Len, nil)` always returns code 122 (ERROR_INSUFFICIENT_BUFFER). But anyway, the Len variable is populated correctly and also the name. Thanks a lot! – Anse Feb 01 '18 at 18:45
  • My mistake. It's clearly documented and I did the pay enough attention. Fixed now. – David Heffernan Feb 01 '18 at 19:23