【问题标题】:Determining if current process runs in WOW64 or not in Go确定当前进程是否在 WOW64 中运行或不在 Go 中运行
【发布时间】:2016-02-20 19:45:59
【问题描述】:

在 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("%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 上运行?

【问题讨论】:

  • 您是否完全了解您的代码主要测试您的 Go 代码是否在 WOW64 仿真上运行,而不是操作系统是否为 32 位架构?要回答如上所述的问题,您应该致电kernel32!GetNativeSystemInfo() 并检查它返回的架构。无论您是在 32 位操作系统上运行 32 位 Go 进程,还是在 64 位操作系统上运行 64 位 Go 进程,还是在 64 位操作系统上运行 32 位 Go 进程,该值都是相同的。
  • 感谢您的评论和澄清@kostix。确实,您是对的,我认为它是 32 位编译的 Go 可执行文件这一事实使我有偏见。我是否应该编辑我的问题以反映我想猜测我们是否在 WOW64 上运行,然后使用 Go 中的 GetNativeSystemInfo 函数重新提出一个新问题? It looks like it is the stackoverflow-way to handle this kind of situation.
  • 在@kostix 评论之后,已编辑问题以反映最终提出和回答的问题。

标签: windows dll go 32bit-64bit wow64


【解决方案1】:

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

下面的SO问题How to get process handle from process id表示你需要调用OpenProcess传入pid,它会返回句柄。

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

handle, err := syscall.GetCurrentProcess()

【讨论】:

  • 感谢您的回答。到目前为止,Here 是我的代码。不幸的是,我在运行它时遇到了运行时异常 (link),我无法诊断。它发生在 proc.Call() 行。看起来它不喜欢影响result var?
【解决方案2】:

好的,这是一个工作代码:

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 var 对于 WOW64 系统为 true,对于 32 位系统为 false。

【讨论】:

    【解决方案3】:

    你也可以使用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)
    }
    
    

    【讨论】:

      猜你喜欢
      • 2012-02-20
      • 1970-01-01
      • 2012-09-17
      • 2011-07-09
      • 2022-07-24
      • 2011-05-12
      • 1970-01-01
      • 1970-01-01
      • 2011-06-30
      相关资源
      最近更新 更多