Most recently activated process [tree]?
Moderators: JRL, Dorian (MJT support)
Most recently activated process [tree]?
How do you get this variable? I'm trying to script a macro that will terminate the most recently activated process and all processes activated by that process (sub-processes, main one being the one shown in Task manager).
Oh come on, somebody's got to know this! With all those columns avaliable in the XP Task manager you'd expect *one* of them to record how long has the process been running! Hmmph. Guess not. Anyway, can anyone help me make this pseudo code operational? i cant seem to code it in a way so it will work.
//macro runs right after windows startup
//masterscript
msched recorder.scp
msched terminator.scp //
//recorder.scp
label>start
wait for new process to open;
write process name and current date and time to c:\processes.ini;
goto>start
//terminator.scp
label>st
waitkeydown>k //will change later
go to processes.ini and kill latest entry and all subprocesses and then delete it (or maby move it to a killedprocesses.ini);
goto>st
Ok, now i need the data and time in processes.ini so i can view it myself, and terminator.scp must be able to kill any process except those who arent on the list, and if they arent on the list then they must have been activated before the macro, so i know they are safe. The thing im having problems with is getting MS to wait for a new process to open. I just dont know how to do it. This macro has several obvious uses, such as closing a game if it froze and you cant see the task manager because the game is allways on top, and you can only see the mouse; or if you accidently or unknowingly activated a virus/trojan/spyware installer/etc. then you can close it much faster by pressing a button rather having to press ctrl alt del and searching for the process in the list; it also has some less obvious uses. All in all i think this thing can be so useful that many probably have done it allready.
//macro runs right after windows startup
//masterscript
msched recorder.scp
msched terminator.scp //

