Delphi 10.4/11调用EnumServicesStatus报类型不兼容及访问违例问题
问题根因
Delphi 10.4及后续版本调整了Winapi.WinSvc单元中EnumServicesStatus的函数声明:旧版本该API的缓冲区参数按值接收TEnumServiceStatus(即_ENUM_SERVICE_STATUSW)类型,传数组首元素即可正常调用;新版本将该参数明确为LPENUM_SERVICE_STATUSW(_ENUM_SERVICE_STATUSW的指针类型),原有代码传ssa^[0](结构体值类型)自然会报类型不匹配错误。
之前把数组元素改为LPENUM_SERVICE_STATUSW后触发访问违例,是因为LPENUM_SERVICE_STATUSW本身就是指针类型,此时定义的数组是4096个指针的集合,New(ssa)分配的内存空间远小于存储服务状态结构体所需的大小,API写入数据时直接越界,就会触发内存访问错误。
修复方案
不需要修改原有的数组类型定义,仅需调整EnumServicesStatus调用时的参数,传入数组首元素的地址即可匹配新版本的指针参数要求。核心修正代码如下:
// 保留原有类型定义,不要将数组元素改为LPENUM_SERVICE_STATUSW type TSvcA = array[0..cnMaxServices] of TEnumServiceStatus; PSvcA = ^TSvcA; // 其余变量定义、SC管理器连接逻辑保持不变 EnumServicesStatus( schm, dwServiceType, dwServiceState, @ssa^[0], // 新增@取地址符,传入缓冲区首指针 SizeOf(ssa^), nBytesNeeded, nServices, nResumeHandle ); // 后续遍历列表、释放内存、关闭句柄的逻辑无需改动
补充说明
当前代码默认单次调用即可获取全量服务,若系统内服务总数超过定义的cnMaxServices = 4096阈值,需要循环调用EnumServicesStatus,直到nResumeHandle返回0才能拿全所有服务,否则会出现服务列表缺失的问题。
内容的提问来源于stack exchange,提问作者AbdurRahman
相关产品推荐
相关产品推荐

