2012-02-14 83 views
4

我試圖調用Windows API函數EnumerateTraceGuidsEnumerateTraceGuids返回 「參數不正確」(87)

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

我轉換的代碼到德爾福:

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

下列之一爲真:

  • PropertyArrayCount爲零
  • GuidProper tiesArray是NULL

第一種情況是真實的,我的第二個參數PropertyArrayCount零 - 就像樣品說它應該是。

+0

呃,這真是MSDN頁面上的一些*可怕*示例代碼。但是用C編寫的修剪下來的代碼實際上可以工作,按照預期返回'ERROR_MORE_DATA'。不幸的是,我不知道德爾福,所以我不能告訴你如何修復這些代碼,但我很確定這個錯誤在翻譯過程中會出現。 – 2012-02-14 05:16:19

+0

@Cody有趣的是MSDN代碼只是偶然的工作。如果對malloc的調用返回初始化爲零的內存,那麼該代碼將失敗!所以你對代碼的感覺是點亮的。 – 2012-02-14 09:01:53

回答

2

就我所見,您的代碼應該與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代碼以使providers的內容非零,那麼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, providerCount, registeredProviderCount); 
    Writeln(res);//outputs 87 

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

    Readln; 
end. 

所以我認爲,解釋該問題,但我居然會比這更徹底解決它。我將繼續進行下一步工作,並使用與TRACE_GUID_PROPERTIES結構相同的真正德爾福完全聲明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, providerCount, 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], providerCount, registeredProviderCount); 
    if res<>ERROR_SUCCESS then 
    RaiseLastOSError; 
    //do stuff with providers 
end. 

而不是試圖在GetRegisteredProviderCount太可愛了,我已經過了一個指向一個真正的TRACE_GUID_PROPERTIES

+0

啊,垃圾指針!微妙,微妙,微妙! – 2012-02-14 12:18:04

+0

我的實際代碼使用了一個動態指針數組和一個'TRACE_GUID_PROPERTIES'(即SetLength())的動態數組,它不初始化內存,並且使管理更容易。 – 2012-02-14 16:17:04

+0

@Ian所以我的代碼! – 2012-02-14 16:32:05

相關問題