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 }