0

I'm using Windows 8.1 and I'm running a tcl script that checks the difference between files:

package require twapi
proc diff {file1 file2} {
    set f1 [open $file1 "rb"]
    set f2 [open $file2 "rb"]
    try {
        while 1 {
            if {[read $f1 4096] ne [read $f2 4096]} {
                return 0
            } elseif {[eof $f1]} {
                # The same if we got to EOF at the same time
                return [eof $f2]
            } elseif {[eof $f2]} {
                return 0
            }
        }
    } finally {
        close $f1
        close $f2
    }
}

I need to run this procedure in the background, but everytime I run it, it opens a windows terminal. I tried using a vbs script and it works:

CreateObject("Wscript.Shell").Run "diff.tcl",0,True

But I need to pass the arguments to the diff.tcl from another program so running as a vbs script is not useful.

milarepa
  • 759
  • 9
  • 28
  • 4
    I suspect this is partially to do with the associations for the Open action of the `.tcl` filetype, but I forget the details and I'm on a totally different platform so I can't just inspect directly. – Donal Fellows Dec 12 '18 at 00:11
  • Thank you, I believe that's the case. I will look into that. – milarepa Dec 12 '18 at 06:24

2 Answers2

2

The problem

What Donal said.

Specifically, your installation of Windows™ supposedly is set up to associate tclsh.exe to run files with .tcl extension in their names. (One way to learn what's the association(s) is running assoc.exe; also see ftype.exe).

tclsh.exe (the name stems from "The Tcl Shell") is an application compiled with the so-called "console subsystem" flag set on (a flag in the special header contained metainformation of an executable file on Windows™). When the OS runs such an application it notices it needs a console and so it spawns one and then runs the application in it.

The solutions

  • Try using the Run method of the WScript.Shell object and pass 0 as its second argument to hide the created window; see this for more.

  • Tcl gets shipped with another interpreter, called wish.exe (a portmanue of "The Windowed Shell") which differs from tclsh.exe by the fact it has Tk automatically available (loaded).

    You might want to explicitly run your script using wish.exe and passing it the pathname of your script as an argument.

    You might need to use wm withdraw . as the first command in your script to hide the main window created by Tk.

kostix
  • 51,517
  • 14
  • 93
  • 176
  • If you don't do any long running stuff and don't need the event loop, it might be easier to just `exit` at the end. – Johannes Kuhn Dec 12 '18 at 16:44
  • Oh, I failed to comprehend you are _already_ using wscript.shell's Run. So the question is: _what from_ are you starting your Tcl script? Is is a program? If yes, what programming language it's written in? – kostix Dec 12 '18 at 17:17
  • 1
    I'm asking because what wscript.shell does it no magic: it basically calls [`CreateProcess`](https://learn.microsoft.com/en-us/windows/desktop/api/processthreadsapi/nf-processthreadsapi-createprocessa) while tweaking the [`STARTUPINFO`](https://learn.microsoft.com/en-us/windows/desktop/api/processthreadsapi/ns-processthreadsapi-_startupinfoa) parameter passed to it in a way so that the process's window is initially hidden. – kostix Dec 12 '18 at 17:20
  • I found the solution: I was calling the script from an autohotkey script using the command "Run, tclsh diff.tcl". I just needed to add ,,hide at the end and that way it will not show the command prompt. The problem I have with wish.exe is that when I instruct wm withdraw . it loses focus from the current windows. – milarepa Dec 14 '18 at 07:01
  • @milarepa, ah, that lovely [XY Problem](https://meta.stackexchange.com/a/66378)! ;-) Please next time state clear what the real original problem is, and only present your solution to it and a new problem it caused last. – kostix Dec 14 '18 at 10:45
0

Have you thought about outputting the results to a temporary file and having whatever is downstream look for that file? You could then use your VBS method of keying the script. It's messy but it would work.

CK1
  • 472
  • 1
  • 5
  • 16