go-toast

Send toast notifications in Windows
Log | Files | Refs | README | LICENSE

commit 8da8bfc2fa3fcce7958093e99235ec3290ccb578
parent 9c52d53929fd1a8d8ea54a4777022af9a8221753
Author: Jack Mordaunt <jackmordaunt.dev@gmail.com>
Date:   Wed, 15 Mar 2023 14:54:44 +0800

internal/bind: avoid re-initializing windows runtime

Reinit causes errors (eg subsequent invocations of RoInitialize).
This logic will retry on error though, to maximize recoverability.

Signed-off-by: Jack Mordaunt <jackmordaunt.dev@gmail.com>

Diffstat:
Minternal/bind/bind.go | 29+++++++++++++++++++++++++++--
1 file changed, 27 insertions(+), 2 deletions(-)

diff --git a/internal/bind/bind.go b/internal/bind/bind.go @@ -5,6 +5,7 @@ import ( "errors" "fmt" "path/filepath" + "sync" "syscall" "unicode/utf16" "unsafe" @@ -72,13 +73,37 @@ func ConfigureRegistry(appID, appDisplayName, backgroundColor, exePath string) e return nil } +var initLock sync.Mutex +var didInitialize bool + +// initialize attempts to initialize the Windows Runtime. +// Each invocation will retry RoInitialize until a successful initialization +// is achieved. Once initialized, we avoid invoking RoInitialize since subsequent +// reinitialization generates errors. +func initialize() (err error) { + initLock.Lock() + defer initLock.Unlock() + + if didInitialize { + return nil + } + + if err := ole.RoInitialize(1); err != nil { + return fmt.Errorf("RoInitialize: %w", err) + } + + didInitialize = true + + return nil +} + // GenerateToast notification via the specified xml content. // // No validation is performed on this xml content and the caller assumes responsibility // for ensuring it's validity. func GenerateToast(appID, xml string) error { - if err := ole.RoInitialize(1); err != nil { - return fmt.Errorf("RoInitialize: %w", err) + if err := initialize(); err != nil { + return err } xmlStr, err := syscall.UTF16PtrFromString(xml)