英文:
Determining if current process runs in WOW64 or not in 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") // 不是WOW64,所以是32位系统?
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系统上还是在非WOW64系统上进行测试,标准输出都显示相同的结果:
&{0x10ada110 IsWow64Process 2088961457}
0 7 The handle is invalid.
0
我做错了什么?如何进行测试以确定我们的32位Go程序是在64位CPU上的模拟32位环境(WOW64)上运行,还是在真正的32位Windows上运行?
英文:
With Windows, the official way of guessing if the current 32-bit process is running on a 32 or 64-bit architecture (so on WOW64 or not) is to call the IsWow64Process function from kernel32.dll, and see if it is present (as I understand the doc).
In Go we can call functions exported in dll files with the syscall package, so here is my attempt:
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)
}
Unfortunately, testing with or without a WOW64 system displays the same in stdout:
&{0x10ada110 IsWow64Process 2088961457}
0 7 The handle is invalid.
0
What do I do wrong? How to achieve a test to determine if our 32-bit Go program runs on an emulated 32-bit on a 64-bit CPU (WOW64) or on a real 32-bit Windows?
答案1
得分: 4
我认为问题出在你的proc.Call
的handle
参数上。IsWow64Process
期望的参数是一个HANDLE
,而不是一个pid
。这就是为什么它指示该句柄无效。
以下的SO问题如何从进程ID获取进程句柄指出你需要调用OpenProcess
并传入pid,它会返回句柄。
编辑:GetCurrentProcess
在syscall中定义。所以我认为你可以用以下代码替换Getpid
的调用:
handle, err := syscall.GetCurrentProcess()
英文:
I believe the issue is the handle parameter on your proc.Call
. The expected parameter for IsWow64Process
is a HANDLE which is not the same as a pid
. Which is why it is indicating that the handle is invalid.
The following SO question How to get process handle from process id indicates that you need to call OpenProcess
passsing in the pid and it returns the handle.
EDIT: GetCurrentProcess is defined in syscall. So I think you can replace the Getpid
call with the following:
handle, err := syscall.GetCurrentProcess()
答案2
得分: 3
好的,下面是代码的中文翻译:
package main
import (
"syscall"
"fmt"
"unsafe"
)
func main() {
dll, err := syscall.LoadDLL("kernel32.dll")
if err != nil {
fmt.Println("无法加载 kernel32")
fmt.Println(err)
}
defer dll.Release()
proc, err := dll.FindProc("IsWow64Process")
if err != nil {
fmt.Println("未找到 Proc")
fmt.Println(err)
}
fmt.Printf("%v\n", proc)
handle, err := syscall.GetCurrentProcess()
if err != nil {
fmt.Println("未找到 Handle")
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 系统上为 true,在 32 位系统上为 false。
英文:
OK, so here is a working code:
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)
}
The result
var will be true for a WOW64 system and false for a 32 bit system.
答案3
得分: 1
你也可以使用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)
}
英文:
You can also use 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)
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论