//go:build windows package backend_golang import ( "bufio" "context" "errors" "io" "os" "os/exec" "path/filepath" "strings" "time" su "github.com/nyaosorg/go-windows-su" wsl "github.com/ubuntu/gowsl" wruntime "github.com/wailsapp/wails/v2/pkg/runtime" ) var distro *wsl.Distro var stdin io.WriteCloser var cmd *exec.Cmd func isWslRunning() (bool, error) { if distro == nil { return false, nil } state, err := distro.State() if err != nil { return false, err } if state != wsl.Running { distro = nil return false, nil } return true, nil } func (a *App) WslStart() error { running, err := isWslRunning() if err != nil { return err } if running { return nil } distros, err := wsl.RegisteredDistros(context.Background()) if err != nil { return err } for _, d := range distros { if strings.Contains(d.Name(), "Ubuntu") { distro = &d break } } if distro == nil { return errors.New("ubuntu not found") } cmd = exec.Command("wsl", "-d", distro.Name(), "-u", "root") stdin, err = cmd.StdinPipe() if err != nil { return err } stdout, err := cmd.StdoutPipe() cmd.Stderr = cmd.Stdout if err != nil { // stdin.Close() stdin = nil return err } go func() { reader := bufio.NewReader(stdout) for { if stdin == nil { break } line, _, err := reader.ReadLine() if err != nil { wruntime.EventsEmit(a.ctx, "wslerr", err.Error()) break } wruntime.EventsEmit(a.ctx, "wsl", string(line)) } // stdout.Close() }() if err := cmd.Start(); err != nil { return err } return nil } func (a *App) WslCommand(command string) error { running, err := isWslRunning() if err != nil { return err } if !running { return errors.New("wsl not running") } _, err = stdin.Write([]byte(command + "\n")) if err != nil { return err } return nil } func (a *App) WslStop() error { running, err := isWslRunning() if err != nil { return err } if !running { return errors.New("wsl not running") } if cmd != nil { err = cmd.Process.Kill() cmd = nil } // stdin.Close() stdin = nil distro = nil if err != nil { return err } return nil } func (a *App) WslIsEnabled() error { ex, err := os.Executable() if err != nil { return err } exDir := filepath.Dir(ex) data, err := os.ReadFile(exDir + "/wsl.state") if err == nil { if strings.Contains(string(data), "Enabled") { return nil } } cmd := `-Command (Get-WindowsOptionalFeature -Online -FeatureName Microsoft-Windows-Subsystem-Linux).State | Out-File -Encoding utf8 -FilePath ` + exDir + "/wsl.state" _, err = su.ShellExecute(su.RUNAS, "powershell", cmd, exDir) if err != nil { return err } time.Sleep(2 * time.Second) data, err = os.ReadFile(exDir + "/wsl.state") if err != nil { return err } if strings.Contains(string(data), "Enabled") { return nil } else { return errors.New("wsl is not enabled") } } func (a *App) WslEnable(forceMode bool) error { cmd := `/online /enable-feature /featurename:Microsoft-Windows-Subsystem-Linux` _, err := su.ShellExecute(su.RUNAS, "dism", cmd, `C:\`) if err != nil { return err } if forceMode { os.WriteFile("./wsl.state", []byte("Enabled"), 0644) } return nil } func (a *App) WslInstallUbuntu() error { _, err := Cmd("ms-windows-store://pdp/?ProductId=9PN20MSR04DW") return err }