package main import ( "fmt" "net/url" "os" "os/exec" "path/filepath" "strings" "golang.org/x/sys/windows/registry" ) const ( protocolName = "a301" gameExeName = "A301.exe" ) func main() { if len(os.Args) < 2 { fmt.Println("사용법:") fmt.Println(" launcher.exe install 프로토콜 등록") fmt.Println(" launcher.exe uninstall 프로토콜 제거") fmt.Println(" launcher.exe a301://... 게임 실행") os.Exit(1) } arg := os.Args[1] switch { case arg == "install": if err := install(); err != nil { fmt.Fprintf(os.Stderr, "설치 실패: %v\n", err) os.Exit(1) } fmt.Println("a301:// 프로토콜이 등록되었습니다.") case arg == "uninstall": if err := uninstall(); err != nil { fmt.Fprintf(os.Stderr, "제거 실패: %v\n", err) os.Exit(1) } fmt.Println("a301:// 프로토콜이 제거되었습니다.") case strings.HasPrefix(arg, protocolName+"://"): if err := handleURI(arg); err != nil { fmt.Fprintf(os.Stderr, "실행 실패: %v\n", err) os.Exit(1) } default: fmt.Fprintf(os.Stderr, "알 수 없는 명령: %s\n", arg) os.Exit(1) } } func launcherPath() (string, error) { exe, err := os.Executable() if err != nil { return "", err } return filepath.Abs(exe) } func install() error { exePath, err := launcherPath() if err != nil { return fmt.Errorf("실행 파일 경로를 찾을 수 없습니다: %w", err) } // HKCU\Software\Classes\a301 key, _, err := registry.CreateKey( registry.CURRENT_USER, `Software\Classes\`+protocolName, registry.SET_VALUE, ) if err != nil { return fmt.Errorf("레지스트리 키 생성 실패: %w", err) } defer key.Close() if err := key.SetStringValue("", "URL:A301 Protocol"); err != nil { return err } if err := key.SetStringValue("URL Protocol", ""); err != nil { return err } // shell\open\command cmdKey, _, err := registry.CreateKey( registry.CURRENT_USER, `Software\Classes\`+protocolName+`\shell\open\command`, registry.SET_VALUE, ) if err != nil { return fmt.Errorf("command 키 생성 실패: %w", err) } defer cmdKey.Close() cmdValue := fmt.Sprintf(`"%s" "%%1"`, exePath) if err := cmdKey.SetStringValue("", cmdValue); err != nil { return err } return nil } func uninstall() error { err := registry.DeleteKey(registry.CURRENT_USER, `Software\Classes\`+protocolName+`\shell\open\command`) if err != nil && err != registry.ErrNotExist { 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 } func handleURI(rawURI string) error { parsed, err := url.Parse(rawURI) if err != nil { return fmt.Errorf("URI 파싱 실패: %w", err) } token := parsed.Query().Get("token") if token == "" { return fmt.Errorf("토큰이 없습니다") } exePath, err := launcherPath() if err != nil { return err } gameDir := filepath.Dir(exePath) gamePath := filepath.Join(gameDir, gameExeName) if _, err := os.Stat(gamePath); os.IsNotExist(err) { return fmt.Errorf("게임 파일을 찾을 수 없습니다: %s", gamePath) } cmd := exec.Command(gamePath, "-token", token) cmd.Dir = gameDir if err := cmd.Start(); err != nil { return fmt.Errorf("게임 실행 실패: %w", err) } fmt.Printf("게임이 실행되었습니다 (PID: %d)\n", cmd.Process.Pid) return nil }