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

如何检查windows中的vbs脚本是否正在运行?,windows,vbscript,Windows,Vbscript,我已经在Windows中创建了VBS脚本。我将运行此脚本以获得文件的大小 我做这个是为了永远跑下去。(即使这是我的要求) 我如何知道它正在运行还是已停止 ------ Exact Script starts here ----- Set FSO = CreateObject("Scripting.FileSystemObject") Set FSO_check=CreateObject("Scripting.FileSystemObject") do while infiniteLoop=

我已经在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

我的问题清楚了吗?

使用命令行属性怎么样?我认为这需要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

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

MS Sysinternals Process Explorer擅长告诉您有关正在运行的进程的信息。大多数情况下,我会使用它来通过唯一的命令行参数来判断哪个脚本进程承载哪个脚本

要从脚本中准确地找到脚本的进程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
然后我注意到了这个帖子

它使用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 
大多数情况下,我觉得这太过分了,无论出于什么原因,你认为你需要知道脚本是否正在运行。相反,关注“知道流程是否正在运行”导致您采取的行动。由于这还没有解释,我们真的无法为您提供一个替代策略,但我相信有一个更简单的解决方案可用。例如,FolderSpy是一种不用无限循环运行程序的替代方法

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


因为您正在查看文件的大小,所以可能正在检查文件的更改。我发现一个循环中有一个小的WScript.Sleep 200延迟,可以很好地检测文件是否被修改。这样,您就可以处理该文件,而不必将其跳过,直到下一个主循环通过(应设置为10秒或更长)。

我编写了一个脚本,开始时我希望避免运行同一进程的多个/重复实例。这是我的代码,用于退出新实例,以防它在已运行时启动。
注意:这确实会防止多个WScript文件运行-只是防止同一特定文件同时具有实例

为了适应原来的问题。。。只需使用检查当前正在运行的进程的块,如果任何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  
功能重复检查
'如果两个脚本同时到达此处-在生成_
'正在运行的进程的列表_
"即,给其中一个时间关门
'否则他们都可以退出,不再运行脚本
调用随机脚本睡眠(2500500)
dim myfilename
myfilename=Wscript.ScriptName
strComputer=“”
设置objWMIService=GetObject(“winmgmts:{impersonationLevel=impersonate}!\\”&strComputer&“\root\cimv2”)
设置colprocesss=objWMIService.ExecQuery(“从win32_进程中选择*)
'填充包含所有运行脚本名称的数组
i=0
对于COLJP进程中的每个OBJP进程
如果objProcess.Name=“wscript.exe”,则
strScriptName=Trim(右(objProcess.CommandLine,Len(objProcess.CommandLine)-instrev(objProcess.CommandLine,“\”))
strScriptName=Left(strScriptName,Len(strScriptName)-1)
a(i)=strScriptName'
i=i+1
如果结束
下一个
'如果已使用相同名称运行,则终止脚本
如果i>1,则'if>1 wscript实例
对于s=0到i
如果a(s)=myfilename,则
wscript.quit
如果结束
下一个
如果结束
'有时重复检查失败,如果失败,请写入错误日志
如果错误编号=1,则
错误_notes=“@duplicate check,firstdupcheck(0/1):”&firstdupcheck
调用错误日志
错误\u notes=“错误未定义”
如果结束
'如果debugmsg=1,则CreateObject(“WScript.Shell”).Popup_
'找到这么多脚本:“&i&vbCrlf&_
““”&i&vbCrlf&_
“,1,“调试弹出窗口”
端函数

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

@图中的答案是正确的,但我的窗口中的“a”数组出现了一个错误。所以我对它做了一点修改,并进行了清理

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

如果这回答了您的问题,您可能会在任务管理器中看到流程运行。谢谢Rob。但是流程的名称是什么..sa