单实例
将应用限制为仅运行一个实例
单实例锁是一种防止应用同时运行多个实例的机制。 它适用于设计为从命令行或操作系统文件资源管理器打开文件的应用。
用法
要在应用中启用单实例功能,请在创建应用时提供一个SingleInstanceOptions结构体:
go
app := application.New(application.Options{
// ... other options ...
SingleInstance: &application.SingleInstanceOptions{
UniqueID: "com.myapp.unique-id",
OnSecondInstanceLaunch: func(data application.SecondInstanceData) {
log.Printf("Second instance launched with args: %v", data.Args)
log.Printf("Working directory: %s", data.WorkingDir)
log.Printf("Additional data: %v", data.AdditionalData)
},
// Optional: Pass additional data to second instance
AdditionalData: map[string]string{
"launchtime": time.Now().String(),
},
},
})SingleInstanceOptions结构体包含以下字段:
-
UniqueID:应用的唯一标识符。它应为唯一字符串,通常采用反向域名表示法(例如“com.company.appname”)。 -
EncryptionKey:可选的32字节数组,用于通过AES-256-GCM加密实例之间传递的数据。如果提供的数组不全为零,则实例之间的所有通信都会被加密。 -
OnSecondInstanceLaunch:启动应用的第二个实例时调用的回调函数。该回调会接收一个SecondInstanceData结构体,其中包含:Args:传递给第二个实例的命令行参数WorkingDir:第二个实例的工作目录AdditionalData:从第二个实例传递的任何附加数据(如果提供)
-
AdditionalData:可选的字符串键值对映射,启动后续实例时会将其传递给第一个实例
安全通信
要启用实例之间的安全通信,请提供一个32字节的加密密钥。应用的所有实例都必须使用相同的密钥:
go
// Define your encryption key (must be exactly 32 bytes)
var encryptionKey = [32]byte{
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
}
// Use the key in SingleInstanceOptions
SingleInstance: &application.SingleInstanceOptions{
UniqueID: "com.myapp.unique-id",
// Enable encryption for instance communication
EncryptionKey: encryptionKey,
// ... other options ...
}窗口管理
处理第二个实例的启动时,通常需要将应用窗口置于最前。可以使用窗口的Focus()方法执行此操作。如果窗口已最小化,可能需要先将其还原:
go
var mainWindow *application.WebviewWindow
SingleInstance: &application.SingleInstanceOptions{
// Other options...
OnSecondInstanceLaunch: func(data application.SecondInstanceData) {
// Focus the window if needed
if mainWindow != nil {
mainWindow.Restore()
mainWindow.Focus()
}
},
}工作原理
使用命名互斥体实现单实例锁。互斥体名称根据你提供的唯一ID生成。数据通过NSDistributedNotificationCenter传递给第一个实例。
使用命名互斥体实现单实例锁。互斥体名称根据你提供的唯一ID生成。数据通过使用SendMessage的共享窗口传递给第一个实例。