A simple command line tool for embedding usual resources in Windows executables built with Go:
- A manifest
- An application icon
- Version information (the Details tab in file properties)
- Other icons and cursors
You might want to directly use winres as a library too: github.com/tc-hib/winres
To install the go-winres command, run:
go install github.com/tc-hib/go-winres@latestPlease type go-winres help to get a list of commands and options.
Typical usage would be:
- Run
go-winres initto create awinresdirectory - Modify the contents of
winres.json - Before
go build, rungo-winres make
go-winres make creates files named rsrc_windows_*.syso that go build automatically embeds in the executable.
The suffix _windows_amd64 is very important.
Thanks to it, go build knows it should not include that object in a Linux or 386 build.
The --file-version and --product-version flags can take a special value: git-tag.
This will retrieve the current tag with git describe --tags and add it to the file properties of the executable.
You can use a //go:generate comment as well:
//go:generate go-winres make --product-version=git-tag
There are other subcommands:
go-winres simplyis a simplermakethat does not rely on a json file.go-winres extractextracts resources from anexefile or adll.go-winres patchreplaces resources directly in anexefile or adll. For example, to enhance a 7z self extracting archive, you may change its icon, and add a manifest to make it look better on high DPI screens.
The JSON file follows this hierarchy:
- Resource type (e.g.
"RT_GROUP_ICON"or"#42"or"MY_TYPE")- Resource name (e.g.
"MY_ICON"or"#1")- Language ID (e.g.
"0409"for en-US)- Actual resource: a filename or a json structure
- Language ID (e.g.
- Resource name (e.g.
Standard resource types can be found there. But
please never use RT_ICON or RT_CURSOR. Use RT_GROUP_ICON and RT_GROUP_CURSOR instead.
{
"RT_GROUP_ICON": {
"APP": {
"0000": [
"icon_64.png",
"icon_48.png",
"icon_32.png",
"icon_16.png"
]
},
"OTHER": {
"0000": "icon.png"
},
"#42": {
"0409": "icon_EN.ico",
"040C": "icon_FR.ico"
}
}
}This example contains 3 icons:
"APP""OTHER"42
Windows Explorer will display "APP" because it is the first one. Icons are sorted by name in case sensitive ascending
order, then by ID.
42 is an ID, not a name, this is why it comes last.
"APP"is made of 4 png files."OTHER"will be generated from one png file. It will be resized to 256x256, 64x64, 48x48, 32x32, and 16x16.42is a native icon, it probably already contains several images.
Finally, 42 will display a different icon for french users.
"0409"means en-US, which is the default."040C"means fr-FR.
You can find other language IDs there.
{
"RT_GROUP_CURSOR": {
"ARROW": {
"0000": [
{
"image": "arrow_32.png",
"x": 28,
"y": 4
},
{
"image": "arrow_48.png",
"x": 40,
"y": 6
}
]
},
"MOVE": {
"0409": "move_EN.cur",
"040C": "move_FR.cur"
},
"#1": {
"0000": {
"image": "cross.png",
"x": 16,
"y": 16
}
}
}
}This example contains 3 cursors:
"ARROW"contains two images (one for higher DPI). It is a json array."MOVE"uses cur files directly. It is different in French. It is a string.1contains one image. It is an object.
When a cursor is made with a png file, you have to provide the coordinates of the "hot spot", that is, the pixel that clicks.
The manifest should be defined as resource 1 with language 0409.
{
"RT_MANIFEST": {
"#1": {
"0409": {
"identity": {
"name": "",
"version": ""
},
"description": "",
"minimum-os": "win7",
"execution-level": "as invoker",
"ui-access": false,
"auto-elevate": false,
"dpi-awareness": "system",
"disable-theming": false,
"disable-window-filtering": false,
"high-resolution-scrolling-aware": false,
"ultra-high-resolution-scrolling-aware": false,
"long-path-aware": false,
"printer-driver-isolation": false,
"gdi-scaling": false,
"segment-heap": false,
"use-common-controls-v6": false
}
}
}
}All boolean values default to false.
It is recommended to omit identity if your program is a plain application, not meant to be a side-by-side
dependency.
""(default)"highest": elevates to the highest level available to the current user"administrator": require the user to be an administrator and elevate to this level
"vista""win7"(default)"win8""win8.1""win10"
"unaware""system"(default)"per monitor""per monitor v2"(recommended)
{
"RT_MANIFEST": {
"#1": {
"0409": "my_manifest.xml"
}
}
}Here is an example JSON file containing every standard info field, a French translation, and every possible flag.
"0409" and "040C" are language code identifiers (LCID) for en-US and fr-FR respectively.
{
"RT_VERSION": {
"#1": {
"0000": {
"fixed": {
"file_version": "1.2.3.4",
"product_version": "1.2.3.42",
"flags": "Debug,Prerelease,Patched,PrivateBuild,SpecialBuild",
"timestamp": "2020-12-18T23:00:00+01:00"
},
"info": {
"0409": {
"Comments": "Comments",
"CompanyName": "Company",
"FileDescription": "A description",
"FileVersion": "1.2.3.4",
"InternalName": "",
"LegalCopyright": "© You",
"LegalTrademarks": "",
"OriginalFilename": "X.EXE",
"PrivateBuild": "",
"ProductName": "Product",
"ProductVersion": "1.2.3.42 beta",
"SpecialBuild": ""
},
"040C": {
"Comments": "Commentaire",
"CompanyName": "Compagnie",
"FileDescription": "Une description",
"FileVersion": "1.2.3.4",
"InternalName": "",
"LegalCopyright": "© Vous",
"LegalTrademarks": "",
"OriginalFilename": "X.EXE",
"PrivateBuild": "",
"ProductName": "Produit",
"ProductVersion": "1.2.3.42 bêta",
"SpecialBuild": ""
}
}
}
}
}
}This project is similar to akavel/rsrc and josephspurrier/goversioninfo.
Additional features are:
- Multilingual resources
- Multilingual VersionInfo that works in Windows Explorer
- Explicitly named resources, by ID or by string (so you can use them in runtime)
- Extracting resources from
exeordllfiles - Replacing resources in
exeordllfiles - Simplified VersionInfo definition
- Simplified manifest definition
- Support for custom information in VersionInfo
- Making an icon or a cursor from a PNG file
- Embedding custom resources
It might be closer to Microsoft specifications too.
go-winres is not a real resource compiler, which means it won't help you embed these UI templates:
ACCELERATORSDIALOGEXMENUEXPOPUP
If you ever need them, you can use one of those tools instead:
rc.exeandcvtres.exefrom Visual Studiowindresfrom GNU Binary Utilitiesllvm-rcandllvm-cvtresfrom LLVM tools
See Resource Compiler for more information.
Many thanks to akavel for his help.
This project uses these very helpful libs:
- nfnt/resize - pure Go image resizing
- urfave/cli - makes building a CLI easier