Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve Windows stash behaviour #2543

Merged
merged 8 commits into from May 4, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
6 changes: 0 additions & 6 deletions Makefile
Expand Up @@ -50,12 +50,6 @@ ifndef OFFICIAL_BUILD
$(eval OFFICIAL_BUILD := false)
endif

ifdef IS_WIN_OS
ifndef SUPPRESS_WINDOWSGUI
PLATFORM_SPECIFIC_LDFLAGS := -H windowsgui
endif
endif

build: pre-build
build:
$(eval LDFLAGS := $(LDFLAGS) -X 'github.com/stashapp/stash/internal/api.version=$(STASH_VERSION)' -X 'github.com/stashapp/stash/internal/api.buildstamp=$(BUILD_DATE)' -X 'github.com/stashapp/stash/internal/api.githash=$(GITHASH)')
Expand Down
38 changes: 29 additions & 9 deletions cmd/stash/main.go
Expand Up @@ -7,7 +7,6 @@ import (
"os/signal"
"syscall"

"github.com/apenwarr/fixconsole"
"github.com/stashapp/stash/internal/api"
"github.com/stashapp/stash/internal/desktop"
"github.com/stashapp/stash/internal/manager"
Expand All @@ -17,24 +16,45 @@ import (
_ "github.com/golang-migrate/migrate/v4/source/file"
)

func init() {
// On Windows, attach to parent shell
err := fixconsole.FixConsoleIfNeeded()
func main() {
defer recoverPanic()

_, err := manager.Initialize()
if err != nil {
fmt.Printf("FixConsoleOutput: %v\n", err)
panic(err)
}
}

func main() {
manager.Initialize()
api.Start()
go func() {
defer recoverPanic()
if err := api.Start(); err != nil {
handleError(err)
} else {
manager.GetInstance().Shutdown(0)
}
}()

go handleSignals()
desktop.Start(manager.GetInstance(), &manager.FaviconProvider{UIBox: ui.UIBox})

blockForever()
}

func recoverPanic() {
if p := recover(); p != nil {
handleError(fmt.Errorf("Panic: %v", p))
}
}

func handleError(err error) {
desktop.FatalError(err)

if desktop.IsDesktop() {
manager.GetInstance().Shutdown(0)
} else {
panic(err)
}
}

func handleSignals() {
// handle signals
signals := make(chan os.Signal, 1)
Expand Down
2 changes: 0 additions & 2 deletions go.mod
Expand Up @@ -46,7 +46,6 @@ require (
)

require (
github.com/apenwarr/fixconsole v0.0.0-20191012055117-5a9f6489cc29
github.com/go-chi/httplog v0.2.1
github.com/go-toast/toast v0.0.0-20190211030409-01e6764cf0a4
github.com/hashicorp/golang-lru v0.5.4
Expand All @@ -60,7 +59,6 @@ require (
require (
github.com/agnivade/levenshtein v1.1.1 // indirect
github.com/antchfx/xpath v1.2.0 // indirect
github.com/apenwarr/w32 v0.0.0-20190407065021-aa00fece76ab // indirect
github.com/chromedp/sysutil v1.0.0 // indirect
github.com/cpuguy83/go-md2man/v2 v2.0.1 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
Expand Down
5 changes: 0 additions & 5 deletions go.sum
Expand Up @@ -97,10 +97,6 @@ github.com/antchfx/xpath v1.2.0/go.mod h1:i54GszH55fYfBmoZXapTHN8T8tkcHfRgLyVwwq
github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY=
github.com/apache/arrow/go/arrow v0.0.0-20200601151325-b2287a20f230/go.mod h1:QNYViu/X0HXDHw7m3KXzWSVXIbfUvJqBFe6Gj8/pYA0=
github.com/apache/arrow/go/arrow v0.0.0-20210521153258-78c88a9f517b/go.mod h1:R4hW3Ug0s+n4CUsWHKOj00Pu01ZqU4x/hSF5kXUcXKQ=
github.com/apenwarr/fixconsole v0.0.0-20191012055117-5a9f6489cc29 h1:muXWUcay7DDy1/hEQWrYlBy+g0EuwT70sBHg65SeUc4=
github.com/apenwarr/fixconsole v0.0.0-20191012055117-5a9f6489cc29/go.mod h1:JYWahgHer+Z2xbsgHPtaDYVWzeHDminu+YIBWkxpCAY=
github.com/apenwarr/w32 v0.0.0-20190407065021-aa00fece76ab h1:CMGzRRCjnD50RjUFSArBLuCxiDvdp7b8YPAcikBEQ+k=
github.com/apenwarr/w32 v0.0.0-20190407065021-aa00fece76ab/go.mod h1:nfFtvHn2Hgs9G1u0/J6LHQv//EksNC+7G8vXmd1VTJ8=
github.com/arbovm/levenshtein v0.0.0-20160628152529-48b4e1c0c4d0 h1:jfIu9sQUG6Ig+0+Ap1h4unLjW6YQJpKZVmUzxsD4E/Q=
github.com/arbovm/levenshtein v0.0.0-20160628152529-48b4e1c0c4d0/go.mod h1:t2tdKJDJF9BV14lnkjHmOQgcvEKgtqs5a1N3LNdJhGE=
github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o=
Expand Down Expand Up @@ -955,7 +951,6 @@ golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5h
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190403152447-81d4e9dc473e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190405154228-4b34438f7a67/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190415145633-3fd5a3612ccd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190419153524-e8e3143a4f4a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
Expand Down
24 changes: 13 additions & 11 deletions internal/api/server.go
Expand Up @@ -41,7 +41,7 @@ var githash string
var uiBox = ui.UIBox
var loginUIBox = ui.LoginUIBox

func Start() {
func Start() error {
initialiseImages()

r := chi.NewRouter()
Expand Down Expand Up @@ -263,16 +263,18 @@ func Start() {
displayAddress = "http://" + displayAddress + "/"
}

go func() {
if tlsConfig != nil {
logger.Infof("stash is running at " + displayAddress)
logger.Error(server.ListenAndServeTLS("", ""))
} else {
logger.Infof("stash is running at " + displayAddress)
logger.Error(server.ListenAndServe())
}
manager.GetInstance().Shutdown(0)
}()
logger.Infof("stash is running at " + displayAddress)
if tlsConfig != nil {
err = server.ListenAndServeTLS("", "")
} else {
err = server.ListenAndServe()
}

if !errors.Is(err, http.ErrServerClosed) {
return err
}

return nil
}

func printVersion() {
Expand Down
8 changes: 8 additions & 0 deletions internal/desktop/desktop.go
@@ -1,6 +1,7 @@
package desktop

import (
"fmt"
"io/ioutil"
"os"
"path"
Expand Down Expand Up @@ -29,6 +30,8 @@ type FaviconProvider interface {
// MUST be run on the main goroutine or will have no effect on macOS
func Start(shutdownHandler ShutdownHandler, faviconProvider FaviconProvider) {
if IsDesktop() {
hideConsole()

c := config.GetInstance()
if !c.GetNoBrowser() {
openURLInBrowser("")
Expand Down Expand Up @@ -60,6 +63,11 @@ func SendNotification(title string, text string) {
}

func IsDesktop() bool {
if isDoubleClickLaunched() {
fmt.Println("double click launched")
return true
}

// Check if running under root
if os.Getuid() == 0 {
return false
Expand Down
8 changes: 8 additions & 0 deletions internal/desktop/desktop_platform_darwin.go
Expand Up @@ -34,3 +34,11 @@ func sendNotification(notificationTitle string, notificationText string) {
func revealInFileManager(path string) {
exec.Command(`open`, `-R`, path)
}

func isDoubleClickLaunched() bool {
return false
}

func hideConsole() {

}
8 changes: 8 additions & 0 deletions internal/desktop/desktop_platform_nixes.go
Expand Up @@ -37,3 +37,11 @@ func sendNotification(notificationTitle string, notificationText string) {
func revealInFileManager(path string) {

}

func isDoubleClickLaunched() bool {
return false
}

func hideConsole() {

}
41 changes: 41 additions & 0 deletions internal/desktop/desktop_platform_windows.go
Expand Up @@ -5,12 +5,19 @@ package desktop

import (
"os/exec"
"syscall"
"unsafe"

"github.com/go-toast/toast"
"github.com/stashapp/stash/pkg/logger"
"golang.org/x/sys/windows/svc"
)

var (
kernel32 = syscall.NewLazyDLL("kernel32.dll")
user32 = syscall.NewLazyDLL("user32.dll")
)

func isService() bool {
result, err := svc.IsWindowsService()
if err != nil {
Expand All @@ -20,6 +27,40 @@ func isService() bool {
return result
}

// Detect if windows golang executable file is running via double click or from cmd/shell terminator
// https://stackoverflow.com/questions/8610489/distinguish-if-program-runs-by-clicking-on-the-icon-typing-its-name-in-the-cons?rq=1
// https://github.com/shirou/w32/blob/master/kernel32.go
// https://github.com/kbinani/win/blob/master/kernel32.go#L3268
// win.GetConsoleProcessList(new(uint32), win.DWORD(2))
// from https://gist.github.com/yougg/213250cc04a52e2b853590b06f49d865
func isDoubleClickLaunched() bool {
lp := kernel32.NewProc("GetConsoleProcessList")
if lp != nil {
var pids [2]uint32
var maxCount uint32 = 2
ret, _, _ := lp.Call(uintptr(unsafe.Pointer(&pids)), uintptr(maxCount))
if ret > 1 {
return false
}
}
return true
}

func hideConsole() {
const SW_HIDE = 0
h := getConsoleWindow()
lp := user32.NewProc("ShowWindow")

// don't want to check for errors and can't prevent dogsled
_, _, _ = lp.Call(h, SW_HIDE) //nolint:dogsled
}

func getConsoleWindow() uintptr {
lp := kernel32.NewProc("GetConsoleWindow")
ret, _, _ := lp.Call()
return ret
}

func isServerDockerized() bool {
return false
}
Expand Down
9 changes: 9 additions & 0 deletions internal/desktop/dialog_nonwindows.go
@@ -0,0 +1,9 @@
//go:build !windows
// +build !windows

package desktop

func FatalError(err error) int {
// nothing to do
return 0
}
33 changes: 33 additions & 0 deletions internal/desktop/dialog_windows.go
@@ -0,0 +1,33 @@
//go:build windows
// +build windows

package desktop

import (
"fmt"
"syscall"
"unsafe"
)

func FatalError(err error) int {
const (
NULL = 0
MB_OK = 0
MB_ICONERROR = 0x10
)

return messageBox(NULL, fmt.Sprintf("Error: %v", err), "Stash - Fatal Error", MB_OK|MB_ICONERROR)
}

func messageBox(hwnd uintptr, caption, title string, flags uint) int {
lpText, _ := syscall.UTF16PtrFromString(caption)
lpCaption, _ := syscall.UTF16PtrFromString(title)

ret, _, _ := syscall.NewLazyDLL("user32.dll").NewProc("MessageBoxW").Call(
uintptr(hwnd),
uintptr(unsafe.Pointer(lpText)),
uintptr(unsafe.Pointer(lpCaption)),
uintptr(flags))

return int(ret)
}