180 lines
3.2 KiB
Go
180 lines
3.2 KiB
Go
//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")
|
|
}
|
|
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
|
|
}
|