OnEvent SRT enhancement

Ideas for new features & functions

Moderators: Dorian (MJT support), JRL

User avatar
jpuziano
Automation Wizard
Posts: 1085
Joined: Sat Oct 30, 2004 12:00 am

Post by jpuziano » Wed Mar 04, 2009 10:14 pm

Hi JRL,

Its not that easy, here's what I have so far:

Code: Select all

GetWindowList>winlist
MDL>winlist

//window titles will be in vars win_title_1, win_title_2, etc.
Separate>winlist,%CRLF%,win_title
MDL>win_title_count=%win_title_count%

Let>index=0

Label>loop
Let>index=index+1
If>index>win_title_count,end
Position>Notepad,win_title_%index%,1,result
If>result=0,loop
//at this point we have found a window title containing "Notepad"
GetWindowHandle>win_title_%index%,handle
Let>display_win_title=win_title_%index%
MDL>index=%index%%CRLF%win_title=%display_win_title%%CRLF%handle=%handle%
Goto>loop

Label>end
The problem is, all three Notepad windows have exactly the same title...

Untitled - Notepad

...so each time through the loop, GetWindowHandle> returns the handle of the same Notepad window.

How do I get it to give me the handles of the other two?


Hi Bob,

I think there will be the same problem with your suggestion.

I just had an evil thought. :twisted:

As I processed each one, maybe I could use a Win32 API call to actually change the Notepad window's title... I could tack on [1] at the end. Then the next time I called GetWindowHandle> it would find the next one that matched. I get that one's handle, mess with its title and repeat. Finally, at the end of it all, I restore the titles to what they should be.

Of course, I'd rather not have to resort to messing with the window titles. As I said, this is supposed to run in the background... unnoticed by the user.

It feels like there should be a better way of dealing with this.

Am I missing something?
Last edited by jpuziano on Thu Mar 05, 2009 3:17 pm, edited 2 times in total.
jpuziano

Note: If anyone else on the planet would find the following useful...
[Open] PlayWav command that plays from embedded script data
...then please add your thoughts/support at the above post - :-)

gdyvig
Automation Wizard
Posts: 447
Joined: Fri Jun 27, 2008 7:57 pm
Location: Seattle, WA

Use IsProcessRunning as JRL suggested

Post by gdyvig » Thu Mar 05, 2009 2:47 am

Here is the link to the Macrus's code that JRL suggested you use. It uses VBSCRIPT and lists all occurrences by process name:

http://www.mjtnet.com/usergroup/viewtop ... essrunning

Gale

User avatar
jpuziano
Automation Wizard
Posts: 1085
Joined: Sat Oct 30, 2004 12:00 am

Re: Use IsProcessRunning as JRL suggested

Post by jpuziano » Thu Mar 05, 2009 8:09 am

I think I'm making progress. Window Titles seem to be of no use in this situation... since there are no MS commands that can differentiate one window from the next if they have the exact same name. Also, there are no MS commands I can use to pull the Window Handles if the titles are all the same (though there may be a VBScript method... and if so, please post).

So instead I'm going to look for all running processes where Process Name=Notepad.exe and try to pull the Process IDs and monitor those.

I started with some code Marcus posted here: Get running process info and see if a process is running

Code: Select all

VBSTART
'returns the number of copies of ProcessName that are running
'will return 0 if ProcessName is not running
Function IsProcessRunning(ProcessName)
	Set oWMIService = GetObject("winmgmts:" & "{impersonationLevel=impersonate}!\\.\root\cimv2")
	Set colProcessList = oWMIService.ExecQuery ("Select Name from Win32_Process where Name='" & ProcessName & "'")
	IsProcessRunning = colProcessList.count
End Function
VBEND
VBEval>IsProcessRunning("opera.exe"),res
MessageModal>res
I have two Notepad windows running now, here's how they look from the MS "View System Windows" tool. The numbers are the Window Handles:

263324 - Notepad "Untitled - Notepad"
1180650 - Notepad "Untitled - Notepad"

In Task Manager, I can see these two Notepad.exe processes and their PID (Process ID) values below:

2504
3164