//recorder.scp
label>start
wait for new process to open;
write process name and current date and time to c:\processes.ini;
goto>start
//terminator.scp
label>st
waitkeydown>k //will change later
go to processes.ini and kill latest entry and all subprocesses and then delete it (or maby move it to a killedprocesses.ini);
goto>st
Ok, now i need the data and time in processes.ini so i can view it myself, and terminator.scp must be able to kill any process except those who arent on the list, and if they arent on the list then they must have been activated before the macro, so i know they are safe. The thing im having problems with is getting MS to wait for a new process to open. I just dont know how to do it. This macro has several obvious uses, such as closing a game if it froze and you cant see the task manager because the game is allways on top, and you can only see the mouse; or if you accidently or unknowingly activated a virus/trojan/spyware installer/etc. then you can close it much faster by pressing a button rather having to press ctrl alt del and searching for the process in the list; it also has some less obvious uses. All in all i think this thing can be so useful that many probably have done it allready.
-
- Automation Wizard
- Posts: 1101
- Joined: Fri Jan 07, 2005 5:55 pm
- Location: Somewhere else on the planet
Since none of our gurus who really know what they are doing has replied to your post I'll dare to suggest that you may be able to get there by using some of the pstools utilities http://www.sysinternals.com/Utilities/PsTools.html They run from the command line and are very easy to automate with macro scheduler.
Maybe something like capture the process list to a file and find the latest pid?
Maybe something like capture the process list to a file and find the latest pid?
- Marcus Tettmar
- Site Admin
- Posts: 7395
- Joined: Thu Sep 19, 2002 3:00 pm
- Location: Dorset, UK
- Contact:
Hi,
If you searched the Scripts & Tips forum you would have found this post:
http://www.mjtnet.com/forum/viewtopic.php?t=1779
From this it is obvious that you can get properties of running processes. As well as the name of the process, which the above post uses, you can extract KernalModeTime and UserModeTime which are times in milliseconds that the process has been running in each mode. So it should now be a doddle to modify the script in the above post to get the time. Once you have the time of each process all you need to do is sort the results and take the one with the smallest number and that must be the one that has been running the least and is therefore the newest process.
So, this little script should extract the newest process. You can use the kill process function in the above post to kill it, but you may want to add a third dimension to the array to store the PID in, rather than use the process name. Hopefully you can figure that little bit out for yourself.
VBSTART
Dim ProcArray()
Sub SortIt
Dim i,j,tmp1,tmp2
For i = 0 To UBound(ProcArray)
For j = (i+1) To UBound(ProcArray)
If ProcArray(i)(1) > ProcArray(j)(1) Then
tmp1 = ProcArray(i)(0)
tmp2 = ProcArray(i)(1)
ProcArray(i)(0) = ProcArray(j)(0)
ProcArray(i)(1) = ProcArray(j)(1)
ProcArray(j)(0) = tmp1
ProcArray(j)(1) = tmp2
End If
Next
Next
End Sub
Sub GetProcessTimes
set wmi = getobject("winmgmts:")
sQuery = "select * from win32_process"
set processes = wmi.execquery(sQuery)
k = 0
for each process in processes
'if process.UserModeTime > 0 then
ReDim Preserve ProcArray(k)
ProcArray(k) = Array(process.name, process.KernelModeTime)
'ProcArray(k) = Array(process.name, process.UserModeTime)
k = k + 1
'end if
next
Sortit
End Sub
VBEND
VBRun>GetProcessTimes
VBEval>ProcArray(0)(0),p
VBEval>ProcArray(0)(1),p2
MessageModal>%p% is the newest process as it has only been running for %p2% milliseconds
The answers are all here, you just need to search for them.
If you searched the Scripts & Tips forum you would have found this post:
http://www.mjtnet.com/forum/viewtopic.php?t=1779
From this it is obvious that you can get properties of running processes. As well as the name of the process, which the above post uses, you can extract KernalModeTime and UserModeTime which are times in milliseconds that the process has been running in each mode. So it should now be a doddle to modify the script in the above post to get the time. Once you have the time of each process all you need to do is sort the results and take the one with the smallest number and that must be the one that has been running the least and is therefore the newest process.
So, this little script should extract the newest process. You can use the kill process function in the above post to kill it, but you may want to add a third dimension to the array to store the PID in, rather than use the process name. Hopefully you can figure that little bit out for yourself.
VBSTART
Dim ProcArray()
Sub SortIt
Dim i,j,tmp1,tmp2
For i = 0 To UBound(ProcArray)
For j = (i+1) To UBound(ProcArray)
If ProcArray(i)(1) > ProcArray(j)(1) Then
tmp1 = ProcArray(i)(0)
tmp2 = ProcArray(i)(1)
ProcArray(i)(0) = ProcArray(j)(0)
ProcArray(i)(1) = ProcArray(j)(1)
ProcArray(j)(0) = tmp1
ProcArray(j)(1) = tmp2
End If
Next
Next
End Sub
Sub GetProcessTimes
set wmi = getobject("winmgmts:")
sQuery = "select * from win32_process"
set processes = wmi.execquery(sQuery)
k = 0
for each process in processes
'if process.UserModeTime > 0 then
ReDim Preserve ProcArray(k)
ProcArray(k) = Array(process.name, process.KernelModeTime)
'ProcArray(k) = Array(process.name, process.UserModeTime)
k = k + 1
'end if
next
Sortit
End Sub
VBEND
VBRun>GetProcessTimes
VBEval>ProcArray(0)(0),p
VBEval>ProcArray(0)(1),p2
MessageModal>%p% is the newest process as it has only been running for %p2% milliseconds
The answers are all here, you just need to search for them.
mtettmar,
KernelModeTime and UserModeTime count processor time, not real time. You may have misunderstood me. I have read http://www.mjtnet.com/forum/viewtopic.php?t=1779 as well as a lot about WMI on MSDN prior to posting. And did you test your code? Because it seems you did not. It doesn't work. Anyway, it seems your template works more efficiently than mine (I did not post it here), which is based on editing ini files (I imagined it this way so I can read those ini files), but writing data to an ini file *is* an option with it I chose to rework my code based on it. And it works. Well, kind of... There are atleast 5 bugs with it. It very rarely writes the correct time a process has been running. It often gets a different process in two subsequent runs. Sometimes it even changes the process in the same run! If I start a new "My Computer" window, it gets explorer.exe (which is understandable, as I will program something to fix this only later, after I fix the current bugs). I put 2 msgbox commands with the longest and shortest times. Sometimes they show identical values, almost allways the values are WAY out of proportion (example - i've turned on the PC 2 hours ago, and they say the oldest process is running for 24 thousand seconds!), often they will mix the runtime of one process with another, Ocassionaly taking a process that has been closed and re-run runtime and not renewing it, and also they seem to sometimes give me the same response wether if they are sorted as bigger values up or smaller values up. I need serious help with this code... So without boring you further, here it is:
VBSTART
Dim arrProcArray()
Dim arrProcElapsedTimes()
Sub killProcess(kpid)
set processes = getobject("winmgmts:").execquery("select * from win32_process where name ='" & kpid & "'")
for each process in processes
process.terminate
next
End Sub
Function WMIDateStringToDate(dtmStart)
' WMIDateStringToDate = CDate(Mid(dtmStart, 5, 2) & "/" & Mid(dtmStart, 7, 2) & "/" & Left(dtmStart, 4) & " " & Mid (dtmStart, 9, 2) & ":" & Mid(dtmStart, 11, 2) & ":" & Mid(dtmStart, 13, 2))
End Function
Sub SortProcessTimes
Dim i,j,tmp1,tmp2,tmp3,tmp4
For i = 0 To UBound(arrProcElapsedTimes)
For j = (i+1) To UBound(arrProcElapsedTimes)
'If DateTime.Compare(arrProcArray(i)(1), arrProcArray(j)(1))
if (objProcess.Name = "_Total") = false and (objProcess.Name
= "wmiprvse.exe") = false and (objProcess.Name = "System") = false
and (objProcess.Name = "System Idle Process") = false and (objProcess.Name = "smss.exe") = false and (objProcess.Name
= "csrss.exe") = false and (objProcess.Name = "winlogon.exe") = false
and (objProcess.Name = "services.exe") = false and (objProcess.Name
= "lsass.exe") = false and (objProcess.Name = "svchost.exe") = false
and (objProcess.Name = "spoolsv.exe") = false and (objProcess.Name
= "msched.exe") = false and (objProcess.Name = "SMax4PNP.exe") =
false then
ReDim Preserve arrProcArray(k)
ReDim Preserve arrProcElapsedTimes(k)
arrProcArray(k) = Array(objProcess.name, objProcess.description, objProcess.ProcessID)
sQuery2 = "select * from Win32_PerfFormattedData_PerfProc_Process where IDProcess =" & objProcess.ProcessID
set colPerfProcesses = wmi.execquery(sQuery2)
for each process in colPerfProcesses
arrProcElapsedTimes(k) = Process.ElapsedTime
Next
k = k + 1
end if
next
SortProcessTimes
End Sub
VBEND
VBRun>GetProcessTimes
VBEval>arrProcArray(0)(0),p
'VBEval>WMIDateStringToDate(arrProcArray(0)(1)),p2
VBEval>arrProcArray(0)(1),p2
VBEval>arrProcArray(0)(2),pid
VBEval>arrProcElapsedTimes(UBound(arrProcElapsedTimes)),Elapsed
Messagemodal>%p% (PID %pid% Description %p2%) is the newest process as it has only been running for %Elapsed% seconds. Attempting to terminate...
'VBRun>killProcess,%p%
VBRun>GetProcessTimes
VBEval>arrProcArray(0)(0),m
if>{%p%=%m%}
messagemodal>An error occured. Try again
goto>exit
endif
messagemodal>Termination successful
label>exit
I didn't put some code in code tag cause would have messed the page up way to much. ParentID works rarely, and CreationDate worked some versions ago, but not every time so I abandoned it (but left its code in the script just in case...) The kill function is commented out so its safe to run the code. As i've allready said the script is unstable and extremley unreliable. And i want to fix this. Oh and by the way - it may run a little slow on old machines with many processes running...
So can I hear any suggestions as to how this code can be patched for all its bugs? Especially the occasionally changing last run process in two subsequent runs (even though msched.exe and other relevant processes are not eligible for termination).
By the way, if a post gets edited, does it get a "New messages" icon? Or do i have to double post so people would read?
KernelModeTime and UserModeTime count processor time, not real time. You may have misunderstood me. I have read http://www.mjtnet.com/forum/viewtopic.php?t=1779 as well as a lot about WMI on MSDN prior to posting. And did you test your code? Because it seems you did not. It doesn't work. Anyway, it seems your template works more efficiently than mine (I did not post it here), which is based on editing ini files (I imagined it this way so I can read those ini files), but writing data to an ini file *is* an option with it I chose to rework my code based on it. And it works. Well, kind of... There are atleast 5 bugs with it. It very rarely writes the correct time a process has been running. It often gets a different process in two subsequent runs. Sometimes it even changes the process in the same run! If I start a new "My Computer" window, it gets explorer.exe (which is understandable, as I will program something to fix this only later, after I fix the current bugs). I put 2 msgbox commands with the longest and shortest times. Sometimes they show identical values, almost allways the values are WAY out of proportion (example - i've turned on the PC 2 hours ago, and they say the oldest process is running for 24 thousand seconds!), often they will mix the runtime of one process with another, Ocassionaly taking a process that has been closed and re-run runtime and not renewing it, and also they seem to sometimes give me the same response wether if they are sorted as bigger values up or smaller values up. I need serious help with this code... So without boring you further, here it is:
VBSTART
Dim arrProcArray()
Dim arrProcElapsedTimes()
Sub killProcess(kpid)
set processes = getobject("winmgmts:").execquery("select * from win32_process where name ='" & kpid & "'")
for each process in processes
process.terminate
next
End Sub
Function WMIDateStringToDate(dtmStart)
' WMIDateStringToDate = CDate(Mid(dtmStart, 5, 2) & "/" & Mid(dtmStart, 7, 2) & "/" & Left(dtmStart, 4) & " " & Mid (dtmStart, 9, 2) & ":" & Mid(dtmStart, 11, 2) & ":" & Mid(dtmStart, 13, 2))
End Function
Sub SortProcessTimes
Dim i,j,tmp1,tmp2,tmp3,tmp4
For i = 0 To UBound(arrProcElapsedTimes)
For j = (i+1) To UBound(arrProcElapsedTimes)
'If DateTime.Compare(arrProcArray(i)(1), arrProcArray(j)(1))
if (objProcess.Name = "_Total") = false and (objProcess.Name
= "wmiprvse.exe") = false and (objProcess.Name = "System") = false
and (objProcess.Name = "System Idle Process") = false and (objProcess.Name = "smss.exe") = false and (objProcess.Name
= "csrss.exe") = false and (objProcess.Name = "winlogon.exe") = false
and (objProcess.Name = "services.exe") = false and (objProcess.Name
= "lsass.exe") = false and (objProcess.Name = "svchost.exe") = false
and (objProcess.Name = "spoolsv.exe") = false and (objProcess.Name
= "msched.exe") = false and (objProcess.Name = "SMax4PNP.exe") =
false then
ReDim Preserve arrProcArray(k)
ReDim Preserve arrProcElapsedTimes(k)
arrProcArray(k) = Array(objProcess.name, objProcess.description, objProcess.ProcessID)
sQuery2 = "select * from Win32_PerfFormattedData_PerfProc_Process where IDProcess =" & objProcess.ProcessID
set colPerfProcesses = wmi.execquery(sQuery2)
for each process in colPerfProcesses
arrProcElapsedTimes(k) = Process.ElapsedTime
Next
k = k + 1
end if
next
SortProcessTimes
End Sub
VBEND
VBRun>GetProcessTimes
VBEval>arrProcArray(0)(0),p
'VBEval>WMIDateStringToDate(arrProcArray(0)(1)),p2
VBEval>arrProcArray(0)(1),p2
VBEval>arrProcArray(0)(2),pid
VBEval>arrProcElapsedTimes(UBound(arrProcElapsedTimes)),Elapsed
Messagemodal>%p% (PID %pid% Description %p2%) is the newest process as it has only been running for %Elapsed% seconds. Attempting to terminate...
'VBRun>killProcess,%p%
VBRun>GetProcessTimes
VBEval>arrProcArray(0)(0),m
if>{%p%=%m%}
messagemodal>An error occured. Try again
goto>exit
endif
messagemodal>Termination successful
label>exit
I didn't put some code in code tag cause would have messed the page up way to much. ParentID works rarely, and CreationDate worked some versions ago, but not every time so I abandoned it (but left its code in the script just in case...) The kill function is commented out so its safe to run the code. As i've allready said the script is unstable and extremley unreliable. And i want to fix this. Oh and by the way - it may run a little slow on old machines with many processes running...
So can I hear any suggestions as to how this code can be patched for all its bugs? Especially the occasionally changing last run process in two subsequent runs (even though msched.exe and other relevant processes are not eligible for termination).
By the way, if a post gets edited, does it get a "New messages" icon? Or do i have to double post so people would read?