Taskkill inside TCL script (using foreach) is not working - tcl

I need to browse a URL using Internet Explorer, and close using taskkill through TCL script. I am using following TCL script for this.
My TCL Script:
set data [open input_url.txt r]
set test [read $data]
foreach url $test {
exec "C:/Program Files/Internet Explorer/IEXPLORE.EXE" $url
after 2000
exec "C:/WINDOWS/System32/taskkill.exe" /IM IEXPLORE.EXE /F
}
input_url.txt content:
clickshare upload.com upload.to 10upload.com 123upload.pl 139pan.com 163pan.com
But When I run this script, Browser with first URL is opened. But nothing is happening after this. After 2-3 minutes, if I close the browser manually, I am seeing the following error:
C:\Users\kumar\Desktop\test>tclsh stack_question.tcl
child process exited abnormally
while executing
"exec "C:/Program Files/Internet Explorer/IEXPLORE.EXE" $url"
("foreach" body line 2)
invoked from within
"foreach url $test {
exec "C:/Program Files/Internet Explorer/IEXPLORE.EXE" $url
after 2000
exec "C:/WINDOWS/System32/taskkill.exe" /IM IEXPLO..."
(file "stack_question.tcl" line 3)
C:\Users\kumar\Desktop\test>
I am able to kill the browser session manually using taskkill.exe as shown below:
C:\Users\kumar\Desktop\test>tclsh
% exec "C:/WINDOWS/System32/taskkill.exe" /IM IEXPLORE.EXE /F
SUCCESS: The process "iexplore.exe" with PID 3948 has been terminated.
SUCCESS: The process "iexplore.exe" with PID 3744 has been terminated.
%
Could any one please help me to fix this issue?
Thanks in advance.

It seems like exec is waiting for iexplore.exe to finish before it continues execution. In order to allow immediate return use start command:
exec cmd.exe /c start iexplore.exe $url
This will return immediately.

Related

Windows batch start chrome process with defined process ID

I have to start a Web Application with a batch file in the Chrome Browser with a predefined process ID so i can kill that specific Chrome Window later with another batch file. Is there any way to to this?
By typing this command on the CMD console you can see how to create a process :
wmic process call create /?
And this too : How to terminate a Process :
wmic process call terminate /?
So, you can give a try for this batch file :
#echo off
set "targetfile=C:\Program Files\Google\Chrome\Application\chrome.exe"
set targetfile=%targetfile:\=\\%
#for /f "tokens=2 delims==; " %%# in ('wmic PROCESS CALL CREATE "%targetfile%" ^|findstr /I "ProcessId"') do set "PID=%%#"
echo The Process is created with PID=%PID%
pause
wmic process where ProcessId="%PID%" call terminate
REM Taskkill /PID %PID%
pause
And you can create a Subroutine named : :Create_Process <TargetFile> <PID> in order to call it like this :
#echo off
Title Start chrome process with a defined process ID
set "TargetFile=C:\Program Files\Google\Chrome\Application\chrome.exe"
Call :Create_Process "%TargetFile%" PID
echo The Process is created with PID=%PID%
pause
wmic process where ProcessId="%PID%" Call Terminate
REM Taskkill /PID %PID%
pause
Exit
::-----------------------------------------------------------------
:Create_Process <TargetFile> <PID>
Set "TargetFile=%~1"
Set TargetFile=%TargetFile:\=\\%
#for /f "tokens=2 delims==; " %%# in (
'wmic PROCESS CALL CREATE "%TargetFile%" ^|findstr /I "ProcessId"'
) do set "%2=%%#"
Exit /B
::-----------------------------------------------------------------

Invoke command line as in a batch script

I have this batch file with command:
xyz.exe -parm1 path1/a.wav > path2/a.txt
How can this command be executed in TCL script, so that xyz.exe when called with arguments as parm1 and input path path1 of wav file a.wav, produces op that is redirected to a.text file in path2?
I have very basic TCL knowledge, but I couldn't find way of redirection.
sedy
Tcl's exec command knows how to redirect command output into a file. You can just do this:
exec xyz.exe -parm1 path1/a.wav > path2/a.txt
Got it working as below:
set ip_pth path1/a.wav
set op_pth path2/a.txt
set lf [open $op_pth w]
puts $lf [exec xyz.exe -parm1 $ip_pth]
close $lf

How do I launch a particular URL the same time daily in Chrome

