- 互斥体防多开/ShellExecute/窗口类名与标题查询/顶层窗口目录, 新增依赖 lxn/win - 仅 Windows, 附测试、examples/dll 例程与包 README
77 lines
2.1 KiB
Go
77 lines
2.1 KiB
Go
package dll
|
|
|
|
import (
|
|
"fmt"
|
|
"github.com/lxn/win"
|
|
"syscall"
|
|
"unsafe"
|
|
)
|
|
|
|
// CreateMutex 创建命名互斥体(常用于防止程序多开)
|
|
// bInitialOwner 为是否立即持有;互斥体已存在时返回错误(错误码 183)
|
|
func CreateMutex(bInitialOwner bool, mutexName string) (syscall.Handle, error) {
|
|
|
|
// 互斥体名需转为 UTF-16 指针(LPCWSTR),不能直接传 Go string 的地址
|
|
namePtr, nameErr := syscall.UTF16PtrFromString(mutexName)
|
|
if nameErr != nil {
|
|
return 0, nameErr
|
|
}
|
|
|
|
handle, _, err := syscall.SyscallN(procCreateMutexW.Addr(), 0, uintptr(win.BoolToBOOL(bInitialOwner)), uintptr(unsafe.Pointer(namePtr)))
|
|
if err != 0 {
|
|
println(err.Error())
|
|
|
|
lastError := win.GetLastError()
|
|
fmt.Println("lastError", lastError)
|
|
if lastError == 183 {
|
|
fmt.Println("Mutex 已经存在")
|
|
}
|
|
|
|
return 0, err
|
|
}
|
|
//defer syscall.CloseHandle(syscall.Handle(m))
|
|
if syscall.Handle(handle) != 0 {
|
|
lastError := win.GetLastError()
|
|
if lastError == 183 {
|
|
//fmt.Println("Mutex 已经存在")
|
|
}
|
|
|
|
}
|
|
// do something with the mutex
|
|
return syscall.Handle(handle), nil
|
|
}
|
|
|
|
// MUTANT_ALL_ACCESS 互斥体的完全访问权限
|
|
const MUTANT_ALL_ACCESS = 2031617
|
|
|
|
// OpenMutex 打开已存在的命名互斥体
|
|
func OpenMutex(bInheritHandle bool, mutexName string) (syscall.Handle, error) {
|
|
desiredAccess := MUTANT_ALL_ACCESS
|
|
handle, _, err := syscall.SyscallN(procOpenMutexW.Addr(), uintptr(desiredAccess), uintptr(win.BoolToBOOL(bInheritHandle)), uintptr(unsafe.Pointer(&mutexName)))
|
|
if err != 0 {
|
|
return 0, err
|
|
}
|
|
defer syscall.CloseHandle(syscall.Handle(handle))
|
|
if syscall.Handle(handle) == 0 {
|
|
e2 := win.GetLastError()
|
|
if e2 == 183 {
|
|
fmt.Println("打开失败")
|
|
}
|
|
fmt.Println(e2)
|
|
|
|
} // do something with the mutex
|
|
fmt.Println("Mutex open", syscall.Handle(handle))
|
|
return syscall.Handle(handle), nil
|
|
}
|
|
|
|
// ReleaseMutex 释放互斥体持有权
|
|
func ReleaseMutex(handle syscall.Handle) bool {
|
|
// 传句柄值本身,而非句柄变量的地址
|
|
ret, _, e1 := syscall.SyscallN(procReleaseMutex.Addr(), uintptr(handle))
|
|
if e1 != 0 {
|
|
println(e1.Error())
|
|
return false
|
|
}
|
|
return ret != 0
|
|
}
|