All checks were successful
PR Check / check (pull_request) Successful in 58s
Three Windows install/launch issues reported by the user:
1. Double-click on Desktop shortcut → dialog "This is a command line
tool. You need to open cmd.exe and run it from there."
Cause: charmbracelet/huh detects no TTY when launched via Explorer
and aborts. Fix:
- cmd/muyue/commands/root.go: skip RunFirstTimeSetup when
os.Stdin is not a character device; persist config.Default()
and let the React onboarding wizard handle first-run UX.
- ci-{main,develop}.yml: build Windows binaries with
-ldflags="-H=windowsgui" so the .exe is a GUI subsystem app —
no console window flashes on double-click.
2. CLI sub-commands (`muyue scan`, `muyue install-shortcuts`, etc.)
would lose all output under -H=windowsgui when launched from
cmd.exe / PowerShell. Mitigation:
- cmd/muyue/console_windows.go (new, build-tagged): on init(),
call kernel32!AttachConsole(ATTACH_PARENT_PROCESS). If the
parent has a console, rebind os.Stdout/os.Stderr/os.Stdin to
it and call log.SetOutput(os.Stderr) so existing log.Printf
calls surface. If no parent console (Explorer), exit silently.
3. After install, `muyue` not recognized in PowerShell.
Causes: (a) the extracted binary is muyue-windows-amd64.exe, not
muyue.exe; (b) the user PATH update by install-shortcuts doesn't
propagate to the existing PowerShell session.
Fix in install-shortcuts:
- Copy self to <installDir>/muyue.exe (rename impossible — the
running .exe is locked on Windows) so `muyue` resolves once
PATH is set.
- Update Desktop + Start Menu .lnk to target the canonical
muyue.exe rather than the platform-suffixed binary.
- Print the line `$env:Path += ';<installDir>'` for the user to
paste, refreshing the current session immediately.
- ci-main.yml install snippet bumps to 5 lines, last being
`$env:Path += ";$dest"`.
- internal/version/version.go: 0.7.4 → 0.7.5
- CHANGELOG.md: v0.7.5 entry covers all three fixes
55 lines
1.9 KiB
Go
55 lines
1.9 KiB
Go
//go:build windows
|
|
|
|
package main
|
|
|
|
// Windows-only: with -H=windowsgui the binary is registered as a GUI
|
|
// subsystem app, so double-clicking from the Desktop shortcut does NOT
|
|
// spawn a console window (good for the desktop UX). The downside is that
|
|
// sub-commands like `muyue scan`, `muyue version`, `muyue install-shortcuts`
|
|
// produce no output when invoked from cmd.exe.
|
|
//
|
|
// Workaround: at process start, try to attach to the parent's console via
|
|
// kernel32!AttachConsole(ATTACH_PARENT_PROCESS). If the parent has a console
|
|
// (i.e. we were launched from cmd.exe / PowerShell), stdout/stderr/stdin are
|
|
// rebound to it. If not (Explorer double-click), the call fails silently and
|
|
// the binary runs without any console — exactly what we want.
|
|
|
|
import (
|
|
"log"
|
|
"os"
|
|
"syscall"
|
|
)
|
|
|
|
const attachParentProcess = ^uint32(0) // -1 cast to DWORD
|
|
|
|
func init() {
|
|
kernel32, err := syscall.LoadLibrary("kernel32.dll")
|
|
if err != nil {
|
|
return
|
|
}
|
|
defer syscall.FreeLibrary(kernel32)
|
|
attachConsole, err := syscall.GetProcAddress(kernel32, "AttachConsole")
|
|
if err != nil {
|
|
return
|
|
}
|
|
r0, _, _ := syscall.SyscallN(attachConsole, uintptr(attachParentProcess))
|
|
if r0 == 0 {
|
|
return // parent has no console (Explorer launch) — stay silent
|
|
}
|
|
// Re-bind the standard streams to the freshly attached console so
|
|
// fmt.Println / log output appear in the parent terminal.
|
|
if h, err := syscall.GetStdHandle(syscall.STD_OUTPUT_HANDLE); err == nil && h != 0 {
|
|
os.Stdout = os.NewFile(uintptr(h), "stdout")
|
|
}
|
|
if h, err := syscall.GetStdHandle(syscall.STD_ERROR_HANDLE); err == nil && h != 0 {
|
|
os.Stderr = os.NewFile(uintptr(h), "stderr")
|
|
}
|
|
if h, err := syscall.GetStdHandle(syscall.STD_INPUT_HANDLE); err == nil && h != 0 {
|
|
os.Stdin = os.NewFile(uintptr(h), "stdin")
|
|
}
|
|
// log.Default() captured the original os.Stderr at init time — repoint it
|
|
// at the freshly attached console so log.Printf calls (e.g. desktop.Run)
|
|
// surface in the parent terminal.
|
|
log.SetOutput(os.Stderr)
|
|
}
|