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



对于Windows,猜测当前32位进程是否在32位或64位体系结构上运行(WOW64也是如此)的官方方法是从kernel32.dll调用IsWow64Process函数,并查看它是否存在(正如我所理解的文档)。

在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("%vn", proc)
    var handle uintptr = uintptr(os.Getpid())
    var result uintptr
    v, x, y := proc.Call(handle, result)
    fmt.Printf("%v %v %vn", v, x, y)
    fmt.Printf("%vn", result)
}

不幸的是,使用或不使用WOW64系统进行测试都会在stdout:中显示相同的结果

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

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

我认为问题在于proc.Call上的句柄参数。IsWow64Process的预期参数是与pid不同的HANDLE。这就是它指示句柄无效的原因。

下面的SO问题How to get process handle from process id指示您需要调用在pid中传递的OpenProcess,它会返回句柄。

EDIT:GetCurrentProcess是在系统调用中定义的。因此,我认为您可以将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("%vn",proc)
    handle, err := syscall.GetCurrentProcess()  
    if err != nil {
        fmt.Println("Handle not found")
        fmt.Println(err)
    }
    fmt.Printf("%vn",handle)
    var result bool
    v, x, y := proc.Call(uintptr(handle), uintptr(unsafe.Pointer(&result)))
    fmt.Printf("%v %v %vn",v,x,y)
    fmt.Printf("%vn",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)
}

最新更新