对于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)
}