From 821bf3e80b1db9de826100e7b03577d690c5d7bf Mon Sep 17 00:00:00 2001 From: rsteube Date: Sun, 8 Dec 2024 14:47:34 +0100 Subject: [PATCH] windows: swap executable --- selfupdate.go | 7 +------ swap.go | 12 ++++++++++++ swap_windows.go | 46 ++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 59 insertions(+), 6 deletions(-) create mode 100644 swap.go create mode 100644 swap_windows.go diff --git a/selfupdate.go b/selfupdate.go index 3917b31..a91efb7 100644 --- a/selfupdate.go +++ b/selfupdate.go @@ -230,12 +230,7 @@ func (c config) Install(tag, asset string) error { } } - c.Printf("moving to %#v\n", target) - if err = os.Rename(fExecutable.Name(), target); err != nil { - return err - } - - return nil + return c.swap(fExecutable.Name(), target) } func (c config) verify(executable string) error { diff --git a/swap.go b/swap.go new file mode 100644 index 0000000..eba4088 --- /dev/null +++ b/swap.go @@ -0,0 +1,12 @@ +//go:build !windows + +package selfupdate + +import ( + "os" +) + +func (c config) swap(source, target string) error { + c.Printf("moving to %#v\n", target) + return os.Rename(source, target) +} diff --git a/swap_windows.go b/swap_windows.go new file mode 100644 index 0000000..31992ce --- /dev/null +++ b/swap_windows.go @@ -0,0 +1,46 @@ +package selfupdate + +import ( + "os" + "syscall" +) + +func (c config) swap(source, target string) error { + old := target + ".old" + if _, err := os.Stat(old); err == nil { + if err := c.confirm("remove %#v\n", old); err != nil { + return err + } + if err := os.Remove(old); err != nil { + return err + } + } + + c.Printf("moving current executable to %#v\n", old) + if err := os.Rename(target, old); err != nil { + return err + } + + c.Printf("moving new executable to %#v\n", target) + if err := os.Rename(source, target); err != nil { + _ = os.Rename(old, target) // try to restore old executable + return err + } + + c.Printf("hiding %#v\n", old) + return hide(old) +} + +func hide(path string) error { + p, err := syscall.UTF16PtrFromString(path) + if err != nil { + return err + } + + err = syscall.SetFileAttributes(p, syscall.FILE_ATTRIBUTE_HIDDEN) + if err != nil { + return err + } + + return nil +}