fix: on Windows don't allocate console if not opened inside one (#10726)

This change allows Syncthing to be launched from Explorer without
showing a console window, while preserving the existing command-line
behavior.
Previously, launching syncthing.exe from Explorer would always allocate
a console window, which could only be hidden later by using
`--no-console`. It was not possible to avoid console allocation entirely
without introducing other issues.

On Windows 24H2 and later a new application manifest allows us to
achieve it. See [console allocation
policy](https://learn.microsoft.com/en-us/windows/console/console-allocation-policy)
This manifest is built into a syso-file by `goversioninfo`, which is
already used to generate Windows resource files consumed by the Go
compiler.

**Note1:** On Windows 24H2 and later, no console is allocated when
Syncthing is launched from Explorer, even if `--no-console` is set to
`False`. It can still be used as a CLI tool as usual if you call it from
console.

**Note2:** The content of the manifest file may not be formatted. Even a
`newline` would break it.

### Testing

Tested on Windows 11 25H2: No console visible from explorer. CLI works
as usual.

Ref #8046, ref #10633, ref #10481, ref #10600

Signed-off-by: Elias <1elias.bauer@gmail.com>
Co-authored-by: Elias <1elias.bauer@gmail.com>
This commit is contained in:
Shablone
2026-06-02 14:00:38 +02:00
committed by GitHub
co-authored by Elias
parent 8961f642c6
commit 9bb5f9b4dd
3 changed files with 21 additions and 4 deletions
+8
View File
@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<application>
<windowsSettings>
<consoleAllocationPolicy xmlns="http://schemas.microsoft.com/SMI/2024/WindowsSettings">detached</consoleAllocationPolicy>
</windowsSettings>
</application>
</assembly>
+12 -3
View File
@@ -732,9 +732,18 @@ func shouldBuildSyso(dir string) (string, error) {
sysoPath := filepath.Join(dir, "cmd", "syncthing", "resource.syso")
// See https://github.com/josephspurrier/goversioninfo#command-line-flags
arm := strings.HasPrefix(goarch, "arm")
a64 := strings.Contains(goarch, "64")
if _, err := runError("goversioninfo", "-o", sysoPath, fmt.Sprintf("-arm=%v", arm), fmt.Sprintf("-64=%v", a64)); err != nil {
// For manifest see https://learn.microsoft.com/en-us/windows/console/console-allocation-policy
isARM := strings.HasPrefix(goarch, "arm")
is64Bit := strings.Contains(goarch, "64")
args := []string{
"-manifest=assets/windows/syncthing.exe.manifest", // console-allocation-policy
"-o", sysoPath, // output path
fmt.Sprintf("-arm=%v", isARM),
fmt.Sprintf("-64=%v", is64Bit),
}
if _, err := runError("goversioninfo", args...); err != nil {
return "", errors.New("failed to create " + sysoPath + ": " + err.Error())
}
+1 -1
View File
@@ -7,5 +7,5 @@
package main
type buildSpecificOptions struct {
HideConsole bool `name:"no-console" help:"Hide console window" env:"STHIDECONSOLE"`
HideConsole bool `name:"no-console" help:"Hide console window (Always enabled on Windows 11 24H2 and later)" env:"STHIDECONSOLE"`
}