如何在Go语言中获得Windows进程的句柄?

bihw5rsg  于 2022-12-24  发布在  Windows
关注(0)|答案(3)|浏览(561)

我试图调用user32.dll的函数RegisterDeviceNotificationW,但是函数的第一个参数是"接收设备事件的窗口或服务的句柄"(这是我从微软得到的)。
基于云打印机连接器,我尝试使用svc.StatusHandler()获取处理程序,但对我不起作用,每次运行时我都会收到以下错误:
句柄无效。
我使用sysexamples的相同代码创建了自己的"服务",用RegisterDeviceNotification(与google相同的代码)替换了beep函数,并发送了服务的名称和svc.StatusHandler()返回的值,但我再次收到了相同的消息:"句柄无效。"

函数寄存器设备通知

var (
    u32                            = syscall.MustLoadDLL("user32.dll")
    registerDeviceNotificationProc = u32.MustFindProc("RegisterDeviceNotificationW")
)

此处是我需要发送有效处理程序的位置

func RegisterDeviceNotification(handle windows.Handle) error {

    var notificationFilter DevBroadcastDevinterface
    notificationFilter.dwSize = uint32(unsafe.Sizeof(notificationFilter))
    notificationFilter.dwDeviceType = DBT_DEVTYP_DEVICEINTERFACE
    notificationFilter.dwReserved = 0
    // BUG(pastarmovj): This class is ignored for now. Figure out what the right GUID is.
    notificationFilter.classGuid = PRINTERS_DEVICE_CLASS
    notificationFilter.szName = 0

    r1, _, err := registerDeviceNotificationProc.Call(uintptr(handle), uintptr(unsafe.Pointer(&notificationFilter)), DEVICE_NOTIFY_SERVICE_HANDLE|DEVICE_NOTIFY_ALL_INTERFACE_CLASSES)
    if r1 == 0 {
        return err
    }
    return nil
}

调用函数

func (m *myservice) Execute(args []string, r <-chan svc.ChangeRequest, changes chan<- svc.Status) (ssec bool, errno uint32) {
    h := windows.Handle(uintptr(unsafe.Pointer(m)))
    err := RegisterDeviceNotification(h)

    fmt.Println(err)
}

注意:我也尝试了"myService"的指针:

h := windows.Handle(uintptr(unsafe.Pointer(m)))
err := RegisterDeviceNotification(h)

检索当前进程的伪句柄。

h, err := syscall.GetCurrentProcess()
err = RegisterDeviceNotification(windows.Handle(h))

问题是:* * 如何在Go语言中获得进程的有效句柄?**
如果我的问题有任何问题,请告诉我以改进.

hfyxw5xn

hfyxw5xn1#

可以像这样使用syscall.GetCurrentProcess()。

package main

import (
    "fmt"
    "syscall"
    "unsafe"
)

func main() {
    kernel32, err := syscall.LoadDLL("kernel32.dll")
    if err != nil {
        fmt.Println(err)
    }
    defer kernel32.Release()

    proc, err := kernel32.FindProc("IsWow64Process")
    if err != nil {
        fmt.Println(err)
    }

    handle, err := syscall.GetCurrentProcess()
    if err != nil {
        fmt.Println(err)
    }

    var result bool

    _, _, msg := proc.Call(uintptr(handle), uintptr(unsafe.Pointer(&result)))

    fmt.Printf("%v\n", msg)
}
dsekswqp

dsekswqp2#

import (
    "context"
    "encoding/json"
    "fmt"
    "os"
    "os/exec"
    "strings"
    "syscall"
    "time"
    "unsafe"
    "golang.org/x/sys/windows"
)

func main() {
    ProcessUtils{}.SetWinNice(13716, windows.HIGH_PRIORITY_CLASS)
}

var (
    kernel32        = syscall.MustLoadDLL("kernel32.dll")
    procOpenProcess = kernel32.MustFindProc("OpenProcess")
)

const PROCESS_ALL_ACCESS = 0x1F0FFF

type ProcessUtils struct {
}

func (ProcessUtils) GetProcessHandle(pid int) windows.Handle {
    handle, _, _ := procOpenProcess.Call(ToUintptr(PROCESS_ALL_ACCESS), ToUintptr(true), ToUintptr(pid))
    return windows.Handle(handle)
}

func (u ProcessUtils) SetWinNice(pid int, priority uint32) error {
    handle := u.GetProcessHandle(pid)
    return windows.SetPriorityClass(handle, priority)
}
func ToUintptr(val interface{}) uintptr {
    switch t := val.(type) {
    case string:
        p, _ := syscall.UTF16PtrFromString(val.(string))
        return uintptr(unsafe.Pointer(p))
    case int:
        return uintptr(val.(int))
    default:
        _ = t
        return uintptr(0)
    }
}
gstyhher

gstyhher3#

这是我不久前写的一些代码来处理这个问题,上次我检查的时候它还在工作。我已经为一堆winapi调用创建了 Package 函数。

package main

import "syscall"

// import the required winapi DLLs and functions
var (
    dllKernel32 := syscall.NewLazyDLL("kernel32.dll")
    procOpenProcess = dllKernel32.NewProc("OpenProcess")
    procCloseHandle = dllKernel32.NewProc("CloseHandle")
)

// when passing this to the OpenProcess function it will get
// a handle with the PROCESS_ALL_ACCESS permissions
const PROCESS_ALL_ACCESS = STANDARD_RIGHTS_REQUIRED | SYNCHRONIZE | uintptr(0xFFFF)

func main() {
    pid := uint32(123456)
    inheritHandle := uint32(1)

    handle, err := OpenProcess(PROCESS_ALL_ACCESS, inheritHandle, pid)
   
    if err != nil {
        panic(err)
    }
    
    ... // whatever your code wants to do

    err = CloseHandle(handle)

    if err != nil {
        panic(err)
    }

}

// Wraps the winapi OpenProcess function
func OpenProcess(desiredAccess uintptr, inheritHandle uint32, pid uint32) (uintptr, error) {
    // call the winapi function to get a handle
    handle, _, err := procOpenProcess.Call(desiredAccess, uintptr(inheritHandle), uintptr(pid))

    // check for errors
    if handle == 0 || err != nil {
        return r1, err
    }

    // return the handle
    return handle, nil
}

// Wraps the winapi CloseHandle function
func CloseHandle(handle uintptr) error {
    // call the winapi function to close the handle
    r, _, err := procCloseHandle.Call(handle)

    // check for errors
    if r == 0 || err != nil {
        return r1, err
    }

    return nil
}

我希望这些评论足以让你度过难关,如果你有任何问题,请告诉我。
确保在使用完句柄后将其关闭,不希望无限期地保持随机句柄打开。
以下是一些资源,可以帮助您了解正在发生的事情:
https://learn.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-openprocess
https://learn.microsoft.com/en-us/windows/win32/api/handleapi/nf-handleapi-closehandle
https://learn.microsoft.com/en-us/windows/win32/procthread/process-security-and-access-rights

相关问题