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); } }