feat: 더블클릭 시 MessageBox로 프로토콜 등록 안내
- 인자 없이 실행(더블클릭) 시 install 확인 팝업 표시 - 모든 결과/에러를 Windows MessageBox로 표시 - -H windowsgui 빌드 플래그로 콘솔창 표시 제거 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
89
main.go
89
main.go
@@ -7,7 +7,9 @@ import (
|
|||||||
"os/exec"
|
"os/exec"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
|
"unsafe"
|
||||||
|
|
||||||
|
"golang.org/x/sys/windows"
|
||||||
"golang.org/x/sys/windows/registry"
|
"golang.org/x/sys/windows/registry"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -16,40 +18,76 @@ const (
|
|||||||
gameExeName = "A301.exe"
|
gameExeName = "A301.exe"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
user32 = windows.NewLazySystemDLL("user32.dll")
|
||||||
|
messageBoxW = user32.NewProc("MessageBoxW")
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
mbOK = 0x00000000
|
||||||
|
mbIconInfo = 0x00000040
|
||||||
|
mbIconError = 0x00000010
|
||||||
|
mbYesNo = 0x00000004
|
||||||
|
mbIconQuestion = 0x00000020
|
||||||
|
idYes = 6
|
||||||
|
)
|
||||||
|
|
||||||
|
func msgBox(title, text string, flags uintptr) int {
|
||||||
|
t, _ := windows.UTF16PtrFromString(title)
|
||||||
|
m, _ := windows.UTF16PtrFromString(text)
|
||||||
|
ret, _, _ := messageBoxW.Call(
|
||||||
|
0,
|
||||||
|
uintptr(unsafe.Pointer(m)),
|
||||||
|
uintptr(unsafe.Pointer(t)),
|
||||||
|
flags,
|
||||||
|
)
|
||||||
|
return int(ret)
|
||||||
|
}
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
if len(os.Args) < 2 {
|
if len(os.Args) < 2 {
|
||||||
fmt.Println("사용법:")
|
// 더블클릭 실행 시 install 안내 후 자동 설치
|
||||||
fmt.Println(" launcher.exe install 프로토콜 등록")
|
ret := msgBox(
|
||||||
fmt.Println(" launcher.exe uninstall 프로토콜 제거")
|
"A301 런처",
|
||||||
fmt.Println(" launcher.exe a301://... 게임 실행")
|
"게임 실행을 위해 프로토콜을 등록합니다.\n계속하시겠습니까?",
|
||||||
|
mbYesNo|mbIconQuestion,
|
||||||
|
)
|
||||||
|
if ret != idYes {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if err := install(); err != nil {
|
||||||
|
msgBox("A301 런처 - 오류", fmt.Sprintf("등록 실패:\n%v", err), mbOK|mbIconError)
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
|
msgBox("A301 런처", "a301:// 프로토콜이 등록되었습니다.\n이제 웹에서 게임 시작 버튼을 사용할 수 있습니다.", mbOK|mbIconInfo)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
arg := os.Args[1]
|
arg := os.Args[1]
|
||||||
|
|
||||||
switch {
|
switch {
|
||||||
case arg == "install":
|
case arg == "install":
|
||||||
if err := install(); err != nil {
|
if err := install(); err != nil {
|
||||||
fmt.Fprintf(os.Stderr, "설치 실패: %v\n", err)
|
msgBox("A301 런처 - 오류", fmt.Sprintf("등록 실패:\n%v", err), mbOK|mbIconError)
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
fmt.Println("a301:// 프로토콜이 등록되었습니다.")
|
msgBox("A301 런처", "a301:// 프로토콜이 등록되었습니다.", mbOK|mbIconInfo)
|
||||||
|
|
||||||
case arg == "uninstall":
|
case arg == "uninstall":
|
||||||
if err := uninstall(); err != nil {
|
if err := uninstall(); err != nil {
|
||||||
fmt.Fprintf(os.Stderr, "제거 실패: %v\n", err)
|
msgBox("A301 런처 - 오류", fmt.Sprintf("제거 실패:\n%v", err), mbOK|mbIconError)
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
fmt.Println("a301:// 프로토콜이 제거되었습니다.")
|
msgBox("A301 런처", "a301:// 프로토콜이 제거되었습니다.", mbOK|mbIconInfo)
|
||||||
|
|
||||||
case strings.HasPrefix(arg, protocolName+"://"):
|
case strings.HasPrefix(arg, protocolName+"://"):
|
||||||
if err := handleURI(arg); err != nil {
|
if err := handleURI(arg); err != nil {
|
||||||
fmt.Fprintf(os.Stderr, "실행 실패: %v\n", err)
|
msgBox("A301 런처 - 오류", fmt.Sprintf("실행 실패:\n%v", err), mbOK|mbIconError)
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
fmt.Fprintf(os.Stderr, "알 수 없는 명령: %s\n", arg)
|
msgBox("A301 런처 - 오류", fmt.Sprintf("알 수 없는 명령: %s", arg), mbOK|mbIconError)
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -68,7 +106,6 @@ func install() error {
|
|||||||
return fmt.Errorf("실행 파일 경로를 찾을 수 없습니다: %w", err)
|
return fmt.Errorf("실행 파일 경로를 찾을 수 없습니다: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// HKCU\Software\Classes\a301
|
|
||||||
key, _, err := registry.CreateKey(
|
key, _, err := registry.CreateKey(
|
||||||
registry.CURRENT_USER,
|
registry.CURRENT_USER,
|
||||||
`Software\Classes\`+protocolName,
|
`Software\Classes\`+protocolName,
|
||||||
@@ -86,7 +123,6 @@ func install() error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// shell\open\command
|
|
||||||
cmdKey, _, err := registry.CreateKey(
|
cmdKey, _, err := registry.CreateKey(
|
||||||
registry.CURRENT_USER,
|
registry.CURRENT_USER,
|
||||||
`Software\Classes\`+protocolName+`\shell\open\command`,
|
`Software\Classes\`+protocolName+`\shell\open\command`,
|
||||||
@@ -98,29 +134,21 @@ func install() error {
|
|||||||
defer cmdKey.Close()
|
defer cmdKey.Close()
|
||||||
|
|
||||||
cmdValue := fmt.Sprintf(`"%s" "%%1"`, exePath)
|
cmdValue := fmt.Sprintf(`"%s" "%%1"`, exePath)
|
||||||
if err := cmdKey.SetStringValue("", cmdValue); err != nil {
|
return cmdKey.SetStringValue("", cmdValue)
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func uninstall() error {
|
func uninstall() error {
|
||||||
err := registry.DeleteKey(registry.CURRENT_USER, `Software\Classes\`+protocolName+`\shell\open\command`)
|
paths := []string{
|
||||||
|
`Software\Classes\` + protocolName + `\shell\open\command`,
|
||||||
|
`Software\Classes\` + protocolName + `\shell\open`,
|
||||||
|
`Software\Classes\` + protocolName + `\shell`,
|
||||||
|
`Software\Classes\` + protocolName,
|
||||||
|
}
|
||||||
|
for _, p := range paths {
|
||||||
|
err := registry.DeleteKey(registry.CURRENT_USER, p)
|
||||||
if err != nil && err != registry.ErrNotExist {
|
if err != nil && err != registry.ErrNotExist {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
err = registry.DeleteKey(registry.CURRENT_USER, `Software\Classes\`+protocolName+`\shell\open`)
|
|
||||||
if err != nil && err != registry.ErrNotExist {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
err = registry.DeleteKey(registry.CURRENT_USER, `Software\Classes\`+protocolName+`\shell`)
|
|
||||||
if err != nil && err != registry.ErrNotExist {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
err = registry.DeleteKey(registry.CURRENT_USER, `Software\Classes\`+protocolName)
|
|
||||||
if err != nil && err != registry.ErrNotExist {
|
|
||||||
return err
|
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@@ -144,7 +172,7 @@ func handleURI(rawURI string) error {
|
|||||||
gamePath := filepath.Join(gameDir, gameExeName)
|
gamePath := filepath.Join(gameDir, gameExeName)
|
||||||
|
|
||||||
if _, err := os.Stat(gamePath); os.IsNotExist(err) {
|
if _, err := os.Stat(gamePath); os.IsNotExist(err) {
|
||||||
return fmt.Errorf("게임 파일을 찾을 수 없습니다: %s", gamePath)
|
return fmt.Errorf("게임 파일을 찾을 수 없습니다:\n%s", gamePath)
|
||||||
}
|
}
|
||||||
|
|
||||||
cmd := exec.Command(gamePath, "-token", token)
|
cmd := exec.Command(gamePath, "-token", token)
|
||||||
@@ -153,6 +181,5 @@ func handleURI(rawURI string) error {
|
|||||||
return fmt.Errorf("게임 실행 실패: %w", err)
|
return fmt.Errorf("게임 실행 실패: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt.Printf("게임이 실행되었습니다 (PID: %d)\n", cmd.Process.Pid)
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user