I want to launch a particular URL in chrome every day at the same time. How can I achieve this using command line?
There are two ways to do this. The first being from a single command line. You will want to create a new task in Task Scheduler and have it run a command at a desired time. If you wish to use a different browser that supports command lines, be sure to use _ for any spaces in the directory path.
Command line:
SchTasks /Create /SC DAILY /TN "New_Task" /TR "start "C:\Program_Files_(x86)\Google\Chrome\Application\chrome.exe" www.stackoverflow.com" /ST 09:00
The second option is to use a batch file you store somewhere and it will be called to using the SchTasks. Simply create the site1.bat and place it somewhere safe example C:\Windows\My Tasks.
From Batch:
#ECHO OFF
#set Task_Name=Task1
#Set Time=09:00
#set Site=www.stackoverflow.com
schtasks /query /TN "%Task_Name%" >NUL 2>&1
IF %ERRORLEVEL% EQU 0 (goto :EXISTS) ELSE (goto :CREATE)
:CREATE
Set Folder=%~dp0
Set Name=%~nx0
Echo Task does not already exist, creating it now.
SchTasks /Create /SC DAILY /TN "%Task_Name%" /TR "%Folder%%Name%" /ST %Time%
goto :eof
:EXISTS
start "C:\Program Files (x86)\Google\Chrome\Application\chrome.exe" %Site%
goto :eof

How to do 'svn checkout URL' using exec?