I made some modifications to the VBScript, here's what I have so far:
mods in red wrote:VBSTART
'returns the number of copies of ProcessName that are running
'will return 0 if ProcessName is not running
'also shows each unique PID
Function IsProcessRunning(ProcessName)
Set oWMIService = GetObject("winmgmts:" & "{impersonationLevel=impersonate}!\\.\root\cimv2")
Set colProcessList = oWMIService.ExecQuery ("Select Name, Handle from Win32_Process where Name='" & ProcessName & "'")

For Each oProcess in colProcessList
MsgBox oProcess.Name & "," & oProcess.Handle
Next

IsProcessRunning = colProcessList.count

End Function
VBEND

VBEval>IsProcessRunning("notepad.exe"),res
MessageModal>res
When I ran the code, it found both Notepad windows and correctly told me what the PID values were via MsgBox commands inside the VBScript. I'd like to pass those numbers back for use in the MS code... but can't seem to do that. Can anyone with VBScript knowledge show me how to do that? Marcus? Anyone?

The idea is, I could keep calling the VBScript function, passing in "Notepad.exe" and getting back a list of PID values. I could just keep checking those against a list. When a new value appears, increment the open count. When a known value from the list is no longer being seen, increment the closed count.

Thanks for all the help so far, getting close to something workable... but this would be so much easier with either of the following:

1) An improved GetWindowList> command that could optionally return a list of Window Title / Window Handle pairs... instead of just Window Titles.

2) New OnEvent>WINDOW_JUST_OPENED and OnEvent>WINDOW_JUST_CLOSED commands that would only fire once... when a window matching the specified title parameter was instantiated or destroyed. Thinking a bit more on it... when it fires... it would be great if it returned the Window Handle involved. That would certainly make things easier. Once we know the Window Handle, there are lot of commands we can use to do whatever we want with that particular window, monitor it, etc.
jpuziano

Note: If anyone else on the planet would find the following useful...
[Open] PlayWav command that plays from embedded script data
...then please add your thoughts/support at the above post - :-)

User avatar
JRL
Automation Wizard
Posts: 3497
Joined: Mon Jan 10, 2005 6:22 pm
Location: Iowa

Post by JRL » Thu Mar 05, 2009 6:52 pm

Without a lot of explanation except this checks processes using Marcus' VBScript and DOS tasklist. There is probably a better way.

Does this work for you?

Code: Select all

VBSTART
  'returns the number of copies of ProcessName that are running
  'will return 0 if ProcessName is not running
  'also shows each unique PID
  Function IsProcessRunning(ProcessName)
  Set oWMIService = GetObject("winmgmts:" & "{impersonationLevel=impersonate}!\\.\root\cimv2")
  Set colProcessList = oWMIService.ExecQuery ("Select Name, Handle from Win32_Process where Name='" & ProcessName & "'")
  IsProcessRunning = colProcessList.count
  End Function
VBEND


Let>OriginalCount=0
Let>OriginalProcessList=
Let>NewOriginalProcessList=
GoSub>ChkPs
  Let>OriginalCount=res
  Let>LastCount=%res%-%OriginalCount%
  Message>%OriginalCount% Old Notepads running%CRLF%%LastCount% New Notepads running


If>res>0
  GoSub>RunTaskList,1
EndIf

Label>Loop
  GoSub>ChkPs
  If>res<>0
    Let>TestSum=%res%-%OriginalCount%
    If>%TestSum%<>%LastCount%
      GoSub>RunTaskList,0
      Message>%OriginalCount% Old Notepads running%CRLF%%LastCount% New Notepads running
    EndIf
  Else
    If>OriginalCount>0
      Let>OriginalCount=0
      Message>%OriginalCount% Old Notepads running%CRLF%%LastCount% New Notepads running
    EndIf
    If>LastCount>0
      Let>LastCount=0
      Message>%OriginalCount% Old Notepads running%CRLF%%LastCount% New Notepads running
    EndIf
  EndIf
Goto>Loop

SRT>ChkPs
  VBEval>IsProcessRunning("notepad.exe"),res
END>ChkPs

