确定当前进程是否在 WOW64 中运行或不在 Go 中

Determining if current process runs in WOW64 or not in Go

使用 Windows,猜测当前 32 位进程在 32 位或 64 位体系结构(是否在 WOW64 上)上是 运行 的官方方法是调用 IsWow64Process 来自 kernel32.dll 的函数,并查看它是否存在(据我了解文档)。

在 Go 中,我们可以使用 syscall 包调用 dll 文件中导出的函数,所以这是我的尝试:

package main

import (
    "fmt"
    "os"
    "syscall"
)

func main() {
    dll, err := syscall.LoadDLL("kernel32.dll")
    if err != nil {
        fmt.Println(err)
    }
    defer dll.Release()
    proc, err := dll.FindProc("IsWow64Process")
    if err != nil {
        fmt.Println("Proc not found") // not a WOW64 so a 32 bit system?
        fmt.Println(err)
    }
    fmt.Printf("%v\n", proc)

    var handle uintptr = uintptr(os.Getpid())

    var result uintptr
    v, x, y := proc.Call(handle, result)

    fmt.Printf("%v %v %v\n", v, x, y)
    fmt.Printf("%v\n", result)
}

不幸的是,使用或不使用 WOW64 系统的测试在标准输出中显示相同的结果:

&{0x10ada110 IsWow64Process 2088961457}
0 7 The handle is invalid.
0

我做错了什么?如何实现测试以确定我们的 32 位 Go 程序是在 64 位 CPU (WOW64) 上的模拟 32 位上运行还是在真实的 32 位上运行 Windows?

我认为问题出在您 proc.Call 的 handle 参数上。 IsWow64Process 的预期参数是一个 HANDLE,它与 pid 不同。这就是为什么它指示句柄无效。

下面的 SO 问题 How to get process handle from process id 表示您需要调用 OpenProcess 传递 pid 并且它 returns 句柄。

编辑:GetCurrentProcess 在 syscall 中定义。所以我认为您可以用以下内容替换 Getpid 调用:

handle, err := syscall.GetCurrentProcess()

好的,这是一个有效的代码:

package main

import (
    "syscall"
    "fmt"
    "unsafe"
)
func main() {
    dll, err := syscall.LoadDLL("kernel32.dll")
    if err != nil {
        fmt.Println("Can't load kernel32")
        fmt.Println(err)
    }
    defer dll.Release()
    proc, err := dll.FindProc("IsWow64Process")
    if err != nil {
        fmt.Println("Proc not found")
        fmt.Println(err)
    }
    fmt.Printf("%v\n",proc)

    handle, err := syscall.GetCurrentProcess()  
    if err != nil {
        fmt.Println("Handle not found")
        fmt.Println(err)
    }
    fmt.Printf("%v\n",handle)

    var result bool

    v, x, y := proc.Call(uintptr(handle), uintptr(unsafe.Pointer(&result)))

    fmt.Printf("%v %v %v\n",v,x,y)
    fmt.Printf("%v\n",result)
}

result 变量对于 WOW64 系统为真,对于 32 位系统为假。

您也可以使用golang.org/x/sys/windows

package main

import (
    "fmt"
    "golang.org/x/sys/windows"
)

func main() {
    handle := windows.CurrentProcess()
    var isWow64 bool
    err := windows.IsWow64Process(handle, &isWow64)
    if err != nil {
        panic(err)
    }
    fmt.Println(isWow64)
}