How do you set the application icon in golang?

huangapple go评论68阅读模式
英文:

How do you set the application icon in golang?

问题

你好!以下是你要翻译的内容:

我刚在Windows上创建了我的第一个Go应用程序。

我该如何为它添加一个图标?

似乎没有任何构建标志可以做到这一点,而且我知道Go语言不支持资源。

英文:

I've just created my first go application on Windows.

How do I give it an icon?

There doesn't seem to be any build flags to do this, and I know golang doesn't support resources.

答案1

得分: 41

你可以使用类似akavel/rsrc的工具来生成一个包含指定资源的.syso文件,这些资源被嵌入到.rsrc部分中,用于在构建Win32可执行文件时由Go链接器使用。

lxn/walk应用程序为例,它在可执行文件中嵌入了其他元数据。

rsrc [-manifest FILE.exe.manifest] [-ico FILE.ico[,FILE2.ico...]] -o FILE.syso

-ico="":要嵌入的.ico文件的逗号分隔路径列表

这与将二进制数据嵌入到Go程序中不同。
对于这个,可以使用jteeuwen/go-bindata

> 要访问资源数据,我们使用生成的输出中包含的Asset(string) []byte函数。

data := Asset("pub/style/foo.css")
if len(data) == 0 {
    // 未找到资源。
}

// 使用资源数据

更新于2021年:如John N答案中所述,你还可以使用:

github.com/tc-hib/go-winres

> 一个简单的命令行工具,用于在使用Go构建的Windows可执行文件中嵌入常规资源:
>
> - 一个清单
> - 一个应用程序图标
> - 版本信息(文件属性中的详细信息选项卡)
> - 其他图标和光标

它也可以作为库使用。

英文:

You can use a tool like akavel/rsrc in order to generate a .syso file with specified resources embedded in .rsrc section, aimed for consumption by Go linker when building Win32 excecutables.

See as an example the lxn/walk application, which embeds other metadata in its executable.

rsrc [-manifest FILE.exe.manifest] [-ico FILE.ico[,FILE2.ico...]] -o FILE.syso

-ico="": comma-separated list of paths to .ico files to embed


This differs from embedding binary data into a go program.
For that, use jteeuwen/go-bindata.

> To access asset data, we use the Asset(string) []byte function which is included in the generated output.

data := Asset("pub/style/foo.css")
if len(data) == 0 {
    // Asset was not found.
}

// use asset data

Update 2021: as noted in John N's answer, you can also use:

github.com/tc-hib/go-winres

> 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

It can be used as a library too.

答案2

得分: 10

主题是长时间,实际上mingw只是一个要求,我们不需要第三方依赖。此外,资源文件*.rc对于Win32可执行应用程序是必需的。最后,你可以在rc-demo中找到演示。

1)使用Chocolatey安装mingw:choco install mingw

2)创建main.exe.manifest文件

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<assemblyIdentity
    version="1.0.0.0"
    processorArchitecture="x86"
    name="controls"
    type="win32"
/>
<dependency>
    <dependentAssembly>
        <assemblyIdentity
            type="win32"
            name="Microsoft.Windows.Common-Controls"
            version="6.0.0.0"
            processorArchitecture="*"
            publicKeyToken="6595b64144ccf1df"
            language="*"
        />
    </dependentAssembly>
</dependency>
</assembly>

3)创建main.rc文件

100 ICON    "main.ico"
100 24      "main.exe.manifest"
101 RCDATA  "content.zip"

4)构建

在git-bash窗口执行以下命令:
windres -o main-res.syso main.rc && go build -i

英文:

The topic is long time, in fact mingw is only requirement, we don't need 3rd party dependency. In addition, resource file *.rc is mandatory for win32 executable application. At last, you can find the demo in rc-demo

  1. Install mingw using Chocolatey: choco install mingw

  2. Create main.exe.manifest file

    <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
    <assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
    <assemblyIdentity
    version="1.0.0.0"
    processorArchitecture="x86"
    name="controls"
    type="win32"
    />
    <dependency>
    <dependentAssembly>
    <assemblyIdentity
    type="win32"
    name="Microsoft.Windows.Common-Controls"
    version="6.0.0.0"
    processorArchitecture=""
    publicKeyToken="6595b64144ccf1df"
    language="
    "
    />
    </dependentAssembly>
    </dependency>
    </assembly>

  3. Create main.rc file

    100 ICON "main.ico"
    100 24 "main.exe.manifest"
    101 RCDATA "content.zip"

  4. Build

In git-bash windows perform the following command:
windres -o main-res.syso main.rc &amp;&amp; go build -i

1: https://gitlab.com/gozoo/rc-demo "demo"

答案3

得分: 5

