You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Delphi调用WinRT的get_Thumbprint触发访问违规,是否遗漏关键步骤?

Delphi调用WinRT get_Thumbprint触发访问违规的解决方法

问题根源

你遇到的访问违规,核心是WinRT中返回字节数组的get_*方法遵循双调用规范:必须先调用方法获取实际所需的字节长度,再分配对应缓冲区获取数据。你的代码直接传入固定长度的缓冲区,跳过了获取长度的步骤,导致内存访问越界。此外,Delphi的WinRT绑定已将这类接口方法封装为更易用的Delphi属性,手动调用底层接口方法容易出错。

正确解决方案

方法1:使用Delphi封装的属性(推荐)

TCertificates_CertificateQuery类已将get_Thumbprint和put_Thumbprint封装为Thumbprint属性,直接通过属性读写即可,无需手动调用底层接口:

program Sample;

uses
  System.SysUtils,
  System.Classes,
  System.Win.WinRT,
  System.NetEncoding,
  Winapi.Windows,
  Winapi.ActiveX,
  Winapi.WinRT.Utils,
  Winapi.Winrt,
  Winapi.CommonTypes,
  Winapi.Security.Cryptography;

begin
  CoInitialize(nil);
  try
    var q := TCertificates_CertificateQuery.Create;
    try
      // 设置Thumbprint
      var B := TBytes.Create(1, 2, 3, 4);
      q.Thumbprint := B;

      // 获取Thumbprint
      var D := q.Thumbprint;
      // 此处可直接使用D数组
    finally
      q.Free;
    end;
  finally
    CoUninitialize;
  end;
end.

方法2:手动调用底层接口的正确流程

如果必须手动调用get_Thumbprint,严格遵循WinRT双调用规则:

  1. 第一次调用:传入resultSize=0和resultValue=nil,获取实际需要的字节长度
  2. 根据获取到的长度分配缓冲区,第二次调用传入正确的长度和缓冲区指针

假设你的Delphi接口声明包含resultSizeNeeded输出参数,示例代码如下:

var NeededSize: Cardinal;
var h: HRESULT;

// 第一次调用获取所需长度
h := q.get_Thumbprint(0, nil, @NeededSize);
if Succeeded(h) and (NeededSize > 0) then
begin
  SetLength(D, NeededSize);
  // 第二次调用获取实际数据
  h := q.get_Thumbprint(NeededSize, @D[0], nil);
end;

补充说明

Delphi的WinRT绑定会自动处理WinRT接口的内存管理、参数转换等细节,直接使用封装后的类属性是最安全的方式,能避免手动调用底层接口时的内存访问错误。

内容的提问来源于stack exchange,提问作者Chau Chee Yang

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.14 13:45:06