I'm trying to checkout Joe English's tile-extras from Github using svn using a Tcl script.
The required command is
svn checkout https://github.com/jenglish/tile-extras.git path
I have some code that boils down to
exec C:/cygwin64/bin/svn.exe checkout \
https://github.com/jenglish/tile-extras.git C:/cygwin64/tmp/TCL61416]
which fails with the message
couldn't execute "C:\cygwin64\bin\svn.exe checkout
https:\github.com\jenglish\tile-extras.git
C:\cygwin64\tmp\TCL61416": No error
Pasting the command quoted in the error message into a Windows Command Prompt window, I see
svn: E125002: 'https:\github.com\jenglish\tile-extras.git' does not appear to be a URL
So, the problem seems to be that exec converts Tcl-style paths to Unix-style a little over-enthusiastically. Is there any way I can prevent it from converting https://github.com/jenglish... to https:\github.com\jenglish...?
For information, I'm running on Windows 10, with cygwin (setup version 2.889 (64 bit)), svn 1.9.7 and tcl version 8.6.7 (via ActiveTcl 8.6.7.0).
UPDATE
Here is my actual code, which I'm only slightly embarrassed by:
# svn wrapper proposed by Donal Fellows at
# http://stackoverflow/questions/49224268
proc svn {args} {
exec {*}[auto_execok svn] {*}$args <#stdin >#stdout }
# Checkout from github to a temporary repository
set repository https://github.com/jenglish/tile-extras.git set
svnImage [auto_execok svn]
set fil [file tempfile tempfnm] close $fil file delete $tempfnm
set tempRepo [file rootname $tempfnm] puts stdout tempRepo:\ $tempRepo
file mkdir $tempRepo
set svnCmd [list svn checkout $repository [file nativename $tempRepo]]
puts stdout svnCmd:\ $svnCmd eval $svnCmd
# Determine the tile-extras sources
set sourceFiles {keynav.tcl icons.tcl}
set targets [file nativename [file join $tempRepo trunk *.tcl]]
foreach filnam [split [svn ls $targets] \n] {
if {[string match *.tcl $filnam] && [lsearch $sourceFiles $filnam] < 0} {
lappend sourceFiles $filnam
}
}
And here is the result
$ tclsh foo.tcl
tempRepo: C:/cygwin64/tmp/TCL61838
svnCmd: svn checkout
https://github.com/jenglish/tile-extras.git {C:\cygwin64\tmp\TCL61838}
A C:\cygwin64\tmp\TCL61838/branches
A C:\cygwin64\tmp\TCL61838/trunk
A C:\cygwin64\tmp\TCL61838/trunk/README.md
A C:\cygwin64\tmp\TCL61838/trunk/dialog.tcl
A C:\cygwin64\tmp\TCL61838/trunk/doc
A C:\cygwin64\tmp\TCL61838/trunk/doc/dialog.n
A C:\cygwin64\tmp\TCL61838/trunk/doc/keynav.n
A C:\cygwin64\tmp\TCL61838/trunk/icons.tcl
A C:\cygwin64\tmp\TCL61838/trunk/keynav.tcl
A C:\cygwin64\tmp\TCL61838/trunk/license.terms
A C:\cygwin64\tmp\TCL61838/trunk/pkgIndex.tcl
Checked out revision 7.
svn: E155007: '/home/alan/C:\cygwin64\tmp\TCL61838\trunk\*.tcl' is not a working copy
while executing "exec {*}[auto_execok svn] {*}$args <#stdin >#stdout"
(procedure "svn" line 2)
invoked from within "svn ls $targets"
invoked from within "split [svn ls $targets] \n"
invoked from within "foreach filnam [split [svn ls $targets] \n] {
if {[string match *.tcl $filnam] && [lsearch $sourceFiles $filnam] < 0} {
lappend sourceFiles $filn..."
(file "foo.tcl" line 30)
$ ls /tmp/TCL61838/
$
The directory /tmp/TCL61838 is empty, so it seems the svn checkout command didn't complete completely happily. I also see an unpleasant mixture of forward slashes and backslashes being reported by svn.
Thanks in advance for any more help.
Given the error message, it looks like you're getting word boundaries wrong in the code that you've not shown us; while you might believe the code “boils down to” to that exec, it's not actually done that. Also, you've flipped the slashes in the URL which won't work, but that's probably a side-effect of something else.
Alas, I can't quite guess how to fix things for you. There's just too many options. I provide a suggestion below, but there's no telling for sure whether it will work out.
Diagnosis Methodology
The evidence for why I believe that the problem is what I say? This interactive session log (on OSX, but the generic behaviour should be the same):
% exec cat asdkfajh
cat: asdkfajh: No such file or directory
% exec "cat akjsdhfdkj"
couldn't execute "cat akjsdhfdkj": no such file or directory
% exec "cat aksdjhfkdf" skdjfghd
couldn't execute "cat aksdjhfkdf": no such file or directory
The first case shows an error from an external program. The second case shows an error due to no-such-program. The third case shows that arguments are not reported when erroring due to to no-such-program.
This lets me conclude that both C:\cygwin64\bin\svn.exe and its arguments (checkout, https:\github.com\jenglish\tile-extras.git and C:\cygwin64\tmp\TCL61416) were actually passed as a single argument to exec, a fairly common error, and that the problems lie in the preparatory code. You don't show us the preparatory code, so we can't truly fix things but we can make suggestions that address the common problems.
Suggested Approach
A good way to reduce these errors is to write a small wrapper procedure:
proc svn {args} {
# I add in the I/O redirections so svn can ask for a password
exec {*}[auto_execok svn] {*}$args <#stdin >#stdout
}
This would let you write your call to svn as:
svn checkout $theURL [file nativename $theDirectory]
and it would probably Just Work™. Also note that only the directory name goes through file nativename; the URL does not. (We could embed the call to file nativename in the procedure if we were making a specialised procedure to do checkouts, but there's too much variation in the full svn program to let us do that. The caller — you — has to deal with it.)

Communication between Tcl scripts

I was successfully able to redirect the standard output of a script called by my GUI (tcl/tk) using:
exec [info nameofexecutable] jtag.tcl >#$file_id
Here's a description of my system.
Now I want to be able to tell jtag.tcl to stop data acquisition (which is in an infinite loop) when I click "stop" button. Is it possible through exec or should I use open instead?
The exec command waits until the subprocess finishes before returning control to you at all (unless you run totally disconnected in the background). To maintain control you need to open a pipeline:
# Not a read pipe since output is redirected
set pipe [open |[list [info nameofexecutable] jtag.tcl >#$file_id] "w"]
You also need to ensure that the other process listens for when the pipe is closed or have some other protocol for telling the other end to finish. The easiest mechanism to do that is for the remote end to put the pipe (which is its stdin) into non-blocking mode and to check periodically for a quit message.
# Putting the pipe into nonblocking mode
fconfigure stdin -blocking 0
# Testing for a quit message; put this in somewhere it can be called periodically
if {[gets stdin] eq "quit"} {
exit
}
Then the shutdown protocol for the subprocess becomes this in the parent process:
puts $pipe "quit"
close $pipe
Alternatively, kill the subprocess and pick up the results:
exec kill [pid $pipe]
# Need the catch; this will throw an error otherwise because of the signal
catch {close $pipe}