以上的答案都对我没用。我唯一能够将ico嵌入到GO exe中的方法是使用Resource Hacker。

  1. 安装并打开Resource Hacker。
  2. 在Resource Hacker中打开编译后的exe文件。
  3. 选择操作 > 添加图像或其他二进制资源。
  4. 选择ICO文件 > 添加资源。
  5. 保存并关闭。

如果需要将其添加到构建脚本中,你也可以直接从命令行运行。

ResourceHacker -open main.exe -save output.exe -action addskip -res main.ico -mask ICONGROUP,MAIN,
英文:

None of the above answers worked for me. The only way I could get an ico embedded into a GO exe was with Resource Hacker.

http://www.angusj.com/resourcehacker/

  1. Install and open Resource Hacker
  2. Open compiled exe in Resource Hacker
  3. Action > Add an image or other binary resource
  4. Select ICO > Add Resource
  5. Save and Close

You can also run it directly from the command line if you need to add it to your build scripts.

ResourceHacker -open main.exe -save output.exe -action addskip -res main.ico -mask ICONGROUP,MAIN,

答案4

得分: 3

有一个由Joseph Spurrier创建的GitHub包GoVersionInfo

> 用于Go语言的Microsoft Windows文件属性/版本信息和图标资源生成器
>
> 该包创建一个包含Microsoft Windows版本信息和可选图标的syso文件。当你运行"go build"时,Go语言将在可执行文件中嵌入版本信息、可选图标和可选清单。如果syso文件与main()函数在同一个目录中,Go语言将自动使用该syso文件。

英文:

There is a github package GoVersionInfo by Joseph Spurrier:

> Microsoft Windows File Properties/Version Info and Icon Resource Generator for the Go Language
>
> Package creates a syso file which contains Microsoft Windows Version Information and an optional icon. When you run "go build", Go will embed the version information and an optional icon and an optional manifest in the executable. Go will automatically use the syso file if it's in the same directory as the main() function.

答案5

得分: 2

这对我来说很有效。

去获取 github.com/akavel/rsrc
rsrc -ico YOUR_ICON_FILE_NAME.ico
go build
英文:

This worked out for me

go get github.com/akavel/rsrc
rsrc -ico YOUR_ICON_FILE_NAME.ico
go build

答案6

得分: 2

这个很好用:

go install github.com/tc-hib/go-winres@latest
go-winres simply --icon youricon.png
go build

如果你的应用有图形界面:
go-winres simply --icon icon.png --manifest gui

英文:

This works well:

go install github.com/tc-hib/go-winres@latest
go-winres simply --icon youricon.png
go build

If your app has a GUI:
go-winres simply --icon icon.png --manifest gui

答案7

得分: 1

我为了满足我的需求深入研究了这个问题,但是John NCoconut提到的简单方法并没有按预期工作。

经过更深入的研究,我找出了问题所在,并分享出来,希望对其他人有用。

  • syso文件需要是应用程序使用的一个包的一部分。
  • 当存在用于构建的cmd/main.go文件时,syso文件不能放在项目的根目录中。
  • 当构建cmd/main.go文件时,syso文件不能放在应用程序的主包中(即将syso放在cmd下面不会起作用)。

以下是对我有效的几个示例:

扁平项目结构

...\test1
│   go.mod
│   main.go
│   rsrc.syso

其中go.mod文件内容为:

module test1

go 1.19

main.go文件内容为:

package main

import (
        "fmt"
)

func main() {
        fmt.Println("test1")
}

然后运行go build命令,会按预期创建test1.exe


空包

将syso文件放在一个新的包文件夹中,并创建一个空文件与包名相同,使用_强制导入该包。

...\test2
│   go.mod
│
├───cmd
│       main.go
│
└───rsrc
        rsrc.go
        rsrc.syso

其中go.mod文件内容为:

module test2

go 1.19

rsrc.go文件内容为:

package rsrc

main.go文件内容为:

package main

import (
        "fmt"
        _ "test2/rsrc"
)

func main() {
        fmt.Println("test2")
}

然后运行go build -o test2.exe cmd\main.go命令,会按预期创建test2.exe


借用现有包

将syso文件放在项目应用程序已经使用的一个包文件夹中(注意:不同的应用程序如果使用了该包,将会有相同的syso文件)。

...\test3
│   go.mod
│
├───cmd
│       main.go
│
└───other
        other.go
        rsrc.syso

其中go.mod文件内容为:

module test3

go 1.19

other.go文件内容为:

package other

func Foo() string {
        return "bar"
}

main.go文件内容为:

package main

import (
        "fmt"
        "test3/other"
)

func main() {
        fmt.Println("test3")
        fmt.Println(other.Foo())
}

然后运行go build -o test3.exe cmd\main.go命令,会按预期创建test3.exe


使用Docker构建流程

基于借用现有包的Docker化构建

因为,嘿,其他人可能也需要这个...<br>
使用arch参数将其设置为适当的ARCH,如果你有多平台/架构的构建流程。