SRT>RunTaskList
  Let>RP_WAIT=1
  Let>RP_WINDOWMODE=0
  Run>cmd /c tasklist /fi "imagename eq notepad.exe">%temp_dir%tasklistlist.txt
  ReadFile>%temp_dir%tasklistlist.txt,proclist
  DeleteFile>%temp_dir%tasklistlist.txt
  separate>proclist,CRLF,line
  sub>line_count,1
  Let>kk=3
  Repeat>kk
    add>kk,1
    Let>value=line_%kk%
    Midstr>value,27,6,process
    If>RunTaskList_var_1=1
      ConCat>OriginalProcessList,%process%;
    Else
      Separate>OriginalProcessList,%process%;,Running
      If>running_count>1
        ConCat>NewOriginalProcessList,%process%;
      endIf
    EndIf
  Until>kk,%line_count%
  If>RunTaskList_var_1=1
  Else
    Separate>NewOriginalProcessList,;,item
    Let>OriginalCount=%item_count%-1
    If>OriginalCount<0
      Let>OriginalCount=0
    EndIf
    Let>LastCount=%res%-%OriginalCount%
    Let>OriginalProcessList=%NewOriginalProcessList%
    Let>NewOriginalProcessList=
  EndIf
END>RunTaskList

User avatar
jpuziano
Automation Wizard
Posts: 1085
Joined: Sat Oct 30, 2004 12:00 am

Post by jpuziano » Thu Mar 05, 2009 10:21 pm

Hi JRL,

Thanks but there's still a problem.

--- current behavior ---

I open 2 Notepads then run the macro, it says:

2 old notepads open
0 new notepads open


I then open 3 more Notepads, it says:

2 old notepads open
3 new notepads open


I close both of the old notepads, it says:

0 old notepads open
3 new notepads open


I close all 3 of the new notepads, it says:

0 old notepads open
0 new notepads open


That's impressive because it can differentiate between old and new notepads as it is tracking them by PID... very nice.

However that is only telling me what is open right now. I need to track activity instead. I will run through the exact same steps as above to show what I mean.

--- required behavior ---

There are already 2 notepads open. I start the macro and it should say:

0 notepads were opened
0 notepads were closed


I then open 3 more Notepads, it should say:

3 notepads were opened
0 notepads were closed


I close both of the old notepads, it should say:

3 notepads were opened
2 notepads were closed


I close all 3 of the new notepads, it should say:

3 notepads were opened
5 notepads were closed


---

I think your script could be modified to track activity... but I'll have to stare at it for a while. Thanks for this JRL... much appreciated.
jpuziano

Note: If anyone else on the planet would find the following useful...
[Open] PlayWav command that plays from embedded script data
...then please add your thoughts/support at the above post - :-)

User avatar
Bob Hansen
Automation Wizard
Posts: 2475
Joined: Tue Sep 24, 2002 3:47 am
Location: Salem, New Hampshire, US
Contact:

Post by Bob Hansen » Fri Mar 06, 2009 12:15 am

SysInternals has a utility, "handle.exe"
I have never used it, but I dumped out the Help info, and did a single test with three copies of calculator open. Here is the info.
C:\Program Files\SysInternals>handle /?

Handle v3.2
Copyright (C) 1997-2006 Mark Russinovich
Sysinternals - http://www.sysinternals.com

usage: handle [[-a] [-u] | [-c [-y]] | [-s]] [-p |] [name
]
-a Dump all handle information.
-c Closes the specified handle (interpreted as a hexadecimal number).
You must specify the process by its PID.
WARNING: Closing handles can cause application or system instability.
-y Don't prompt for close handle confirmation.
-s Print count of each type of handle open.
-u Show the owning user name when searching for handles.
-p Dump handles belonging to process (partial name accepted).
name Search for handles to objects with (fragment accepted).

No arguments will dump all file references.

C:\Program Files\SysInternals>handle -a calc

Handle v3.2
Copyright (C) 1997-2006 Mark Russinovich
Sysinternals - http://www.sysinternals.com

