单例锁
单例锁是一种机制,允许您防止您的应用程序的多个实例同时运行。它对于旨在从命令行或操作系统文件资源管理器打开文件的应用程序很有用。
重要
单例锁不会在实例之间实现安全的通信协议。使用单例锁时,您的应用程序应将从第二个实例回调传递给它的任何数据视为不可信。您应验证您收到的参数是否有效,并且不包含任何恶意数据。
它是如何工作的
Windows: 单例锁是使用命名互斥锁实现的。互斥锁名称由您提供的唯一 ID 生成。数据通过共享窗口使用 SendMessage 传递给第一个实例 macOS: 单例锁是使用命名互斥锁实现的。互斥锁名称由您提供的唯一 ID 生成。数据通过 NSDistributedNotificationCenter 传递给第一个实例 Linux: 单例锁是使用 dbus 实现的。dbus 名称由您提供的唯一 ID 生成。数据通过 dbus 传递给第一个实例
用法
创建应用程序时,您可以通过将 SingleInstanceLock
结构体传递给 App
结构体来启用单例锁。使用 UniqueId
字段指定应用程序的唯一 ID。此 ID 用于在 Windows 和 macOS 上生成互斥锁名称,以及在 Linux 上生成 dbus 名称。使用 UUID 以确保 ID 唯一。OnSecondInstanceLaunch
字段用于指定在应用程序的第二个实例启动时调用的回调。回调接收 SecondInstanceData
结构体,其中包含传递给第二个实例的命令行参数和第二个实例的工作目录。
请注意,OnSecondInstanceLaunch 不会触发窗口焦点。您需要调用 runtime.WindowUnminimise
和 runtime.Show
以将您的应用程序带到最前面。请注意,在 Linux 系统上,窗口管理器可能会阻止您的应用程序被带到最前面,以避免抢占焦点。
var wailsContext *context.Context
// NewApp creates a new App application struct
func NewApp() *App {
return &App{}
}
// startup is called when the app starts. The context is saved
// so we can call the runtime methods
func (a *App) startup(ctx context.Context) {
wailsContext = &ctx
}
func (a *App) onSecondInstanceLaunch(secondInstanceData options.SecondInstanceData) {
secondInstanceArgs = secondInstanceData.Args
println("user opened second instance", strings.Join(secondInstanceData.Args, ","))
println("user opened second from", secondInstanceData.WorkingDirectory)
runtime.WindowUnminimise(*wailsContext)
runtime.Show(*wailsContext)
go runtime.EventsEmit(*wailsContext, "launchArgs", secondInstanceArgs)
}
func main() {
// Create an instance of the app structure
app := NewApp()
// Create application with options
err := wails.Run(&options.App{
Title: "wails-open-file",
Width: 1024,
Height: 768,
AssetServer: &assetserver.Options{
Assets: assets,
},
BackgroundColour: &options.RGBA{R: 27, G: 38, B: 54, A: 1},
OnStartup: app.startup,
SingleInstanceLock: &options.SingleInstanceLock{
UniqueId: "e3984e08-28dc-4e3d-b70a-45e961589cdc",
OnSecondInstanceLaunch: app.onSecondInstanceLaunch,
},
Bind: []interface{}{
app,
},
})
if err != nil {
println("Error:", err.Error())
}
}