mIRC Home    About    Download    Register    News    Help

Print Thread
#274004 06/09/26 07:38 PM
Joined: Sep 2026
Posts: 2
O
Ook2 Offline OP
Bowl of petunias
OP Offline
Bowl of petunias
O
Joined: Sep 2026
Posts: 2
I have a small script that I use to launch programs via $com and wscript.shell using the exec method as this allows me to control the exe to some extent,
All works fine until I try to read the stdout & call AtEndOfStream property or ReadLine method when I am at the end, this cause mIRC to freeze until the exe exits.

Shouldn't AtEndOfStream simply give a true result?
I've looked online at other languages using com (vbscript etc..) and they have examples of this working as expected.
This only affects still running programs, if the program runs and quits then I can read the stdout with no issues.
System used: Win 7 Ultimate x64

Using the script below:
Code
alias testcom {
  set -e %testcom $exec(cmd.exe)
  echo eos: $exec(%testcom).eos == $false
  echo line1: $exec(%testcom).readline = $true
  echo line2: $exec(%testcom).readline = $true Microsoft Windows [Version 6.1.7601]
  echo line3: $exec(%testcom).readline = $true Copyright (c) 2009 Microsoft Corporation. All rights reserved.
  echo line4: $exec(%testcom).readline = $true
  ; this next line freezes
  echo line5: $exec(%testcom).readline = $true C:\mIRC>
  echo eos: $exec(%testcom).eos == $true
  echo terminate: $exec(%testcom).terminate
  comclose %testcom
}

Here is the exec script I'm using
Code
; $1- = item to execute & args
; or if $prop is set
; $1 = com object returned by exec()
; $prop = Terminate or pid or Status or eos or Line or ReadLine or WriteLine or debug
alias exec {
  if ($0 == 0) return
  if ($prop) {
    if (!$com($1)) return
    if ($prop == Terminate) noop $com($1,Terminate,1)
    elseif ($prop == pid) noop $com($1,ProcessID,2)
    elseif ($prop == Status) noop $com($1,Status,2)
    elseif ($prop == EOS) {
      ; BUG: causes mirc to freeze when used on a running task when it should return $true! Unfreezes on task exit.
      var %exec_stdout exec_stdout $+ $ticks
      if ((!$com($1,StdOut,2,dispatch* %exec_stdout)) || ($comerr)) return -1
      .timer 1 0 .comclose %exec_stdout
      if ((!$com(%exec_stdout,AtEndOfStream,2)) || ($comerr)) return -2
      return $com(%exec_stdout).result
    }
    elseif ($prop == ReadLine) {
      ; BUG: causes mirc to freeze when used on a running task when it should return $false! Unfreezes on task exit.
      ; also freezes if ReadLine is used without AtEndOfStream check.
      ; NB: results can be an empty line, $true used to make it clear this is a good result
      var %exec_stdout exec_stdout $+ $ticks
      if ((!$com($1,StdOut,2,dispatch* %exec_stdout)) || ($comerr)) return -1
      .timer 1 0 .comclose %exec_stdout
      if ((!$com(%exec_stdout,AtEndOfStream,2)) || ($comerr)) return -2
      if ($com(%exec_stdout).result) return $false
      if ((!$com(%exec_stdout,ReadLine,1)) || ($comerr)) return -3
      return $true $com(%exec_stdout).result
    }
    elseif ($prop == WriteLine) {
      ; NB: results can be an empty line, $true used to make it clear this is a good result
      var %exec_stdin exec_stdout $+ $ticks
      if ((!$com($1,StdIn,2,dispatch* %exec_stdin)) || ($comerr)) return -1
      .timer 1 0 .comclose %exec_stdin
      if ((!$com(%exec_stdin,WriteLine,1,bstr,$2)) || ($comerr)) return -3
      return $true
    }
    elseif ($prop == Line) {
      var %exec_stdout exec_stdout $+ $ticks
      if ((!$com($1,StdOut,2,dispatch* %exec_stdout)) || ($comerr)) return -1
      .timer 1 0 .comclose %exec_stdout
      if ((!$com(%exec_stdout,Line,2)) || ($comerr)) return -2
      return $com(%exec_stdout).result
    }
    elseif ($prop == debug) {
      echo -s start
      var %exec_stdout exec_stdout $+ $ticks
      if ((!$com($1,StdOut,2,dispatch* %exec_stdout)) || ($comerr)) return -1
      .timer 1 0 .comclose %exec_stdout
      echo -s got stdout
      if ((!$com(%exec_stdout,AtEndOfStream,2)) || ($comerr)) return -2
      echo -s got AtEndOfStream
      var %res = $com(%exec_stdout).result
      echo -s ok
      return %res
    }
    else return
    return $com($1).result
  }
  var %% = s $+ $ticks, %exec_com = $+(%%,_exec)
  if (!$com(%%)) .comopen %% wscript.shell
  if ($comerr) return
  .comclose %% $com(%%,exec,1,bstr,$1-,dispatch* %exec_com)
  return %exec_com
}

