From 9b05914fc341f6d49cf0fa0c914e2797958f1969 Mon Sep 17 00:00:00 2001 From: partisan Date: Tue, 18 Feb 2025 13:48:49 +0000 Subject: [PATCH] Added windows manifest generator This file is used to apply icons and versions to files correctly. --- win_manifest_gen.go | 144 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 144 insertions(+) create mode 100644 win_manifest_gen.go diff --git a/win_manifest_gen.go b/win_manifest_gen.go new file mode 100644 index 0000000..427db4a --- /dev/null +++ b/win_manifest_gen.go @@ -0,0 +1,144 @@ +package main + +import ( + "flag" + "fmt" + "os" + "strings" + "time" +) + +func main() { + // Define flags for all configurable parameters. + name := flag.String("name", "", "Application name (e.g. 'Spitfire Installer')") + version := flag.String("version", "", "Application version (e.g. '2025.02.11.0'). If empty, current date will be used") + company := flag.String("company", "", "Company name") + description := flag.String("description", "", "File description") + internalName := flag.String("internalName", "", "Internal name for the application (default: same as name)") + officialURL := flag.String("official", "", "Official website URL") + devURL := flag.String("dev", "", "Source/Development website URL") + requireAdmin := flag.Bool("requireAdmin", false, "Set to true if the application requires administrator privileges") + + flag.Parse() + + // Validate required parameters. + if *name == "" || *company == "" || *description == "" || *officialURL == "" || *devURL == "" { + fmt.Println("Error: --name, --company, --description, --official, and --dev are required") + flag.Usage() + os.Exit(1) + } + + // Use name as default for internalName if not provided. + if *internalName == "" { + *internalName = *name + } + + // Use current date as version if not provided. + if *version == "" { + now := time.Now().Format("2006.01.02") + *version = now + ".0" + } + + // Choose the requested execution level based on the requireAdmin flag. + executionLevel := "asInvoker" + if *requireAdmin { + executionLevel = "requireAdministrator" + } + + // --- Generate app.manifest --- + manifestContent := fmt.Sprintf(` + + + + + + + + + + + + true/PM + + + +`, *name, *version, executionLevel) + + if err := os.WriteFile("app.manifest", []byte(manifestContent), 0644); err != nil { + fmt.Println("Error writing app.manifest:", err) + os.Exit(1) + } + + // --- Generate app.rc (Resource Script) --- + // Convert version string "YYYY.MM.DD.0" into numeric version parts. + parts := strings.Split(*version, ".") + if len(parts) < 4 { + fmt.Println("Version must have at least 4 parts separated by '.'") + os.Exit(1) + } + // Remove leading zeros. + v1 := strings.TrimLeft(parts[0], "0") + if v1 == "" { + v1 = "0" + } + v2 := strings.TrimLeft(parts[1], "0") + if v2 == "" { + v2 = "0" + } + v3 := strings.TrimLeft(parts[2], "0") + if v3 == "" { + v3 = "0" + } + v4 := strings.TrimLeft(parts[3], "0") + if v4 == "" { + v4 = "0" + } + fileVersion := fmt.Sprintf("%s,%s,%s,%s", v1, v2, v3, v4) + + rcContent := fmt.Sprintf(`1 RT_MANIFEST "app.manifest" + +1 VERSIONINFO +FILEVERSION %s +PRODUCTVERSION %s +FILEFLAGSMASK 0x3fL +#ifdef _DEBUG +FILEFLAGS 0x1L +#else +FILEFLAGS 0x0L +#endif +FILEOS 0x40004L +FILETYPE 0x1L +FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904E4" + BEGIN + VALUE "CompanyName", "%s\0" + VALUE "FileDescription", "%s\0" + VALUE "FileVersion", "%s\0" + VALUE "InternalName", "%s\0" + VALUE "OriginalFilename", "%s.exe\0" + VALUE "ProductName", "%s\0" + VALUE "ProductVersion", "%s\0" + VALUE "Comments", "Official website: %s; Source/Dev website: %s\0" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x0409, 1252 + END +END +`, fileVersion, fileVersion, *company, *description, *version, *internalName, *internalName, *name, *version, *officialURL, *devURL) + + if err := os.WriteFile("app.rc", []byte(rcContent), 0644); err != nil { + fmt.Println("Error writing app.rc:", err) + os.Exit(1) + } + + fmt.Printf("Generated app.manifest and app.rc with version: %s\n", *version) +}