csrss.exe pid: 1628 794: calc.exe(4076): 2920
csrss.exe pid: 1628 858: calc.exe(792)
csrss.exe pid: 1628 90C: calc.exe(792): 816
csrss.exe pid: 1628 950: calc.exe(1792): 824
csrss.exe pid: 1628 9A4: calc.exe(4076)
csrss.exe pid: 1628 C40: calc.exe(1792)
svchost.exe pid: 2036 17D8: calc.exe(792)
svchost.exe pid: 2036 185C: calc.exe(4076)
svchost.exe pid: 2036 1890: calc.exe(1792)
At this point, I have no idea what I am looking at. This is unfamiliar territory for me, but perhaps some of lines in the last command are the Handles? Just trying to help you find some tools.

From the documentation heading:
Handle v3.42
By Mark Russinovich
Published: November 19, 2008

Introduction

Ever wondered which program has a particular file or directory open? Now you can find out. Handle is a utility that displays information about open handles for any process in the system. You can use it to see the programs that have a file open, or to see the object types and names of all the handles of a program.

You can also get a GUI-based version of this program, Process Explorer, here at Sysinternals.
This Help is at here: http://technet.microsoft.com/en-us/sysi ... 96655.aspx

Also saw a reference to this, sounds worth knowing about:
Your computer may stop responding when you monitor open handles
http://support.microsoft.com/kb/276525
Hope this was helpful..................good luck,
Bob
A humble man and PROUD of it!

User avatar
Marcus Tettmar
Site Admin
Posts: 7378
Joined: Thu Sep 19, 2002 3:00 pm
Location: Dorset, UK
Contact:

Post by Marcus Tettmar » Fri Mar 06, 2009 9:05 am

When I ran the code, it found both Notepad windows and correctly told me what the PID values were via MsgBox commands inside the VBScript. I'd like to pass those numbers back for use in the MS code... but can't seem to do that. Can anyone with VBScript knowledge show me how to do that? Marcus? Anyone?
I would have the function set a global VBScript array. Then after calling the function you can query it:

Code: Select all

VBSTART
'global array to store process Names and handles
Dim ProcessArray()

'returns the number of copies of ProcessName that are running
'will return 0 if ProcessName is not running
Function IsProcessRunning(ProcessName)
    Set oWMIService = GetObject("winmgmts:" & "{impersonationLevel=impersonate}!\\.\root\cimv2")
    Set colProcessList = oWMIService.ExecQuery ("Select Name, Handle from Win32_Process where Name='" & ProcessName & "'")
    IsProcessRunning = colProcessList.count
    
    'populate the array - first element is process Name, second is handle
    k = 0
    For Each oProcess in colProcessList
        k = k + 1
        ReDim Preserve ProcessArray(1,k)
        ProcessArray(0,k) = oProcess.Name
        ProcessArray(1,k) = oProcess.Handle  
    Next    
End Function
VBEND
VBEval>IsProcessRunning("chrome.exe"),res
MessageModal>res

//if any found, read through array
If>res>0
  Let>k=0
  Repeat>k
    Let>k=k+1
    VBEval>ProcessArray(0,%k%),ProcName
    VBEval>ProcessArray(1,%k%),ProcHandle
    MessageModal>%ProcName% - %ProcHandle%
  Until>k=res
Endif
Marcus Tettmar
http://mjtnet.com/blog/ | http://twitter.com/marcustettmar

Did you know we are now offering affordable monthly subscriptions for Macro Scheduler Standard?

User avatar
jpuziano
Automation Wizard
Posts: 1085
Joined: Sat Oct 30, 2004 12:00 am

Post by jpuziano » Sat Mar 07, 2009 7:06 am

Hi JRL,

A few mods to your script allowed me to track activity over time, specifically:

- the number of Notepad windows that were Opened
- the number of Notepad windows that were Closed

Code: Select all

VBSTART
  'returns the number of copies of ProcessName that are running
  'will return 0 if ProcessName is not running
  'also shows each unique PID
  Function IsProcessRunning(ProcessName)
  Set oWMIService = GetObject("winmgmts:" & "{impersonationLevel=impersonate}!\\.\root\cimv2")
  Set colProcessList = oWMIService.ExecQuery ("Select Name, Handle from Win32_Process where Name='" & ProcessName & "'")
  IsProcessRunning = colProcessList.count
  End Function
VBEND

//NEW
Let>Opened=0
//NEW
Let>Closed=0

