|
2026-10-25
| ||
| 08:54 | • Ticket [6dacb3b6f0] exec and open | fail for .bat files if 8dot3name is disabled... artifact: ba95bbdfe8 user: serhiy.storchaka | |
| 08:54 | • Ticket [f91ab723f3] exec+wish fails to handle windows batch file with arguments ... artifact: b40598dafc user: serhiy.storchaka | |
| 08:53 | Rebase of bug-f91ab723f3-quoting to main. Fix [6dacb3b6f0] and [f91ab723f3]: put the command after "... leaf check-in: e8d1e56815 user: serhiy.storchaka tags: bug-f91ab723f3-quoting-main | |
|
2026-10-14
| ||
| 15:33 | • Ticket [6dacb3b6f0] exec and open | fail for .bat files if 8dot3name is disabled... artifact: 6baeb86727 user: serhiy.storchaka | |
| 14:58 | • Ticket [f91ab723f3] exec+wish fails to handle windows batch file with arguments ... artifact: d9c873ecad user: serhiy.storchaka | |
| 14:55 | Fix [6dacb3b6f0] and [f91ab723f3]: append the closing quote for "cmd.exe /c" in BuildCommandLine(), ... leaf check-in: 30bc26a91e user: serhiy.storchaka tags: bug-f91ab723f3-quoting | |
| 14:31 | • Ticket [f91ab723f3] exec+wish fails to handle windows batch file with arguments ... artifact: 7178483f01 user: serhiy.storchaka | |
|
2024-08-25
| ||
| 13:15 | Merge [d7e7498d41d8fbe6]: Fix [f91ab723f3]: remove Windows 16 bit dead code. check-in: 8b549b5ebb user: pooryorick tags: unchained, INCOMPATIBLE_LICENSE | |
|
2024-02-28
| ||
| 08:01 | • Ticket [f91ab723f3] exec+wish fails to handle windows batch file with arguments ... artifact: 5b793fcc9a user: oehhar | |
| 00:41 | • Ticket [f91ab723f3]: 3 changes artifact: 787360d42f user: anonymous | |
|
2024-02-27
| ||
| 20:23 | Bug [f91ab723f3] : remove Windows 16 bit dead code check-in: ce2bd7a315 user: oehhar tags: core-8-6-branch | |
|
2024-02-26
| ||
| 14:09 | • Ticket [f91ab723f3] exec+wish fails to handle windows batch file with arguments ... artifact: 7b8a65fc15 user: oehhar | |
| 13:56 | Bug [f91ab723]: MS-WIN: remove dead code as TclWinGetPlatformId() constantly returns "VER_PLATFORM_W... closed check-in: 69a34921d1 user: oehhar tags: bug-f91ab723-dead-code-removal | |
| 13:34 | bug [f91ab723f3]: possible solution to remove cmd.exe handling. leaf check-in: bdca8a3971 user: oehhar tags: bug-f91ab723f3-no-cmd | |
| 13:29 | Bug: [f91ab723f3]: possible solution to add quoting "" for cmd.exe /c argument check-in: 0530fbcf2d user: oehhar tags: bug-f91ab723f3-quoting | |
| 11:53 | • Ticket [f91ab723f3] exec+wish fails to handle windows batch file with arguments ... artifact: 80835f0825 user: ralfixx | |
|
2024-02-23
| ||
| 10:01 | • Ticket [f91ab723f3]: 4 changes artifact: c025afff3d user: oehhar | |
| 09:57 | • Ticket [f91ab723f3]: 4 changes artifact: 18b701e85d user: oehhar | |
| 07:34 | • Ticket [f91ab723f3]: 3 changes artifact: 0b3d335c7f user: anonymous | |
|
2024-02-22
| ||
| 21:36 | • New ticket [f91ab723f3]. artifact: 59bc7fa31a user: anonymous | |
| Ticket UUID: | f91ab723f3dfbc0d2b720a70a1fa09eebfa1cde5 | ||
| Title: | exec+wish fails to handle windows batch file with arguments and spaces | ||
| Type: | Bug | Created on: | 2024-02-22 21:36:06 |
| Submitter: | anonymous | Assigned to: | nobody |
| Subsystem: | 16. Commands A-H | Severity: | Minor |
| Priority: | 5 Medium | Last modified: | 2026-10-25 08:54:48 |
| Status: | Open | Closed by: | nobody |
| Resolution: | None | Closed on: | |
| Version: | 8.6.18, 9.0.5, 9.1.0 | ||
| Description: | ||||
Reproduce the error with the following code run in wish console on Windows. Note that this works fine in tclsh:
#Test4:
set batFile {C:\batTest\bat test\test.bat}
set arg1 {arg with spaces}
set arg2 8
set command [list $batFile $arg1 $arg2]
exec {*}$command
Output:
'C:\batTest\bat' is not recognized as an internal or external command,
operable program or batch file.
Where the bat file just outputs all arguments given:
@echo off
(for %%a in (%*) do (
echo %%a
))
Proper output can be reproduced if the space if removed from the bat file path or the argument:
(bin) 54 % #Test1:
set batFile {C:\batTest\bat test\test.bat}
set arg1 {argNoSpaces}
set arg2 8
set command [list $batFile $arg1 $arg2]
exec {*}$command
Output:
argNoSpaces
8
(bin) 64 % #Test3:
set batFile {C:\batTest\test.bat}
set arg1 {arg with spaces}
set arg2 8
set command [list $batFile $arg1 $arg2]
exec {*}$command
Output:
"arg with spaces"
8
I have tested this in an older version of tcl (8.5.9) and it works fine.
| ||||
| User Comments: | ||||
anonymous added on 2024-02-23 07:34:22:
When it's a batch job, i.e. something .bat, wish generates:
cmd.exe /c "pa th\to.bat" "pa th/to.txt" 8
and that fails. If you enter that into a windows cmd window, it also fails *because* it needs to have another set of quotes around the whole string following the /c.
Changing that in a cmd window to:
cmd.exe /c ""pa th\to.bat" "pa th/to.txt" 8"
and it works.
When the path to the batch file has no spaces, it does not quote that, *and* will fail if you do add quotes anyway. Now that's really weird, but in fact I saw something about that in the documentation. However, adding quotes around the entire string will also make that case work.
Now, if you use tclsh and exec, it ends up being just this:
"pa th\to.bat" "pa th/to.txt" 8
and that works from tclsh and also in a cmd window.
It's because the call to HasConsole() returns true in tclsh so that the command line is not prefixed with cmd.exe /c
Here's the key code:
if (HasConsole()) {
createFlags = 0;
} else if (applType == APPL_DOS) {
/*
* Under NT, 16-bit DOS applications will not run unless they can
* be attached to a console. If we are running without a console,
* run the 16-bit program as an normal process inside of a hidden
* console application, and then run that hidden console as a
* detached process.
*/
startInfo.wShowWindow = SW_HIDE;
startInfo.dwFlags |= STARTF_USESHOWWINDOW;
createFlags = CREATE_NEW_CONSOLE;
TclDStringAppendLiteral(&cmdLine, "cmd.exe /c");
} else {
createFlags = DETACHED_PROCESS;
}
oehhar added on 2024-02-23 09:57:40:
The upper code is in file win\tclWinPipe.c line 1126. The comment above the code
} else if (applType == APPL_DOS) {
/*
* Under NT, 16-bit DOS applications will not run unless they can
* be attached to a console. If we are running without a console,
* run the 16-bit program as an normal process inside of a hidden
* console application, and then run that hidden console as a
* detached process.
*/
only speaks about 16 bit DOS applications.
So, we have two possible solutions:
We probably need tests in tk for this, so it is a double-project bug. Any comment appreciated, Harald oehhar added on 2024-02-23 10:01:52:
I have not traced it. But it may happen, that the name of the batch file is replaced by the 8 character short name in ApplicationType(). So much work to do, renovate this very old code may be a challenge... Take care, Harald ralfixx added on 2024-02-26 11:53:12:
This describes the quoting required in the "Remarks" section: https://learn.microsoft.com/en-us/windows-server/administration/windows-commands/cmd oehhar added on 2024-02-26 14:09:08:
Please find two possible branches: Adding quotesSee branch bug-f91ab723f3-quoting starting with commit [0530fbcf2d]. A verbatim " is added around the argument. This causes the following test failure:
==== winFCmd-3.10 TclpDeleteFile: path is readonly FAILED
==== Contents of test case:
createfile tf1
testchmod 0 tf1
testfile rm tf1
file exists tf1
---- Test generated error; Return code was: 1
---- Return code should have been one of: 0 2
---- errorInfo: EACCES
while executing
"testfile rm tf1"
("uplevel" body line 4)
invoked from within
"uplevel 1 $script"
---- errorCode: NONE
==== winFCmd-3.10 FAILED
Removing cmd.exeSee branch bug-f91ab723f3-no-cmd starting with commit [bdca8a3971]. The special handling with "cmd.exe /c" of batch files is totally removed. Dead CodeWhile looking into this, I remarked, that the following stubs-function returns a constant value:
int
TclWinGetPlatformId(void)
{
return VER_PLATFORM_WIN32_NT;
}
Thus, the else branch in win/tclWinPipe.c line 1092
if (TclWinGetPlatformId() == VER_PLATFORM_WIN32_NT) {
....
} else {
if (HasConsole()) {
createFlags = 0;
} else {
createFlags = DETACHED_PROCESS;
}
if (applType == APPL_DOS) {
Tcl_SetObjResult(interp, Tcl_NewStringObj(
"DOS application process not supported on this platform",
-1));
Tcl_SetErrorCode(interp, "TCL", "OPERATION", "EXEC", "DOS_APP",
NULL);
goto end;
}
}
can never be reached.
This part is removed with commit [69a34921d1] in branch bug-f91ab723-dead-code-removal. Unfortunately, I always get a lot of test failures I am not able to explain (see below). Test failuresI ran tests in all 3 branches plus core-8-6-branch. I always get the following test failures. This is quite annoying, as the current 8.6.14rc1 has no test failures.
==== fCmd-9.3 file rename: comprehensive: file to new name FAILED
==== Contents of test case:
createfile tf1
createfile tf2
testchmod 0o444 tf2
file rename tf1 tf3
file rename tf2 tf4
list [lsort [glob tf*]] [file writable tf3] [file writable tf4]
---- Test generated error; Return code was: 1
---- Return code should have been one of: 0 2
---- errorInfo: error renaming "tf2" to "tf4": permission denied
while executing
"file rename tf2 tf4"
("uplevel" body line 6)
invoked from within
"uplevel 1 $script"
---- errorCode: POSIX EACCES {permission denied}
==== fCmd-9.3 FAILED
==== fCmd-9.5 file rename: comprehensive: file to self FAILED
==== Contents of test case:
createfile tf1 tf1
createfile tf2 tf2
testchmod 0o444 tf2
file rename -force tf1 tf1
file rename -force tf2 tf2
list [contents tf1] [contents tf2] [file writable tf1] [file writable tf2]
---- Test generated error; Return code was: 1
---- Return code should have been one of: 0 2
---- errorInfo: error renaming "tf2": permission denied
while executing
"file rename -force tf2 tf2"
("uplevel" body line 6)
invoked from within
"uplevel 1 $script"
---- errorCode: POSIX EACCES {permission denied}
==== fCmd-9.5 FAILED
==== fCmd-9.7 file rename: comprehensive: file to existing file FAILED
==== Contents of test case:
createfile tf1
createfile tf2
createfile tfs1
createfile tfs2
createfile tfs3
createfile tfs4
createfile tfd1
createfile tfd2
createfile tfd3
createfile tfd4
testchmod 0o444 tfs3
testchmod 0o444 tfs4
testchmod 0o444 tfd2
testchmod 0o444 tfd4
set msg [list [catch {file rename tf1 tf2} msg] $msg]
file rename -force tfs1 tfd1
file rename -force tfs2 tfd2
file rename -force tfs3 tfd3
file rename -force tfs4 tfd4
list [lsort [glob tf*]] $msg [file writable tfd1] [file writable tfd2] [file writable tfd3] [file writable tfd4]
---- Test generated error; Return code was: 1
---- Return code should have been one of: 0 2
---- errorInfo: error renaming "tfs2" to "tfd2": permission denied
while executing
"file rename -force tfs2 tfd2"
("uplevel" body line 18)
invoked from within
"uplevel 1 $script"
---- errorCode: POSIX EACCES {permission denied}
==== fCmd-9.7 FAILED
==== fCmd-9.10 file rename: comprehensive: file to new name and dir FAILED
==== Contents of test case:
createfile tf1
createfile tf2
file mkdir td1
testchmod 0o444 tf2
file rename tf1 [file join td1 tf3]
file rename tf2 [file join td1 tf4]
list [catch {glob tf*}] [lsort [glob -directory td1 t*]] [file writable [file join td1 tf3]] [file writable [file join td1 tf4]]
---- Test generated error; Return code was: 1
---- Return code should have been one of: 0 2
---- errorInfo: error renaming "tf2" to "td1/tf4": permission denied
while executing
"file rename tf2 [file join td1 tf4]"
("uplevel" body line 7)
invoked from within
"uplevel 1 $script"
---- errorCode: POSIX EACCES {permission denied}
==== fCmd-9.10 FAILED
==== winFCmd-3.10 TclpDeleteFile: path is readonly FAILED
==== Contents of test case:
createfile tf1
testchmod 0 tf1
testfile rm tf1
file exists tf1
---- Test generated error; Return code was: 1
---- Return code should have been one of: 0 2
---- errorInfo: EACCES
while executing
"testfile rm tf1"
("uplevel" body line 4)
invoked from within
"uplevel 1 $script"
---- errorCode: NONE
==== winFCmd-3.10 FAILED
QuestionsMay I ask for an opinion what is wise? Those are the actions of a person with no experience here. May someone double-check the removal of the dead code? Thank you all and take care, Harald anonymous added on 2024-02-28 00:41:10:
Note that the code line,
if (TclWinGetPlatformId() == VER_PLATFORM_WIN32_NT) {
is no longer in 9.0b1, which was where I was getting the problem with cmd.exe /c and the quoting.
For 8.6.13, I couldn't tell exactly what command line was being generated, and so having just built 9.0b1 from source, I used that to instrument the code. I did see it take the path and build up the cmd.exe /c so that should be fixed regardless.
oehhar added on 2024-02-28 08:01:33:
Great. It is now removed in 8.6(.15) too. It would be great, if someone could test or comment the two bugfix branches. Take care, Harald serhiy.storchaka added on 2026-10-14 14:31:39:
This is the same bug as [6dacb3b6f0] (2013). Still reproducible with wish 8.6.18, 9.0.5 and 9.1, for any argument that needs quoting, including serhiy.storchaka added on 2026-10-14 14:58:45:
I tested both branches (applied to the current core-8-6-branch) on Windows 11, with wish and tclsh. bug-f91ab723f3-no-cmd fixes the quoting, but breaks batch files in wish: without the hidden console of cmd.exe, console programs run from the batch file get their own consoles, so their output is lost, and ping ... | findstr ... in the batch file hangs. bug-f91ab723f3-quoting has the right idea, but the closing quote was appended after BuildCommandLine() converted cmdLine to WCHAR, so a single byte was added to a wide string: the command line got garbage at the end (e.g. test.bat"A, 8?u), and many calls failed. I committed a fix on top of it, in the same branch bug-f91ab723f3-quoting (which is against 8.6): [30bc26a91e] appends the quote in BuildCommandLine() before the conversion. With it all cases work in wish as in tclsh: spaces in the path, serhiy.storchaka added on 2026-10-25 08:54:48:
Rebased the fix onto main as bug-f91ab723f3-quoting-main: the command after | ||||
