lua: stop dt.control.execute from flashing a console window on Windows - #22013
lua: stop dt.control.execute from flashing a console window on Windows#22013radialmonster wants to merge 2 commits into
Conversation
dt.control.execute() routes through system(), which spawns cmd.exe with a visible console window. darktable.exe is a console-subsystem binary that frees its console on startup, so on Windows every call pops a console window (issue darktable-org#17193). Add dt_exec_command_sync(): on Windows it runs the command through "cmd.exe /d /s /c <cmd>" via CreateProcessW with CREATE_NO_WINDOW, keeping system()'s shell semantics (cmd builtins, batch files, redirection) while hiding the console; on other platforms it wraps system(). execute_cb() now uses it instead of system(), preserving the integer exit-code return. Add a CMocka test for dt_exec_command_sync() covering success, a cmd builtin, a non-zero exit code and a NULL command.
|
If the whole point is to stop windows popping up, then changing the windows installer to start darktable using the work around #17193 makes the most sense in terms of the amount of code change required and the amount of code to be maintained. If we are looking for more functionality, because the current tools don't provide something we need, then that's a different story. But, since all the titles involve "popping windows" I don't think that's the case. If I take @gerritsangel's PR and this one together we're looking 1200+ lines of code to solve what can be solved with a 1 line shortcut entry. I'll look at this, but it may take awhile since the gtk4 transition is taking up a lot of my time. |
So is there a way to build darktable on windows so it doesn't call FreeConsole()? EDIT: How to Build Without FreeConsole() |
|
We tested this directly rather than reasoning about it (fresh clone, real builds). Quick answer to the compiler-flag question first: darktable already links with That leaves four real approaches, as far as we can tell: 1. This PR's approach (
2. Remove the
3. Same, plus
4. Installer/shortcut-level hidden launcher + output redirect (the
Happy to help pursue whichever direction you'd prefer, or do more testing/validation on any of these — whatever's most useful. Edit - fyi Moved to draft, still working on optimizing this. |
Resolve COMSPEC to an explicit full path before CreateProcessW. This prevents the application or current directory from supplying an unintended cmd.exe while preserving configured interpreter behavior. Fall back to the system-directory cmd.exe when COMSPEC is unavailable, and add regression coverage for a current-directory decoy and COMSPEC selection. Related: darktable-org#17193
Summary
dt.control.execute()usessystem(). On Windows, that launches a consolesubprocess from darktable's console-less GUI process and causes a visible
console-window flash.
This PR adds
dt_exec_command_sync()and routesdt.control.execute()throughit. On Windows, the helper invokes the configured
COMSPECinterpreter withCREATE_NO_WINDOW; ifCOMSPECis unavailable, it uses thecmd.exein theWindows system directory. Other platforms continue to use
system().The Windows helper resolves the interpreter to an explicit full path and passes
it as
CreateProcessW's application name. This avoids the application-directoryand current-directory executable search that occurs when the application name
is
NULL, while preserving shell builtins, batch files, redirection, chaining,Unicode commands, and configured
COMSPECbehavior.Validation
lib_darktableandtest_process.test_process: 6/6 passing, covering success, shell builtins, nonzero status,NULL, a controlled current-directorycmd.exedecoy, andCOMSPECselection.
where the decoy is launched, and passes with the explicit interpreter path.
darktable.exeshowed the same exitstatus with the flash removed for a persistent
dt.control.execute()child.Scope
This addresses only
dt.control.execute(). Lua'sos.execute()andio.popen()use separate implementations and remain follow-up work, so issue#17193 should remain open after this PR.
AI disclosure
OpenAI Codex assisted with implementation, adversarial review, and test
development. The changes were rebuilt and exercised locally as described above.
Related: #17193