为了账号安全,请及时绑定邮箱和手机立即绑定

Golang:如何在没有 cgo 的情况下调用 win32 API?

Golang:如何在没有 cgo 的情况下调用 win32 API?

Go
茅侃侃 2021-11-22 15:57:40
我试图GetUserNameEx从secur32.dll这样打电话:dll, err := syscall.LoadDLL("secur32.dll")if err != nil {    log.Fatal(err)}defer dll.Release()GetUserNameEx, err := dll.FindProc("GetUserNameExW")if err != nil {    log.Fatal(err)}arr := make([]uint8, 256)var size uintGetUserNameEx.Call(3, uintptr(unsafe.Pointer(&arr[0])), uintptr(unsafe.Pointer(&size)))fmt.Println(arr)fmt.Println(size)这段代码编译得很好,但GetUserNameEx.Call()会失败。我不知道为什么我不能得到UserName. 有人可以帮助我吗?
查看完整描述

1 回答

?
白衣非少年

TA贡献1155条经验 获得超0个赞

size是一个输入输出参数。进行调用时,必须将其设置为缓冲区的大小 ( arr)。它的类型也是PULONG,所以在 Go 中使用uint32. WindowsPULONG类型是指向 a ULONG(其范围为 range 0..4294967295)的指针。见来源。


还Call()返回 3 个值:


func (p *Proc) Call(a ...uintptr) (r1, r2 uintptr, lastErr error)

存储返回lastErr并打印。如果你这样做,你会更早发现错误:


_, _, lastErr := GetUserNameEx.Call(

    3, uintptr(unsafe.Pointer(&arr[0])), uintptr(unsafe.Pointer(&size)))


fmt.Println(lastErr)

印刷:


More data is available.

这意味着比适合您传递的缓冲区的数据更多的数据可用 -或者更确切地说- 根据您使用 in-out 参数size(您0作为传递size)指示的大小。


工作代码(注意除以 2 由于 unicode 和减去 1 用于'\0'大小计算的终止字节/字符):


arr := make([]uint8, 256)

var size uint32 = uint32(len(arr)) / 2 - 1

_, _, lastErr := GetUserNameEx.Call(

    3, uintptr(unsafe.Pointer(&arr[0])), uintptr(unsafe.Pointer(&size)))


fmt.Println(lastErr)

fmt.Println(string(arr))

fmt.Println(arr)

fmt.Println(size)

在这种情况下lastErr将是:


The operation completed successfully.

正确处理错误:


返回的错误总是非nil,由 的结果构造而成GetLastError。在查询错误之前,调用者必须检查主要返回值以确定是否发生错误(根据被调用的特定函数的语义)。错误将保证包含syscall.Errno.


例子:


r1, _, lastErr := GetUserNameEx.Call(

    3, uintptr(unsafe.Pointer(&arr[0])), uintptr(unsafe.Pointer(&size)))


if r1 == 0 {

    fmt.Println("ERROR:", lastErr.Error())

    return

}

// No error, proceed to print/use arr


查看完整回答
反对 回复 2021-11-22
  • 1 回答
  • 0 关注
  • 239 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信