如何在 Delphi 中检测通用 Windows 平台 (UWP)

How to detect Universal Windows Platform (UWP) in Delphi

要将用 Delphi 编写的应用程序添加到 Windows 商店,我必须禁用内部更新机制。例如像 "Check for updates" 这样的东西是通过 Store policies 10.2.5

禁止的

所以,我在 DesktopBridgeHelpers project code 中找到了 C# 辅助函数 IsRunningAsUwp()。我的计划是将该助手转换为 Delphi 代码,但 packageFullName 字符串在这里始终为空,即使我 运行 通过 DesktopBridge 转换项目的应用程序也是如此:

[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;
    }
}

我当前的(不工作)Delphi 转换看起来像这样:

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;

当运行通过已安装的 appx 包时,我没有收到其他错误,只有那个空的 PackageName。

函数导入不正确。应该是

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

然后调用它你这样做:

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);

您可能希望以不同的方式处理错误,但我相信您可以解决。

请注意,C# 代码有一些我没有重现的错误。