From c0c140b08dc6ffc78d657188d7559bf1f0067f76 Mon Sep 17 00:00:00 2001 From: Davide Grilli Date: Thu, 15 Oct 2026 12:13:01 +0200 Subject: [PATCH] Windows: eseguibile senza console e CLI che riaggancia il terminale MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit OutputType passa a WinExe: nessuna finestra di console al doppio clic. Con argomenti Core/ConsoleHost.cs chiama AttachConsole sul terminale padre e collega stdout e stderr a CONOUT$ solo se non sono già reindirizzati; senza terminale padre non fa nulla. Su Linux il comportamento non cambia. Co-Authored-By: Claude Sonnet 5.5 --- Core/ConsoleHost.cs | 40 ++++++++++++++++++++++++++++++++++++++++ Program.cs | 1 + agent-wiki-ui.csproj | 3 ++- 3 files changed, 43 insertions(+), 1 deletion(-) create mode 100644 Core/ConsoleHost.cs diff --git a/Core/ConsoleHost.cs b/Core/ConsoleHost.cs new file mode 100644 index 0000000..a107346 --- /dev/null +++ b/Core/ConsoleHost.cs @@ -0,0 +1,40 @@ +using System.Runtime.InteropServices; + +namespace AgentWikiUi.Core; + +// Su Windows l'eseguibile è senza console (WinExe, ADR-0005). In modalità CLI si riaggancia il terminale +// da cui parte, così l'output è visibile; senza terminale padre non succede nulla. +static class ConsoleHost +{ + const int AttachParentProcess = -1; + const int StdOutput = -11, StdError = -12; + const uint GenericReadWrite = 0xC0000000, ShareReadWrite = 3, OpenExisting = 3; + static readonly nint InvalidHandle = -1; + + [DllImport("kernel32.dll", SetLastError = true)] static extern bool AttachConsole(int processId); + [DllImport("kernel32.dll", SetLastError = true)] static extern nint GetStdHandle(int stdHandle); + [DllImport("kernel32.dll", SetLastError = true)] static extern bool SetStdHandle(int stdHandle, nint handle); + [DllImport("kernel32.dll", EntryPoint = "CreateFileW", SetLastError = true, CharSet = CharSet.Unicode)] + static extern nint CreateFile(string name, uint access, uint share, nint security, uint disposition, uint flags, nint template); + + public static void AttachToParent() + { + if (!OperatingSystem.IsWindows()) return; + try + { + if (!AttachConsole(AttachParentProcess)) return; // nessun terminale padre (doppio clic, avvio da altro programma) + Connect(StdOutput); + Connect(StdError); + } + catch (Exception ex) when (ex is DllNotFoundException or EntryPointNotFoundException) { } + } + + // Collega l'handle alla console solo se non è già valido: un file o una pipe ereditati (> file, | altro) restano com'erano. + static void Connect(int std) + { + var current = GetStdHandle(std); + if (current != 0 && current != InvalidHandle) return; + var console = CreateFile("CONOUT$", GenericReadWrite, ShareReadWrite, 0, OpenExisting, 0, 0); + if (console != InvalidHandle) SetStdHandle(std, console); + } +} diff --git a/Program.cs b/Program.cs index 5d1352a..b9d599e 100644 --- a/Program.cs +++ b/Program.cs @@ -6,6 +6,7 @@ using AgentWikiUi.Gui; // il resto degli argomenti è unito in un solo prompt. Senza argomenti: GUI. if (args.Length > 0) { + ConsoleHost.AttachToParent(); // Windows: l'eseguibile non ha console, si usa quella del terminale padre var engine = Engines.Claude; var words = args; if (args[0] == "--engine") diff --git a/agent-wiki-ui.csproj b/agent-wiki-ui.csproj index 99361c7..2995468 100644 --- a/agent-wiki-ui.csproj +++ b/agent-wiki-ui.csproj @@ -1,7 +1,8 @@ - Exe + + WinExe net10.0 agent-wiki-ui