当前位置: 首页 > 面试题库 >

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

符正信
2023-03-14
问题内容

我正试图GetUserNameExsecur32.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 uint
GetUserNameEx.Call(3, uintptr(unsafe.Pointer(&arr[0])), uintptr(unsafe.Pointer(&size)))
fmt.Println(arr)
fmt.Println(size)

该代码可以正常编译,但是GetUserNameEx.Call()会失败。我不知道为什么我无法得到UserName。有人可以帮我吗?


问题答案:

size是输入输出参数。进行呼叫时,必须将其设置为缓冲区(arr)的大小。它的类型也是PULONG,所以在Go中使用uint32。Windows
PULONG类型是指向的指针ULONG(具有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(你通过0size)。

工作代码(请注意,由于unicode除以2,除以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


 类似资料:
  • 问题内容: 我在Go中创建了Direct3D9包装器,该包装器使用CGo与C中的COM对象进行接口。 我想摆脱Windows下对C编译器的依赖,因此用户不必安装MinGW或Cygwin即可使用Go中的DirectX。 问题在于d3d9.dll不会公开C函数,而是使用COM。加载DLL(带有)后,可以直接调用的唯一函数是。这将返回一个COM对象,该对象将所有功能公开为方法。 如何在没有CGo的纯Go

  • 问题内容: 这是使用awt包的Java图形的初学者问题。我在网上找到了这段代码来绘制一些简单的图形。 在main方法中,在画布上没有调用paint()。但是我运行了该程序并且它可以工作,那么paint()方法如何运行? 问题答案: 该方法由事件调度线程(EDT)调用,并且基本上不受您的控制。 它的工作方式如下:当 实现 用户界面(以您的情况为例)时,Swing将启动EDT。然后,此EDT线程在后台

  • 问题内容: 我正在尝试设置spring xml配置,而不必创建进一步的。但是,即使我将数据库属性包括在 spring.xml: 我在这里想念什么? 问题答案: 在entityManagerFactory bean定义中指定“ packagesToScan”和“ persistenceUnitName”属性。 请注意,这适用于Spring版本> 3.1

  • 问题内容: 我正在学习使用Selenium(v2.20)来领先一些 即将使用它创建浏览器测试的程序员。我想在 陷阱到达之前发现它们,而我却跌入了一个陷阱。 当我创建ChromeDriver时,它始终会弹出“ Google Chrome EULA”并 显示两个按钮:“接受并运行”和“取消”。因为我希望这是一个 自动化测试,所以让用户单击按钮是不可能的。 我查看了Chromium CommandSwi

  • 我正在玩grpc 有人成功使用进行生产吗?我们需要包括特使在内的所有依赖项吗?

  • 问题内容: 我在整个应用程序中都使用spring 。现在,我也想为一个没有的创建一个。那有可能吗? 问题答案: JPA要求每个实体都有一个ID。因此,不可以,没有ID的实体是不允许的。 每个JPA实体都必须有一个主键。 从JPA规范 您可能想从这里阅读更多有关JPA如何处理数据库端没有ID的情况的信息(请参阅“无主键”)。