mIRC Home    About    Download    Register    News    Help

Print Thread
Joined: Feb 2004
Posts: 2,019
Hoopy frood
OP Offline
Hoopy frood
Joined: Feb 2004
Posts: 2,019
EDIT: Before anyone tries this code, be aware you need atleast mIRC 6.16 or it will not work!

Bug number one:

$comval seems to suffer from a severe inefficiency, where looping through a collection with $comval is significantly slower to its counterpart being the "item" method, which you normally use in other languages such as VBScript, since $comval is an mIRC identifier. One would expect $comval to be more efficient, but the difference is really striking.

Consider the following code, note that it will take a few seconds before it starts echoing stuff to your active window, so give it some time.

Code:
alias mirclinks {
  var %t
  .comopen ie.main internetexplorer.application
  showmirc -s
  %t = $com(ie.main,navigate,1,bstr*,http://www.mirc.com/get.html)
  :loop
  %t = $ticks + 300
  while ($ticks < %t) !
  %t = $com(ie.main,readystate,2)
  if ($com(ie.main).result != 4) goto loop
  %t = $com(ie.main,document,2,dispatch* ie.doc)
  %t = $com(ie.doc,links,2,dispatch* ie.links)
 
  var %total = $comval(ie.links,0), %ticks, %i
  echo -ac info Total amount of links: %total
  echo -a $chr(15)

  echo -ac info * Looping with $!comval from 1 - %total
  %ticks = $ticks
  %i = 1
  while (%i <= %total) {
    %t = $comval(ie.links,%i,href)
    inc %i
  }
  echo -ac info * Time taken with first approach: $calc($ticks - %ticks) ms
  echo -a $chr(15)
  echo -ac info * Looping with $!comval from %total - 1
  %ticks = $ticks
  %i = %total
  while (%i) {
    %t = $comval(ie.links,%i,href)
    dec %i
  }
  echo -ac info * Time taken with second approach: $calc($ticks - %ticks) ms
  echo -a $chr(15)
  echo -ac info * Looping with item method to access the collection 
  %ticks = $ticks
  %i = 0
  while (%i < %total) {
    %t = $com(ie.links,item,1,uint,%i,dispatch* ie.item)
    if ($com(ie.item)) {
      %t = $com(ie.item,href,2)
      %t = $com(ie.item).result
      .comclose ie.item
    }
    inc %i
  }
  echo -ac info * Time taken with third approach: $calc($ticks - %ticks) ms
  :error
  if ($com(ie.links)) .comclose $v1
  if ($com(ie.doc)) .comclose $v1
  if ($com(ie.main)) .comclose $v1 $com($v1,close,1)
}


My results:

  • * Total amount of links: 131

    * Looping with $comval from 1 - 131
    * Time taken with first approach: 2109 ms

    * Looping with $comval from 131 - 1
    * Time taken with second approach: 2125 ms

    * Looping with item method to access a collection
    * Time taken with third approach: 172 ms

The results speak for theirselves, the two methods (looping from front to back, and back to front) take around 2 seconds, whilst the item method, which consists of more code actually only takes 172 milliseconds.


Bug number two:

Often, when I dispatch to a childobject which holds a collection, $comval will not be able to access any of its properties. The worst thing is, that the item method also doesn't work in mIRC on this collection, whereas this does works fine in VBScript.

Consider the following code, but note that you must atleast have 1 internetexplorer window open connected to a site (will also work if you have tabs open in Avantbrowser, Maxthon or other IE based browsers)

Code:
alias shellwindows {
  var %t, %i = 0, %total
  .comopen shell shell.application
  %t = $com(shell,windows,3,dispatch* wins)
  %t = $com(wins,count,3)
  %total = $com(wins).result

  echo -a Total amount of shell windows found: %total
  echo -a But what does comval say? -> $comval(wins,0)

  echo -a Trying to access this collection with the "item" method:

  while (%i < %total) {
    %t = $com(wins,item,1,uint,%i,dispatch* item)
    if ($com(item)) {
      echo -a Item %i retrieved with dispatch
      .comclose item
    }
    inc %i
  }

  echo -a Using VBScript to access the collection:

  window -h @@
  %t = aline @@

  %t dim s
  %t set shell = createobject("shell.application")
  %t set wins = shell.windows
  %t For each item in wins
  %t s = s & item.locationurl & VbCrLf
  %t Next
  %t wscript.echo s

  savebuf @@ wins.vbs
  close -@ @@
  run wins.vbs
  .timer 1 2 .remove wins.vbs
  :error
  if ($com(shell)) .comclose $v1
  if ($com(wins)) .comclose $v1
}


My results:

  • Total amount of shell windows found: 8
    But what does comval say? -> 0
    Trying to access this collection with the "item" method:
    Using VBScript to access the collection:

The count property clearly shows there are 8 shellwindows open, whereas $comval says the collection is empty. Nothing is echoed in the while loop that attempts to dispatch with the item method. Finally, the VBScript executes, and you see the locationurls of the shellwindows in a message box.

Note that in the while loop where I try to retrieve an item object with the line:

%t = $com(wins,item,1,uint,%i,dispatch* item)

I use "1", since it's a method, but changing it to 2 or 3 doesn't change anything. Just thought I'd mention before someone tries to suggest this wink

All of this was tested on mIRC 6.16, Windows XP+SP2


Gone.
Joined: Apr 2004
Posts: 871
Sat Offline
Hoopy frood
Offline
Hoopy frood
Joined: Apr 2004
Posts: 871
I don't have any experience with bug number two, but I can fully confirm bug number one. At least one reason for the inefficiency is the fact that a new iterator is created for each individual $comval call, then looped through N times (N as passed to that $comval call), used, and closed again. It would be great if the iterator were "cached" instead; scripts typically use $comval with values from 1 to the maximum in sequence anyway.


Saturn, QuakeNet staff
Joined: Jan 2003
Posts: 2,523
Q
Hoopy frood
Offline
Hoopy frood
Q
Joined: Jan 2003
Posts: 2,523
Regarding the 2nd bug, you can use Item in mirc (and all properties of the item child object that's created) but you need to change the type from uint to i2 or i4. Why/how this is related to $comval not working, I have no idea.

Oh and I can confirm the 1st 'bug' of course. Caching the results for the duration of the routine (ie the current alias and any parent aliases) would be really wonderful, not just for $comval() but for any other identifier that currently works like that, with $hget(name,N).item being the most important imo.


/.timerQ 1 0 echo /.timerQ 1 0 $timer(Q).com
Joined: Feb 2004
Posts: 2,019
Hoopy frood
OP Offline
Hoopy frood
Joined: Feb 2004
Posts: 2,019
How weird, I've always been able to access the item method with an uint, changing to i2 or i4 indeed works now. I had tried before with i1, which also doesnt work, so didn't bother with versions higher than 1, since i1 already supports the necessary range :rolleyes:

I still see this issue as a $comval bug, it's a collection so $comval should be able to be used on it.


Gone.
Joined: Oct 2004
Posts: 73
M
Babel fish
Offline
Babel fish
M
Joined: Oct 2004
Posts: 73
How would I test this bug with Firefox 1.5? Now that personally IE6 is just a little too "zero-day exploit" friendly for my liking.

Joined: Feb 2004
Posts: 2,019
Hoopy frood
OP Offline
Hoopy frood
Joined: Feb 2004
Posts: 2,019
Whether you use Firefox or IE for your everyday browsing does not matter to test this bug. As long as you have IE installed on your system (every windows user does), you will be able to reproduce it with the code in my first post. It doesn't require for you to open any browser, it is all done programmatically and hidden.

Note that you don't need to use that code, any collection that $comval is able to retrieve where the item method works on, can show you $comval's inefficiency.


Gone.

Link Copied to Clipboard