clientupdate, util/osshare, util/winutil, version: improve Windows GUI filename resolution and WinUI build awareness

On Windows arm64 we are going to need to ship two different GUI builds;
one for Win10 (GOARCH=386) and one for Win11 (GOARCH=amd64, tags +=
winui). Due to quirks in MSI packaging, they cannot both share the
same filename. This requires some fixes in places where we have
hardcoded "tailscale-ipn" as the GUI filename.

We also do some cleanup in clientupdate to ensure that autoupdates
will continue to work correctly with the temporary "-winui" package
variant.

Fixes #17480
Updates https://github.com/tailscale/corp/issues/29940

Signed-off-by: Aaron Klotz <aaron@tailscale.com>
This commit is contained in:
Aaron Klotz
2025-09-29 11:44:23 -06:00
parent e45557afc0
commit 7c49cab1a6
7 changed files with 146 additions and 33 deletions
+25
View File
@@ -8,8 +8,10 @@ import (
"fmt"
"log"
"math"
"os"
"os/exec"
"os/user"
"path/filepath"
"reflect"
"runtime"
"strings"
@@ -33,6 +35,10 @@ var ErrNoShell = errors.New("no Shell process is present")
// ErrNoValue is returned when the value doesn't exist in the registry.
var ErrNoValue = registry.ErrNotExist
// ErrBadRegValueFormat is returned when a string value does not match the
// expected format.
var ErrBadRegValueFormat = errors.New("registry value formatted incorrectly")
// GetDesktopPID searches the PID of the process that's running the
// currently active desktop. Returns ErrNoShell if the shell is not present.
// Usually the PID will be for explorer.exe.
@@ -947,3 +953,22 @@ func IsDomainName(name string) (bool, error) {
return isDomainName(name16)
}
// GUIPathFromReg obtains the path to the client GUI executable from the
// registry value that was written during installation.
func GUIPathFromReg() (string, error) {
regPath, err := GetRegString("GUIPath")
if err != nil {
return "", err
}
if !filepath.IsAbs(regPath) {
return "", ErrBadRegValueFormat
}
if _, err := os.Stat(regPath); err != nil {
return "", err
}
return regPath, nil
}