Reputation: 840
I have created a VBS script in Windows. I will run this script to get size of a file.
I made this to run for ever. (even this is my requirement).
How should I know if it is running or stopped?
------ Exact Script starts here -----
Set FSO = CreateObject("Scripting.FileSystemObject")
Set FSO_check=CreateObject("Scripting.FileSystemObject")
do while infiniteLoop=0
----- This code is lasting for ever ----
Loop
Am i clear in my ques?
Upvotes: 9
Views: 34378
Reputation: 242
@nimizen answer is not correct. If you have another wscript running, it will return that your script is already running.
@h pic answer is correct, but I get an error with the "a" array in my windows. So I changed it a little and cleaned to work.
Set objWMIService = GetObject("winmgmts:{impersonationLevel=impersonate}!\\.\root\cimv2")
Set colProcesses = objWMIService.ExecQuery("select * from win32_process where name = 'wscript.exe'")
i = 0
For Each objProcess in colProcesses
if not (IsNull(objProcess.CommandLine )) then
strScriptName = Trim(Right(objProcess.CommandLine,Len(objProcess.CommandLine) - InstrRev(objProcess.CommandLine,"\")))
strScriptName = Left(strScriptName, Len(strScriptName) - 1)
if strScriptName = Wscript.ScriptName then
i=i+1
end if
if i > 1 then 'if > 1 wscript instance
'Wscript.Echo "Duplicate :"&strScriptName&" ."
Wscript.Quit
end if
end if
Next
'Wscript.Echo "Pause 2 have 2 scripts running ."
Upvotes: 1
Reputation: 51
I made a script and at the beginning i wanted to avoid having multiple / duplicate instances of the same process running. This is my code to quit the newer instance in case it gets launched when already running.
Note: This does note prevent multiple wscripts files from running - just prevents the same particular file from having simultaneous instances.
To adapt to suit the original question... just use the block which checks current running processes, if the any of the wscript file names equal the script file you're looking for, then it's running.
function duplicate_check
'if two scripts get here at the same time - stagger when the generate _
'the list of running processes _
'ie - give 1 of them time to close
'else they can both quit leaving no more scripts running
call random_script_sleep(2500,500)
dim myfilename
myfilename = Wscript.ScriptName
strComputer = "."
Set objWMIService = GetObject("winmgmts:{impersonationLevel=impersonate}!\\" & strComputer & "\root\cimv2")
Set colProcesses = objWMIService.ExecQuery("select * from win32_process")
'fill arrary w/ all running script names
i = 0
For Each objProcess in colProcesses
If objProcess.Name = "wscript.exe" Then
strScriptName = Trim(Right(objProcess.CommandLine,Len(objProcess.CommandLine) - InstrRev(objProcess.CommandLine,"\")))
strScriptName = Left(strScriptName, Len(strScriptName) - 1)
a(i)= strScriptName '
i=i+1
end if
Next
'kill script if already running w/ same name
if i > 1 then 'if > 1 wscript instance
for s = 0 to i
if a(s) = myfilename then
wscript.quit
end if
next
end if
'sometimes duplicate check fails, if so, write to error log
If Err.Number = 1 Then
error_notes = " @duplicate check, firstdupcheck(0/1):" & firstdupcheck
call error_log
error_notes = "error undefined"
end if
' if debugmsg = 1 then CreateObject("WScript.Shell").Popup _
' "found this many scripts: " & i & vbCrlf & _
' "<>" & i & vbCrlf & _
' ", 1, "debug popup"
end function
Upvotes: 1
Reputation: 219
Hmm, well first if its an infinite loop script, then you're probably using it to periodically check a folder to do some work. This sounds bad but is usually less resource intense than hooking into WMI for notifications. If its up and running, its running. The real problem is discriminating it from all the other WScript and CScripts scripts you may have running.
MS Sysinternals Process Explorer http://technet.microsoft.com/en-us/sysinternals/bb896653 is good at telling you information about your running processes. Mostly I would use it to tell by unique command line arguments which script process is hosting which script.
There is no easy way to exactly find your script's process Id from within a script. It is one of the few pieces of runtime information not exposed in the script environment's object model. Since you are already using the File System Object perhaps you could have it look for a dummy file name to use as the indicator that it is running. If the script couldn't create or open the file then you could assume that another instance of the script is already running.
Or have another unique named dummy file that you can easily create and your script automatically deletes during its processing run. That way you simply create an empty file of that name as a test and if it doesn't disappear in a few seconds you know no instances of your script are running.
Also I was thinking that you could launch your script from another script using Exec() which returns the ProcessID of the launched script and then release your reference to it, storing the ProcessID wherever you need it for later use.
Set oExec = WshShell.Exec( "infinite.vbs" )
MyProcessID = oExec.ProcessID ' procID of shell'd program.
set oExec = Nothing
and do something with MyProcessID
Then I noticed this posting
Find my own process ID in VBScript
Which uses Exec() to run an HTA script, get its ProcessID and look that up in WMI, then use the result set from WMI to locate the Parent process' ProcessID which should be the script making the Exec() and WMI calls. The problem with it is the HTA may terminate before WMI gets a chance to find it.
Dim iMyPID : iMyPID = GetObject("winmgmts:root\cimv2").Get("Win32_Process.Handle='" & CreateObject("WScript.Shell").Exec("mshta.exe").ProcessID & "'").ParentProcessId
Mostly I get the feeling that this is all overkill for whatever reason you think you need to know if the script is running. Instead focus on what action "knowing if the process is running or not" causes you to take. Since that hasn't been explained we really can't offer you an alternative strategy to get you there, but I'm sure a more simple solution is available. TheFolderSpy http://venussoftcorporation.blogspot.com/2010/05/thefolderspy.html for example would be one alternative way to run your program without an infinite loop.
Don't forget to use a sleep command in your loop to let other programs get work done. It makes a great difference in resource use. Also you only need one FSO instance, make it global to all your code by creating it early on in your script before any subroutines.
Since you are looking at the size of a file, you are probably checking it for changes. I've found that a loop with a small WScript.Sleep 200 delay in it is good to detect if a file is done being altered. That way you can process the file instead of having to skip it until the next main loop pass which should be set to 10 seconds or more.
Upvotes: 0
Reputation: 3419
How about using the commandline property? I think this need Windows XP and up.
For example:
Set objSWbemServices = GetObject ("WinMgmts:Root\Cimv2")
Set colProcess = objSWbemServices.ExecQuery _
("Select * From Win32_Process where name = 'wscript.exe'")
For Each objProcess In colProcess
WScript.Echo objProcess.Name, _
objProcess.ProcessId, _
objProcess.CommandLine
Next
Upvotes: 4