Let>OriginalCount=0
Let>OriginalProcessList=
Let>NewOriginalProcessList=
GoSub>ChkPs
  Let>OriginalCount=res
  Let>LastCount=%res%-%OriginalCount%
  Message>%OriginalCount% Old Notepads running%CRLF%%LastCount% New Notepads running
  //NEW
  Let>OriginalCount_orig=OriginalCount
  //NEW
  Let>LastCount_orig=LastCount

If>res>0
  GoSub>RunTaskList,1
EndIf

Label>Loop
  GoSub>ChkPs
  If>res<>0
    Let>TestSum=%res%-%OriginalCount%
    If>%TestSum%<>%LastCount%
      GoSub>RunTaskList,0
      //NEW
      GoSub>Increment_Opened_Closed_Counters
      //MODIFIED
      Message>%OriginalCount% Old Notepads running%CRLF%%LastCount% New Notepads running%CRLF%%Opened% were opened  %Closed% were closed
    EndIf
  Else
    If>OriginalCount>0
      Let>OriginalCount=0
      //NEW
      GoSub>Increment_Opened_Closed_Counters
      //MODIFIED
      Message>%OriginalCount% Old Notepads running%CRLF%%LastCount% New Notepads running%CRLF%%Opened% were opened  %Closed% were closed
    EndIf
    If>LastCount>0
      Let>LastCount=0
      //NEW
      GoSub>Increment_Opened_Closed_Counters
      //MODIFIED
      Message>%OriginalCount% Old Notepads running%CRLF%%LastCount% New Notepads running%CRLF%%Opened% were opened  %Closed% were closed
    EndIf
  EndIf
Goto>Loop

SRT>ChkPs
  VBEval>IsProcessRunning("notepad.exe"),res
END>ChkPs

SRT>RunTaskList
  Let>RP_WAIT=1
  Let>RP_WINDOWMODE=0
  Run>cmd /c tasklist /fi "imagename eq notepad.exe">%temp_dir%tasklistlist.txt
  ReadFile>%temp_dir%tasklistlist.txt,proclist
  DeleteFile>%temp_dir%tasklistlist.txt
  separate>proclist,CRLF,line
  sub>line_count,1
  Let>kk=3
  Repeat>kk
    add>kk,1
    Let>value=line_%kk%
    Midstr>value,27,6,process
    If>RunTaskList_var_1=1
      ConCat>OriginalProcessList,%process%;
    Else
      Separate>OriginalProcessList,%process%;,Running
      If>running_count>1
        ConCat>NewOriginalProcessList,%process%;
      endIf
    EndIf
  Until>kk,%line_count%
  If>RunTaskList_var_1=1
  Else
    Separate>NewOriginalProcessList,;,item
    Let>OriginalCount=%item_count%-1
    If>OriginalCount<0
      Let>OriginalCount=0
    EndIf
    Let>LastCount=%res%-%OriginalCount%
    Let>OriginalProcessList=%NewOriginalProcessList%
    Let>NewOriginalProcessList=
  EndIf
END>RunTaskList

//NEW SUBROUTINE
SRT>Increment_Opened_Closed_Counters
  If>OriginalCount<>OriginalCount_orig
    If>OriginalCount>OriginalCount_orig
      Add>Opened,1
    Else
      Add>Closed,1
    EndIf
    Let>OriginalCount_orig=OriginalCount
  EndIf
  If>LastCount<>LastCount_orig
    If>LastCount>LastCount_orig
      Add>Opened,1
    Else
      Add>Closed,1
    EndIf
    Let>LastCount_orig=LastCount
  EndIf
END>Increment_Opened_Closed_Counters
Thanks also to Macrus who posted the solution to let me pass the PID values from inside VBScript back into MS... much appreciated. I'll incorporate that later when I get a chance and post it here.

Mar 7, 2009: Reposted with "Disable HTML in this post" on (checked) as code was not being properly displayed.
jpuziano

Note: If anyone else on the planet would find the following useful...
[Open] PlayWav command that plays from embedded script data
...then please add your thoughts/support at the above post - :-)

Post Reply
cron
Sign up to our newsletter for free automation tips, tricks & discounts