微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

delphi – EnumerateTraceGuids返回“参数不正确”(87)

我试图调用 Windows API函数 EnumerateTraceGuids

ULONG EnumerateTraceGuids(
  __inout  PTRACE_GUID_PROPERTIES *GuidPropertiesArray,__in     ULONG PropertyArrayCount,__out    PULONG GuidCount
);

代码示例on MSDN开始:

ULONG status = ERROR_SUCCESS;
PTRACE_GUID_PROPERTIES *pProviders = NULL;
ULONG RegisteredProviderCount = 0;
ULONG ProviderCount = 0;

pProviders = (PTRACE_GUID_PROPERTIES *) malloc(sizeof(PTRACE_GUID_PROPERTIES));
status = EnumerateTraceGuids(pProviders,ProviderCount,&RegisteredProviderCount);

我将代码转换为Delphi:

var
    providers: PPointerList;
    providerCount: LongWord;
    registeredProviderCount: LongWord;
    res: LongWord;
begin
    providerCount := 0;
    registeredProviderCount := 0;
    providers := Allocmem(SizeOf(Pointer));
    ZeroMemory(providers,SizeOf(Pointer));

    res := EnumerateTraceGuids(providers,providerCount,{out}registeredProviderCount);
end;

随着api电话:

function EnumerateTraceGuids(
      GuidPropertiesArray: Pointer; 
      PropertyArrayCount: Cardinal; 
      var GuidCount: Cardinal): Cardinal; stdcall; external 'advapi32.dll';

我得到结果代码ERROR_INVALID_ParaMETER(87,参数不正确).

我究竟做错了什么?

MSDN描述了导致ERROR_INVALID_ParaMETER的原因:

ERROR_INVALID_ParaMETER

One of the following is true:

  • PropertyArrayCount is zero
  • GuidPropertiesArray is NULL

第一种情况是正确的,我的第二个参数PropertyArrayCount为零 – 就像样本所说的那样.

解决方法

据我所知,您的代码应该与MSDN示例相同.但是,正如Code所说,MSDN示例确实看起来有点时髦.实际上,在我看来,MSDN样本只是偶然的.

请注意,该代码中的注释表明:

// EnumerateTraceGuids requires a valid pointer. Create a dummy
// allocation,so that you can get the actual allocation size.

然后它在pProviders中分配空间来存储单个指针.但是,pProviders中包含的值实际上很重要.它不能为NULL.在你的Delphi代码中,你实际上将内存归零了两次.一次使用Allocmem,一次使用ZeroMemory.如果您只是更改Delphi代码以使提供程序的内容非零,那么Delphi代码将开始工作.

这是一个非常简单的项目,它准确地说明了发生了什么:

program _EnumerateTraceGuidsFaultDemo;

{$APPTYPE CONSOLE}

function EnumerateTraceGuids(
      GuidPropertiesArray: Pointer;
      PropertyArrayCount: Cardinal;
      var GuidCount: Cardinal): Cardinal; stdcall; external 'advapi32.dll';


var
  providers: Pointer;
  providerCount: LongWord;
  registeredProviderCount: LongWord;
  res: LongWord;
begin
  providerCount := 0;
  registeredProviderCount := 0;

  providers := Allocmem(SizeOf(Pointer));//zeroises memory
  res := EnumerateTraceGuids(providers,registeredProviderCount);
  Writeln(res);//outputs 87

  PInteger(providers)^ := 1;
  res := EnumerateTraceGuids(providers,registeredProviderCount);
  Writeln(res);//outputs 234

  Readln;
end.

所以我认为这解释了这个问题,但我实际上解决的问题还不止于此.我将继续进行下一步的工作,并使用与TRACE_GUID_PROPERTIES结构等效的真实Delphi完全声明EnumerateTraceGuids.

我可能会写这样的代码

program _EnumerateTraceGuids;

{$APPTYPE CONSOLE}

{$R *.res}

uses
  System.SysUtils,Windows;

type
  PTraceGuidProperties = ^TTraceGuidProperties;
  TTraceGuidProperties = record
    Guid: TGUID;
    GuidType: ULONG;
    LoggerId: ULONG;
    EnableLevel: ULONG;
    EnableFlags: ULONG;
    IsEnable: Boolean;
  end;

function EnumerateTraceGuids(
  var GuidPropertiesArray: PTraceGuidProperties;
  PropertyArrayCount: ULONG;
  var GuidCount: ULONG
): ULONG; stdcall; external 'advapi32.dll';

function GetRegisteredProviderCount: ULONG;
var
  provider: TTraceGuidProperties;
  pprovider: PTraceGuidProperties;
  providerCount: LongWord;
  registeredProviderCount: ULONG;
  res: ULONG;
begin
  providerCount := 0;
  pprovider := @provider;
  res := EnumerateTraceGuids(pprovider,registeredProviderCount);
  if (res<>ERROR_MORE_DATA) and (res<>ERROR_SUCCESS) then
    RaiseLastOSError;
  Result := registeredProviderCount;
end;

var
  i: Integer;
  provider: TTraceGuidProperties;
  pprovider: PTraceGuidProperties;
  providers: array of TTraceGuidProperties;
  pproviders: array of PTraceGuidProperties;
  providerCount: ULONG;
  registeredProviderCount: ULONG;
  res: ULONG;
begin
  providerCount := GetRegisteredProviderCount;
  SetLength(providers,providerCount);
  SetLength(pproviders,providerCount);
  for i := 0 to providerCount-1 do
    pproviders[i] := @providers[i];
  res := EnumerateTraceGuids(pproviders[0],registeredProviderCount);
  if res<>ERROR_SUCCESS then
    RaiseLastOSError;
  //do stuff with providers
end.

我没有尝试在GetRegisteredProviderCount中过于可爱,而是传递了指向真实TRACE_GUID_PROPERTIES的指针.

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