...
ARG TARGETARCH
ARG TARGETOS
RUN go install github.com/tc-hib/go-winres@latest
RUN go-winres simply --icon images/icon.png --out other/rsrc --arch ${TARGETARCH}
...
GOOS=${TARGETOS} GOARCH=${TARGETARCH} go build -o test3.exe cmd/main.go 
...

希望这对那些遇到困难的人有所帮助。


英文:

I delved into this issue for my requirements and the simple methods mentioned by John N and Coconut did not work as expected.

After more delving i figure out what was the problem and I share it so it might be useful for others.

  • the syso file need to be part of a package used by the application.
  • the syso file cant be placed in the root of the project when there is a cmd/main.go file used for the build.
  • the syso file cant be placed in the main package of your application (i.e. placing the syso under cmd when building cmd/main.go file wont make it).

couple examples that worked for me:

flat project structure

...\test1
│   go.mod
│   main.go
│   rsrc.syso

where go.mod

module test1

go 1.19

and main.go

package main

import (
        &quot;fmt&quot;
)

func main() {
        fmt.Println(&quot;test1&quot;)
}

then go build created test1.exe as expected


empty package

put syso file in a new folder package and create empty file with the package name, force import this package using _

...\test2
│   go.mod
│
├───cmd
│       main.go
│
└───rsrc
        rsrc.go
        rsrc.syso

where go.mod

module test2

go 1.19

rsrc.go

package rsrc

and main.go

package main

import (
        &quot;fmt&quot;
        _ &quot;test2/rsrc&quot;
)

func main() {
        fmt.Println(&quot;test2&quot;)
}

then go build -o test2.exe cmd\main.go created test2.exe as expected


piggyback on existing package

place the syso file in a folder package that already used by the project app (Note: that different apps would have the same syso in case they use that package)

...\test3
│   go.mod
│
├───cmd
│       main.go
│
└───other
        other.go
        rsrc.syso

where go.mod

module test3

go 1.19

other.go

package other

func Foo() string {
        return &quot;bar&quot;
}

and main.go

package main

import (
        &quot;fmt&quot;
        &quot;test3/other&quot;
)

func main() {
        fmt.Println(&quot;test3&quot;)
        fmt.Println(other.Foo())
}

then go build -o test3.exe cmd\main.go created test3.exe as expected


using docker build flow

Dockerized build based on piggybacking on existing package

because, hey someone else probably needs this as well....<br>
use the arch to set it to the proper ARCH if you have multi platform/architecture build flow

...
ARG TARGETARCH
ARG TARGETOS
RUN go install github.com/tc-hib/go-winres@latest
RUN go-winres simply --icon images/icon.png --out other/rsrc --arch ${TARGETARCH}
...
GOOS=${TARGETOS} GOARCH=${TARGETARCH} go build -o test3.exe cmd/main.go 
...

hope this helps anyone who got stuck


答案8

得分: 0

你可以首先了解setIcon()方法,它只允许使用byte[]格式。所以你需要先创建图像,然后将其转换为byte[]格式。按照以下步骤进行操作:

// 使用os.Open()定义图标路径
iconFile, err := os.Open("/home/user/image/icon.png")
if err != nil {
    log.Fatal(err)
}
defer iconFile.Close()

// 使用png.Decode()将图像路径转换为图像
img, err := png.Decode(iconFile)
if err != nil {
    log.Fatal(err)
}

// 然后使用bytes.Buffer将图像转换为byte[]格式
buf := new(bytes.Buffer)
err1 := jpeg.Encode(buf, img, nil)
_ = err1

// 将转换后的byte[]保存到变量中
img_buf := buf.Bytes()

// 使用systray.SetTemplateIcon()方法设置转换后的byte[]图标
systray.SetTemplateIcon(img_buf, img_buf)

谢谢!

英文:

you ant change a icon first think you know setIcon() method it only alow byte[] format so you first create image and convert into byte[]. so do following procedure.

// define icon path using os.Open()
iconFile, err := os.Open(&quot;/home/user/image/icon.png&quot;)
if err != nil {
	log.Fatal(err)
}
defer iconFile.Close()

// png.Decode() to convert image path to image
img, err := png.Decode(iconFile)
if err != nil {
	log.Fatal(err)
}

// Then convert the image to byte[] format using bytes.Buffer
buf := new(bytes.Buffer)
err1 := jpeg.Encode(buf, img, nil)
_ = err1

// save the converted byte[] to variable
img_buf := buf.Bytes()

// set the coverted byte[] icon using systray.SetTemplateIcon() method
systray.SetTemplateIcon(img_buf, img_buf)

Thank you!!!

huangapple
  • 本文由 发表于 2014年9月1日 17:20:30
  • 转载请务必保留本文链接:https://go.coder-hub.com/25602600.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定