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

使用Delphi 11.3调用EvtQuery()遇ERROR_ACCESS_DENIED问题求助

问题描述

之前在Delphi 10.3 + Windows 7环境下可正常调用EvtQuery()读取Windows事件日志,但切换到Delphi 11.3 + Windows 10后,EvtQuery()返回0,GetLastError()返回5(ERROR_ACCESS_DENIED,拒绝访问)。

本地机器操作,无需跨机器凭据验证,理应返回有效句柄,请问哪里被忽略了?

测试代码

program EvtQueryTest;

{$APPTYPE CONSOLE}

uses
  Windows, SysUtils;

type
  EVT_HANDLE = type THandle;

function EvtQuery(Session: EVT_HANDLE; Path, Query: PWideChar; Flags: DWORD): EVT_HANDLE;stdcall; external 'wevtapi.dll';

procedure TestEvtQuery;
// 参考事件查询官方文档

const
  EvtQueryChannelPath = $1;
  EvtQueryReverseDirection = $200;

var
  Path, Query : string;
  HostHandle, EventLogHandle : EVT_Handle;

begin
  Path := 'Security';
  Query :=  '<QueryList><Query Path="Security"><Select>Event/System[EventID=4625]</Select></Query></QueryList>';
  HostHandle := 0;

  EventLogHandle := EvtQuery(HostHandle, PWideChar(Path), PWideChar(Query), EvtQueryChannelPath + EvtQueryReverseDirection);
  if (EventLogHandle <> 0) then writeln('success !') else Writeln('ERROR Code: ' + IntToStr(GetLastError));
  readln;
  CloseHandle(EventLogHandle); // 修正原代码的Close为CloseHandle
end;

begin
  TestEvtQuery;
end.

完整代码片段

FEventLogHandle := EvtQuery.WinEvtDefs.EvtQuery(FHostHandle, PWideChar(FPath), PWideChar(FQuery), EvtQueryChannelPath + EvtQueryReverseDirection);
    result := (FEventLogHandle <> 0);
    if result then
    begin
      FEvent := TEvtEvent.Create(hSysContext, hUsrContext, FEventReaderMode);
      FEvent.UseXmlMode := XmlMode;
    end
    else
    begin
      Status := GetLastError;
      if (Status = ERROR_ACCESS_DENIED) then HandleEvtError('[E11A] - Access Denied'#13#10 + FPath + #13#10 + FQuery + #13#10, Status, false, true)
      else if (Status = ERROR_EVT_CHANNEL_NOT_FOUND) then HandleEvtError('[E11B] ' + pwsPath + ' 不是有效的事件通道', Status)
      else if (status = ERROR_EVT_INVALID_QUERY) then
      begin
       /// 可调用EvtGetExtendedStatus函数获取查询错误的详细信息
       HandleEvtError('[E12] ' + pwsQuery + ' 不是有效的事件查询语句', Status);
      end
      else HandleEvtError('[E13] EvtQuery调用失败', status);
    end;
解决方法

出现ERROR_ACCESS_DENIED的核心原因是Windows 10及后续系统对安全日志(Security)的访问权限做了更严格的限制,即使是管理员账号,默认也没有直接读取安全日志的权限。以下是具体解决步骤:

  • 以管理员身份运行程序
    右键点击编译后的exe文件,选择“以管理员身份运行”,测试是否能正常读取。如果有效,说明是权限不足导致的问题。

  • 配置程序UAC清单
    在Delphi项目中添加UAC清单,让程序启动时自动请求管理员权限:

    1. 在项目文件(.dpr)中添加:{$R 'UAC.RES' 'UAC.RC'}
    2. 创建UAC.RC文件,内容为:1 24 "UAC.Manifest"
    3. 创建UAC.Manifest文件,内容如下:
      <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
      <assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
        <trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
          <security>
            <requestedPrivileges>
              <requestedExecutionLevel level="requireAdministrator" uiAccess="false"/>
            </requestedPrivileges>
          </security>
        </trustInfo>
      </assembly>
      
  • 检查本地安全策略权限
    如果管理员身份运行仍报错,需确认账号权限:

    1. 打开“本地安全策略”(运行secpol.msc)
    2. 展开“本地策略”->“用户权限分配”
    3. 找到“管理审核和安全日志”权限,确保当前用户或Administrators组已添加
    4. 重启电脑生效
  • 修正代码中的资源泄漏问题
    原测试代码中用Close(EventLogHandle)是错误的,Windows内核句柄需用CloseHandle()关闭,避免资源泄漏。

内容的提问来源于stack exchange,提问作者ss2006

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.22 16:39:56