Ook2 #274005 07/09/26 11:12 AM
Joined: Dec 2002
Posts: 3,926
Hoopy frood
Offline
Hoopy frood
Joined: Dec 2002
Posts: 3,926
When I run your script, the error "* Invalid parameters: $com" is reported when a second call to "ReadLine" is made with a parameter at the line:

Quote
echo line2: $exec(%testcom).readline = $true Microsoft Windows [Version 6.1.7601]

So I have not been able to reproduce the issue here yet.

Khaled #274006 07/09/26 04:52 PM
Joined: Dec 2002
Posts: 3,926
Hoopy frood
Offline
Hoopy frood
Joined: Dec 2002
Posts: 3,926
Looking at your script, it was specifying two parameters in the $com() call instead of one. If I change it to one, it seems to work as expected. As for the momentary pause before the $com() call returns, I was able to reproduce this every twenty calls or so but it was pretty intermittent. mIRC is dependent on ActiveX returning from the call in this case, so there isn't anything it can actually do about this. As far as I can see, $com() is just waiting for the call to return.

Khaled #274007 07/09/26 10:45 PM
Joined: Sep 2026
Posts: 2
O
Ook2 Offline OP
Bowl of petunias
OP Offline
Bowl of petunias
O
Joined: Sep 2026
Posts: 2
I have done some more research into this & it seems to be all com's fault, so nothing mirc can do about it frown
I also found the script issue, the .timer 1 0 .comclose line was causing the issue when the commands were used quickly

Fixed version....

Code
; $1- = item to execute & args
; or if $prop is set
; $1 = com object returned by exec()
; $prop = Terminate or pid or Status or eos or Line or ReadLine or WriteLine or debug
alias exec {
  if ($0 == 0) return
  if ($prop) {
    if (!$com($1)) return
    if ($prop == Terminate) noop $com($1,Terminate,1)
    elseif ($prop == pid) noop $com($1,ProcessID,2)
    elseif ($prop == Status) noop $com($1,Status,2)
    elseif ($prop == EOS) {
      ; BUG: causes mirc to freeze when used on a running task when it should return $true! Unfreezes on task exit.
      var %exec_stdout exec_stdout $+ $ticks
      if ((!$com($1,StdOut,2,dispatch* %exec_stdout)) || ($comerr)) return -1
      if ((!$com(%exec_stdout,AtEndOfStream,2)) || ($comerr)) var %res = -2
      else var %res = $com(%exec_stdout).result
      .comclose %exec_stdout
      return %res
    }
    elseif ($prop == ReadLine) {
      ; BUG: causes mirc to freeze when used on a running task when it should return 0! Unfreezes on task exit.
      ; NB: results can be an empty line, 1 used to make it clear this is a good result
      var %exec_stdout exec_stdout $+ $ticks
      if ((!$com($1,StdOut,2,dispatch* %exec_stdout)) || ($comerr)) return -1
      if ((!$com(%exec_stdout,AtEndOfStream,2)) || ($comerr)) var %res = -2
      elseif ($com(%exec_stdout).result) var %res = 0
      elseif ((!$com(%exec_stdout,ReadLine,1)) || ($comerr)) var %res -3
      else var %res = 1 $com(%exec_stdout).result
      .comclose %exec_stdout
      returnex %res
    }
    elseif ($prop == WriteLine) {
      var %exec_stdin exec_stdout $+ $ticks
      if ((!$com($1,StdIn,2,dispatch* %exec_stdin)) || ($comerr)) return -1
      if ((!$com(%exec_stdin,WriteLine,1,bstr,$2)) || ($comerr)) var %res = -3
      else var %res = 1
      .comclose %exec_stdin
      return %res
    }
    elseif ($prop == Line) {
      var %exec_stdout exec_stdout $+ $ticks
      if ((!$com($1,StdOut,2,dispatch* %exec_stdout)) || ($comerr)) return -1
      if ((!$com(%exec_stdout,Line,2)) || ($comerr)) var %res = -2
      else var %res = $com(%exec_stdout).result
      .comclose %exec_stdout
      return %res
    }
    elseif ($prop == debug) {
      echo -s start
      var %exec_stdout exec_stdout $+ $ticks
      if ((!$com($1,StdOut,2,dispatch* %exec_stdout)) || ($comerr)) return -1
      echo -s got stdout
      if ((!$com(%exec_stdout,AtEndOfStream,2)) || ($comerr)) var %res =  -2
      else {
        echo -s got AtEndOfStream
        var %res = $com(%exec_stdout).result
      }
      echo -s ok
      .comclose %exec_stdout
      return %res
    }
    else return
    return $com($1).result
  }
  var %% = s $+ $ticks, %exec_com = $+(%%,_exec), %exec_stdout = %exec_com $+ _stdout.txt
  if (!$com(%%)) .comopen %% wscript.shell
  if ($comerr) return
  .comclose %% $com(%%,exec,1,bstr,$1-,dispatch* %exec_com)
  return %exec_com
}


Link Copied to Clipboard