猿问

在 Go 中调用 EnumServicesStatusEx,内存分配?

我正在编写一个与 Windows 服务中的 Windows API 交互的应用程序。

之后从@chowey帮助负载在这里,我有点得到的东西的窍门,并开始,我已经把在GitHub上一个基本库在这里

我现在转到“服务”,要求列出机器上的所有 Windows 服务,启动、停止、重新启动它们。一旦你有一个服务句柄可以使用,启动/停止/重新启动看起来很简单,但我正在努力获取已安装服务的列表。

Advapi32.dll 中的EnumServicesStatusEx是我需要调用的函数,但它需要一个指向ENUM_SERVICE_STATUS_PROCESS结构数组的预分配内存的指针。

您可以使用空指针调用该函数,它将返回所需的内存分配大小,但我不相信有一种方法可以直接在 Go 中分配内存。

起初我以为我可以得到内存分配要求,使用 unsafe 包将它除以结构的 SizeOf,创建一个包含该数量元素的切片,然后将指向第一个元素的指针传递给函数,但它说的是内存需要为字符串数据包含空间,而这不会。

有谁知道这是如何实现的,漂亮吗?:)。


紫衣仙女
浏览 232回答 1
1回答

杨__羊羊

在@alex 的建议之后,我得到了以下示例代码。看起来我们创建了一个正确大小的字节切片,然后使用 unsafe 类转换为我们的结构类型。&nbsp; &nbsp; _, _, _ = svcEnumServicesStatusEx.Call(&nbsp; &nbsp; &nbsp; &nbsp; uintptr(handle),&nbsp; &nbsp; &nbsp; &nbsp; uintptr(uint32(SVC_SC_ENUM_PROCESS_INFO)),&nbsp; &nbsp; &nbsp; &nbsp; uintptr(uint32(SVC_SERVICE_WIN32)),&nbsp; &nbsp; &nbsp; &nbsp; uintptr(uint32(SVC_SERVICE_STATE_ALL)),&nbsp; &nbsp; &nbsp; &nbsp; uintptr(0),&nbsp; &nbsp; &nbsp; &nbsp; 0,&nbsp; &nbsp; &nbsp; &nbsp; uintptr(unsafe.Pointer(&bytesReq)),&nbsp; &nbsp; &nbsp; &nbsp; uintptr(unsafe.Pointer(&numReturned)),&nbsp; &nbsp; &nbsp; &nbsp; uintptr(unsafe.Pointer(&resumeHandle)),&nbsp; &nbsp; &nbsp; &nbsp; uintptr(0),&nbsp; &nbsp; )&nbsp; &nbsp; if bytesReq > 0 {&nbsp; &nbsp; &nbsp; &nbsp; var buf []byte = make([]byte, bytesReq)&nbsp; &nbsp; &nbsp; &nbsp; ret, _, _ := svcEnumServicesStatusEx.Call(&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; uintptr(handle),&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; uintptr(uint32(SVC_SC_ENUM_PROCESS_INFO)),&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; uintptr(uint32(SVC_SERVICE_WIN32)),&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; uintptr(uint32(SVC_SERVICE_STATE_ALL)),&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; uintptr(unsafe.Pointer(&buf[0])),&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; uintptr(bytesReq),&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; uintptr(unsafe.Pointer(&bytesReq)),&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; uintptr(unsafe.Pointer(&numReturned)),&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; uintptr(unsafe.Pointer(&resumeHandle)),&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; uintptr(0),&nbsp; &nbsp; &nbsp; &nbsp; )&nbsp; &nbsp; &nbsp; &nbsp; if ret > 0 {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; var sizeTest ENUM_SERVICE_STATUS_PROCESS&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; iter := uintptr(unsafe.Pointer(&buf[0]))&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; for i := uint32(0); i < numReturned; i++ {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; var data *ENUM_SERVICE_STATUS_PROCESS = (*ENUM_SERVICE_STATUS_PROCESS)(unsafe.Pointer(iter))&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; fmt.Printf("Service Name: %s - Display Name: %s - %#v\r\n", syscall.UTF16ToString((*[4096]uint16)(unsafe.Pointer(data.lpServiceName))[:]), syscall.UTF16ToString((*[4096]uint16)(unsafe.Pointer(data.lpDisplayName))[:]), data.ServiceStatusProcess)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; iter = uintptr(unsafe.Pointer(iter + unsafe.Sizeof(sizeTest)))&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; } else {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return nil, fmt.Errorf("Failed to get Service List even with allocated memory.")&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; } else {&nbsp; &nbsp; &nbsp; &nbsp; return nil, fmt.Errorf("Unable to get size of required memory allocation.")&nbsp; &nbsp; }
随时随地看视频慕课网APP

相关分类

Go
我要回答