【发布时间】:2016-09-12 01:29:28
【问题描述】:
我正在编写一个与 Windows 服务中的 Windows API 交互的应用程序。
在@chowey here 提供大量帮助后,我有点掌握了窍门,并开始了一个基本库,我已将它放在 GitHub here 上。
我现在转到“服务”,要求列出机器上的所有 Windows 服务,启动、停止、重新启动它们。一旦你有一个服务句柄可以使用,启动/停止/重启看起来很简单,但我正在努力获取已安装服务的列表。
Advapi32.dll 中的EnumServicesStatusEx 是我需要调用的函数,但它需要一个指向为ENUM_SERVICE_STATUS_PROCESS 结构数组预分配内存的指针。
您可以使用空指针调用该函数,它会返回所需的内存分配大小,但我不相信 Go 中有直接分配内存的方法。
起初我以为我可以得到内存分配要求,使用 unsafe 包将它除以结构的 SizeOf,创建一个包含该数量元素的切片,然后将指向第一个元素的指针传递给函数,但它表示内存需要为字符串数据包含空间,而这不会。
有没有人知道这是如何实现的,谢谢? :)。
【问题讨论】:
-
来自 EnumServicesStatusEx 文档:
lpServices [out, optional] A pointer to the buffer that receives the status information. ... To determine the required size, specify NULL for this parameter and 0 for the cbBufSize parameter. The function will fail and GetLastError will return ERROR_MORE_DATA. The pcbBytesNeeded parameter will receive the required size.。知道缓冲区需要多大后,使用该大小的缓冲区再次调用 EnumServicesStatusEx。 -
你好@alex,如上所述,我不知道有一种方法可以让 Go 直接分配内存。你必须给它一个数据结构让它分配内存,然后通过 unsafe 包暴露该内存。
-
你自己说的:
create a slice containing that number of elements, then pass a pointer to the first element to the function。来自 EnumServicesStatusEx doco:cbBufSize [in] The size of the buffer pointed to by the lpServices parameter, in bytes.因此,您可以创建 cbBufSize 字节数组,并将该数组的第一个元素的地址传递给 EnumServicesStatusEx。例如,请参阅github.com/golang/go/blob/master/src/internal/syscall/windows/…。与示例不同,您应该从按照 EnumServicesStatusEx doco 传递 lpServices=nil 开始。 -
是的,我是这么认为的,但是如果我创建了一个结构切片,这些结构将包含指针。分配的内存足以存储指针地址,但实际上不会为 API 调用分配任何内存来存储 MSDN 文档所要求的指针应引用的字符串数据。虽然如果所需的大小以字节为单位,我可以创建一个该大小的字节切片,然后尝试使用 unsafe 将其转换为正确的类型。必须假设内存布局是兼容的。我试试看,谢谢!
-
您应该分配请求大小的字节片。由您调用的 API 在字节缓冲区内布局所需的所有内容。您的工作将是使用 unsafe 将地址转换为您的第一个字节的正确类型。就像你说的那样。