如何检查Windows中的vbs脚本是否正在运行?

时间:2011-10-21 12:58:00

标签: windows vbscript

我在Windows中创建了一个VBS脚本。我将运行此脚本来获取文件的大小。

我让它永远奔跑。 (即使这是我的要求)。

我应该如何知道它是在运行还是停止?

------ 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

我的问题清楚了吗?

4 个答案:

答案 0 :(得分:4)

如何使用命令行属性?我认为这需要Windows XP及以上版本。

例如:

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

答案 1 :(得分:1)

我创建了一个脚本,并且在开始时我想避免运行同一进程的多个/重复实例。这是我退出新实例的代码,以防它在已经运行时启动 注意:这会注意防止多个wscripts文件运行 - 只是防止同一个特定文件同时具有实例。

要适应原始问题...只需使用检查当前正在运行的进程的块,如果任何wscript文件名等于您正在查找的脚本文件,那么它正在运行

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  

答案 2 :(得分:1)

@nimizen答案不正确。如果你有另一个wscript运行,它将返回你的脚本已经运行。

@h pic的回答是正确的,但我收到错误的&#34; a&#34;我的窗户中的数组。所以我稍微改了一下并清理干净了。

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 ."

答案 3 :(得分:0)

嗯,首先,如果它是一个无限循环脚本,那么你可能正在使用它来定期检查一个文件夹来做一些工作。这听起来很糟糕,但通常比连接到WMI通知更少资源。如果它启动并运行,它的运行。真正的问题是将它与您可能运行的所有其他WScript和CScripts脚本区别开来。

MS Sysinternals Process Explorer http://technet.microsoft.com/en-us/sysinternals/bb896653善于告诉您有关正在运行的进程的信息。大多数情况下,我会用它来通过独特的命令行参数来判断哪个脚本进程正在托管哪个脚本。

没有简单的方法可以在脚本中准确找到脚本的进程ID。它是脚本环境的对象模型中未公开的少数运行时信息之一。由于您已经在使用文件系统对象,因此可以让它查找一个虚拟文件名,以用作它正在运行的指示器。如果脚本无法创建或打开文件,那么您可以假设该脚本的另一个实例已在运行。

或者拥有另一个您可以轻松创建的唯一命名虚拟文件,并且您的脚本会在其处理过程中自动删除。这样你就可以简单地创建一个具有该名称的空文件作为测试,如果它在几秒钟内没有消失,你就不会知道你的脚本没有运行。

此外,我认为您可以使用Exec()从另一个脚本启动脚本,该脚本返回已启动脚本的ProcessID,然后释放对它的引用,将ProcessID存储在您需要的任何位置以备日后使用。

Set oExec = WshShell.Exec( "infinite.vbs" )
MyProcessID = oExec.ProcessID ' procID of shell'd program. 
set oExec = Nothing

and do something with MyProcessID

然后我注意到这个帖子

Find my own process ID in VBScript

使用Exec()运行HTA脚本,获取其ProcessID并在WMI中查找,然后使用WMI的结果集找到父进程的ProcessID,它应该是生成Exec()和WMI的脚本调用。它的问题是HTA可能在WMI有机会找到它之前终止。

Dim iMyPID : iMyPID = GetObject("winmgmts:root\cimv2").Get("Win32_Process.Handle='" & CreateObject("WScript.Shell").Exec("mshta.exe").ProcessID & "'").ParentProcessId 

大多数情况下,我觉得如果脚本运行,您认为需要知道的任何原因都是过度的。而是关注什么行动“知道过程是否正在运行”导致您采取。由于没有解释,我们真的无法为您提供另一种策略来帮助您,但我确信可以使用更简单的解决方案。例如,FileSpy http://venussoftcorporation.blogspot.com/2010/05/thefolderspy.html将是一种在没有无限循环的情况下运行程序的替代方法。

不要忘记在循环中使用sleep命令让其他程序完成工作。它在资源使用方面有很大的不同。此外,您只需要一个FSO实例,通过在任何子例程之前在脚本中尽早创建它来使其对所有代码都是全局的。

由于您正在查看文件的大小,因此您可能正在检查它是否有更改。我发现一个带有小WScript.Sleep 200延迟的循环可以很好地检测文件是否被修改。这样你就可以处理文件而不必跳过它,直到下一个主循环传递应该设置为10秒或更长时间。