mirror of
https://github.com/wailsapp/wails.git
synced 2025-05-03 06:39:30 +08:00
169 lines
4.4 KiB
Go
169 lines
4.4 KiB
Go
//go:build windows
|
|
// +build windows
|
|
|
|
package webview2runtime
|
|
|
|
import (
|
|
_ "embed"
|
|
"fmt"
|
|
"io"
|
|
"net/http"
|
|
"os"
|
|
"os/exec"
|
|
"path/filepath"
|
|
"syscall"
|
|
"unsafe"
|
|
)
|
|
|
|
//go:embed MicrosoftEdgeWebview2Setup.exe
|
|
var setupexe []byte
|
|
|
|
// Info contains all the information about an installation of the webview2 runtime.
|
|
type Info struct {
|
|
Location string
|
|
Name string
|
|
Version string
|
|
SilentUninstall string
|
|
}
|
|
|
|
// IsOlderThan returns true if the installed version is older than the given required version.
|
|
// Returns error if something goes wrong.
|
|
func (i *Info) IsOlderThan(requiredVersion string) (bool, error) {
|
|
var mod = syscall.NewLazyDLL("WebView2Loader.dll")
|
|
var CompareBrowserVersions = mod.NewProc("CompareBrowserVersions")
|
|
v1, err := syscall.UTF16PtrFromString(i.Version)
|
|
if err != nil {
|
|
return false, err
|
|
}
|
|
v2, err := syscall.UTF16PtrFromString(requiredVersion)
|
|
if err != nil {
|
|
return false, err
|
|
}
|
|
var result int = 9
|
|
_, _, err = CompareBrowserVersions.Call(uintptr(unsafe.Pointer(v1)), uintptr(unsafe.Pointer(v2)), uintptr(unsafe.Pointer(&result)))
|
|
if result < -1 || result > 1 {
|
|
return false, err
|
|
}
|
|
return result == -1, nil
|
|
}
|
|
|
|
func downloadBootstrapper() (string, error) {
|
|
bootstrapperURL := `https://go.microsoft.com/fwlink/p/?LinkId=2124703`
|
|
installer := filepath.Join(os.TempDir(), `MicrosoftEdgeWebview2Setup.exe`)
|
|
|
|
// Download installer
|
|
out, err := os.Create(installer)
|
|
defer out.Close()
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
resp, err := http.Get(bootstrapperURL)
|
|
defer resp.Body.Close()
|
|
if err != nil {
|
|
err = out.Close()
|
|
return "", err
|
|
}
|
|
_, err = io.Copy(out, resp.Body)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
|
|
return installer, nil
|
|
}
|
|
|
|
// InstallUsingEmbeddedBootstrapper will download the bootstrapper from Microsoft and run it to install
|
|
// the latest version of the runtime.
|
|
// Returns true if the installer ran successfully.
|
|
// Returns an error if something goes wrong
|
|
func InstallUsingEmbeddedBootstrapper() (bool, error) {
|
|
|
|
installer := filepath.Join(os.TempDir(), `MicrosoftEdgeWebview2Setup.exe`)
|
|
err := os.WriteFile(installer, setupexe, 0755)
|
|
if err != nil {
|
|
return false, err
|
|
}
|
|
result, err := runInstaller(installer)
|
|
if err != nil {
|
|
return false, err
|
|
}
|
|
|
|
return result, os.Remove(installer)
|
|
|
|
}
|
|
|
|
// InstallUsingBootstrapper will extract the embedded bootstrapper from Microsoft and run it to install
|
|
// the latest version of the runtime.
|
|
// Returns true if the installer ran successfully.
|
|
// Returns an error if something goes wrong
|
|
func InstallUsingBootstrapper() (bool, error) {
|
|
|
|
installer, err := downloadBootstrapper()
|
|
if err != nil {
|
|
return false, err
|
|
}
|
|
|
|
result, err := runInstaller(installer)
|
|
if err != nil {
|
|
return false, err
|
|
}
|
|
|
|
return result, os.Remove(installer)
|
|
|
|
}
|
|
|
|
func runInstaller(installer string) (bool, error) {
|
|
err := ShellExecuteAndWait(0, "runas", installer, "", os.Getenv("TMP"), syscall.SW_NORMAL)
|
|
if err != nil {
|
|
fmt.Println(err)
|
|
return false, err
|
|
}
|
|
return true, nil
|
|
}
|
|
|
|
// Confirm will prompt the user with a message and OK / CANCEL buttons.
|
|
// Returns true if OK is selected by the user.
|
|
// Returns an error if something went wrong.
|
|
func Confirm(caption string, title string) (bool, error) {
|
|
var flags uint = 0x00000001 // MB_OKCANCEL
|
|
result, err := MessageBox(caption, title, flags)
|
|
if err != nil {
|
|
return false, err
|
|
}
|
|
return result == 1, nil
|
|
}
|
|
|
|
// Error will an error message to the user.
|
|
// Returns an error if something went wrong.
|
|
func Error(caption string, title string) error {
|
|
var flags uint = 0x00000010 // MB_ICONERROR
|
|
_, err := MessageBox(caption, title, flags)
|
|
return err
|
|
}
|
|
|
|
// MessageBox prompts the user with the given caption and title.
|
|
// Flags may be provided to customise the dialog.
|
|
// Returns an error if something went wrong.
|
|
func MessageBox(caption string, title string, flags uint) (int, error) {
|
|
captionUTF16, err := syscall.UTF16PtrFromString(caption)
|
|
if err != nil {
|
|
return -1, err
|
|
}
|
|
titleUTF16, err := syscall.UTF16PtrFromString(title)
|
|
if err != nil {
|
|
return -1, err
|
|
}
|
|
ret, _, _ := syscall.NewLazyDLL("user32.dll").NewProc("MessageBoxW").Call(
|
|
uintptr(0),
|
|
uintptr(unsafe.Pointer(captionUTF16)),
|
|
uintptr(unsafe.Pointer(titleUTF16)),
|
|
uintptr(flags))
|
|
|
|
return int(ret), nil
|
|
}
|
|
|
|
// OpenInstallerDownloadWebpage will open the browser on the WebView2 download page
|
|
func OpenInstallerDownloadWebpage() error {
|
|
cmd := exec.Command("rundll32", "url.dll,FileProtocolHandler", "https://developer.microsoft.com/en-us/microsoft-edge/webview2/")
|
|
return cmd.Run()
|
|
}
|