// vpnem-installer: Windows installer (GUI, no console window). // Installs to Program Files, creates Task Scheduler task for UAC-free launch. // Requires admin (one-time). Supports silent mode: vpnem-installer.exe /S // Cross-compiles from Linux with -ldflags "-H windowsgui" package main import ( "fmt" "io" "log" "net/http" "os" "os/exec" "path/filepath" "strings" "time" ) const ( installDir = `C:\Program Files\vpnem` dataDir = `C:\ProgramData\vpnem` taskName = "vpnem" baseURL = "https://vpn.em-sysadmin.xyz/releases" vpnemURL = baseURL + "/vpnem-windows-amd64.exe" singboxURL = baseURL + "/sing-box.exe" wintunURL = baseURL + "/wintun.dll" ) var ( silent bool noShortcut bool launch bool logFile *os.File ) func main() { // Parse flags for _, arg := range os.Args[1:] { a := strings.ToLower(strings.TrimLeft(arg, "/-")) switch a { case "s", "silent": silent = true case "noshortcut": noShortcut = true case "launch": launch = true } } os.MkdirAll(installDir, 0o755) os.MkdirAll(dataDir, 0o755) // Log to data dir lf, err := os.Create(filepath.Join(dataDir, "install.log")) if err == nil { logFile = lf defer lf.Close() log.SetOutput(lf) } step("vpnem installer started") step("install dir: " + installDir) step("data dir: " + dataDir) // Kill running instances step("stopping running instances") exec.Command("taskkill", "/F", "/IM", "vpnem.exe").Run() time.Sleep(time.Second) // Clean stale configs step("cleaning old state") for _, f := range []string{"state.json", "config.json", "cache.db"} { os.Remove(filepath.Join(dataDir, f)) os.Remove(filepath.Join(installDir, f)) // Also clean old C:\ProxySwitcher location os.Remove(filepath.Join(`C:\ProxySwitcher`, f)) } // Download vpnem.exe step("downloading vpnem") if err := download(vpnemURL, filepath.Join(installDir, "vpnem.exe")); err != nil { fatal("download vpnem: %v", err) } // Download sing-box 1.11 (external subprocess, proven to work) downloadIfMissing("sing-box.exe", singboxURL) // Download wintun.dll downloadIfMissing("wintun.dll", wintunURL) // Create Task Scheduler task — runs vpnem as admin WITHOUT UAC prompt. // This is the key: task created by admin runs with highest privileges silently. step("creating scheduled task (UAC-free launch)") createTask() // Desktop shortcut — launches via schtasks (no UAC popup) if !noShortcut { step("creating desktop shortcut") createShortcut() } step("installation complete") if launch { step("launching vpnem") exec.Command("schtasks", "/Run", "/TN", taskName).Run() } if !silent { showDoneMessage() } } // createTask sets up a scheduled task that: // 1. Runs vpnem.exe with highest privileges (no UAC) // 2. Starts at logon with 15s delay (autostart) // The same task is used for both manual launch and autostart. func createTask() { exec.Command("schtasks", "/Delete", "/TN", taskName, "/F").Run() // Create XML task definition for full control exePath := filepath.Join(installDir, "vpnem.exe") xml := fmt.Sprintf(` vpnem VPN client true PT15S InteractiveToken HighestAvailable IgnoreNew false false PT0S true true %s --data "%s" %s `, exePath, dataDir, installDir) xmlPath := filepath.Join(dataDir, "task.xml") os.WriteFile(xmlPath, []byte(xml), 0o644) cmd := exec.Command("schtasks", "/Create", "/TN", taskName, "/XML", xmlPath, "/F") out, err := cmd.CombinedOutput() if err != nil { log.Printf("task create failed: %v\n%s", err, string(out)) } else { log.Println("task created ok") } os.Remove(xmlPath) } // createShortcut makes a desktop shortcut that runs the scheduled task (no UAC) // IconLocation points to vpnem.exe so the shortcut has the app icon func createShortcut() { exePath := filepath.Join(installDir, "vpnem.exe") ps := ` $ws = New-Object -ComObject WScript.Shell $s = $ws.CreateShortcut("$env:USERPROFILE\Desktop\vpnem.lnk") $s.TargetPath = "schtasks.exe" $s.Arguments = "/Run /TN vpnem" $s.WorkingDirectory = "` + installDir + `" $s.IconLocation = "` + exePath + `,0" $s.Description = "vpnem VPN client" $s.Save() ` cmd := exec.Command("powershell", "-NoProfile", "-WindowStyle", "Hidden", "-Command", ps) if err := cmd.Run(); err != nil { log.Printf("shortcut failed: %v (non-critical)", err) } } func step(msg string) { log.Println(msg) } func fatal(format string, args ...any) { msg := fmt.Sprintf(format, args...) log.Printf("FATAL: %s", msg) if silent { os.Exit(1) } showError(msg) os.Exit(1) } func download(url, dest string) error { client := &http.Client{Timeout: 5 * time.Minute} resp, err := client.Get(url) if err != nil { return err } defer resp.Body.Close() if resp.StatusCode != http.StatusOK { return fmt.Errorf("HTTP %d", resp.StatusCode) } tmp := dest + ".tmp" f, err := os.Create(tmp) if err != nil { return err } written, err := io.Copy(f, resp.Body) f.Close() if err != nil { os.Remove(tmp) return err } log.Printf(" %s (%.1f MB)", filepath.Base(dest), float64(written)/1024/1024) return os.Rename(tmp, dest) } func downloadIfMissing(filename, url string) { path := filepath.Join(installDir, filename) if _, err := os.Stat(path); os.IsNotExist(err) { step("downloading " + filename) if err := download(url, path); err != nil { fatal("download %s: %v", filename, err) } } else { step(filename + " already present, skipping") } } func showDoneMessage() { msg := fmt.Sprintf("vpnem installed to %s\\n\\nDesktop shortcut created.\\nAutostart at logon enabled.\\n\\nNo admin prompts needed to launch.", installDir) exec.Command("powershell", "-NoProfile", "-WindowStyle", "Hidden", "-Command", fmt.Sprintf(`Add-Type -AssemblyName System.Windows.Forms; [System.Windows.Forms.MessageBox]::Show("%s", "vpnem installer", "OK", "Information")`, msg), ).Run() } func showError(msg string) { exec.Command("powershell", "-NoProfile", "-WindowStyle", "Hidden", "-Command", fmt.Sprintf(`Add-Type -AssemblyName System.Windows.Forms; [System.Windows.Forms.MessageBox]::Show("Installation failed:\n%s", "vpnem installer", "OK", "Error")`, msg), ).Run() }