新鲜鱼排的幸福生活

No pains,no gains.

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::
        有C:\Document1和C:\Document2这样两个文件夹,里面分别有一个相同的Exe文件E1和E2,它的作用是一定被执行就处理该文件夹下的文件。
需求:不可以修改Exe文件,通过一个程序P1来完成:
  1. 定时运行(Exe文件中没有定时功能)。
  2. P1运行,保证E1和E2都要运行,即如果运行了就要保持,如果没有运行的话就要启动Exe。
  3. 写入日志。需要写入如下内容:
------------------------------------------------
Process ID: 3036
Process Path:
Time Created: 2/14/2007 11:04:53 AM
Time Deleted: 2/14/2007 11:05:23 AM
Duration: 30 seconds
------------------------------------------------
      启动了几个就要写入几个。
Note: 进程名称相同,路径不同,不能修改Exe文件。
 
方案:通过一个将一个VBS程序添加到Task Schedule中来定时地执行。通过VBS可以实现对Process的查询,以及对Process的create和delete的情况进行记录。
实现代码如下:
 
On error resume next
'The path of the executable.
'
The first path is as usual.
'
The second path is on the C disk.(You can copy the notepad.exe from system32 and run it.)
Dim strPath1
Dim strPath2
'The name of the process.
Dim strNameOfProcess
'The interval string between different log data.
Dim strInterval
'An Integer 
'
0 The process don't exists in the Windows Task Manager
'
1 Exist one of two.
'
2 Both exist.
Dim intWhetherExist
'The path of the process need to be fun.
Dim strExePath
'The ID of the process need to be fun.
Dim intExeID
'Save the match relationship between ProcessID and ExecutablePath in this array.
Dim arrayProcessIDandExecutablePath(11)
'The path of the log file.
Dim strLogPath 
'--------------------------------------------------------------------------------
'
Take notepad.exe for example. Open just one notepad.
strPath1 = "C:WINNTSystem32 otepad.exe"
strPath2 
= "C: otepad.exe"
strNameOfProcess 
= "notepad.exe"
strInterval 
= "------------------------------------------------"
strLogPath 
= "c: estfile.txt" 
'--------------------------------------------------------------------------------
'
Default is zero.
intWhetherExist = 0
'Create an array contains the name of all processes need to be found.
strComputer = "."
arrTargetProcs 
= Array(strNameOfProcess)

'---------------------------------------------------------------
'
1. Find the process we want.
'
---------------------------------------------------------------
'
Find the process in the name list.
Set objWMIService = GetObject("winmgmts:" _
 
& "{impersonationLevel=impersonate}!\" & strComputer & " ootcimv2")
Set colProcesses = objWMIService.ExecQuery("SELECT * FROM Win32_Process")

For Each objProcess in colProcesses
  
For Each strTargetProc In arrTargetProcs
    
If LCase(objProcess.Name) = LCase(strTargetProc) Then
      
'Exist.
      intWhetherExist = intWhetherExist + 1      
      
'msgbox objProcess.ExecutablePath 
      strExePath = objProcess.ExecutablePath  
      intExeID 
= objProcess.ProcessId     
      
If Err <> 0 Then
         WScript.Echo 
"Error on associators query= " _
            
& Err.number _ 
            
& " " & Err.Description
         WScript.Quit
      
End If  
    
End If    
  
Next
Next    

Dim WshShell
Set WshShell = Wscript.CreateObject("Wscript.Shell")
'Confirm whether exists.
Select Case intWhetherExist
           
Case 0    
               
'If not exist, run them.               
               '-----------------------------------------
               'I use constant addresses.
               '-----------------------------------------
               WshShell.Run(strPath1)
               WshShell.Run(strPath2)
               
'msgbox strExePath2
           Case 1 
               
'-----------------------------------------
               'Make sure which executable had been run.
               '-----------------------------------------
               select case LCase(strExePath)
                   
case LCase(strPath1)
                       WshShell.Run strPath2
                   
case LCase(strPath2)
                       WshShell.Run strPath1
               
end select 
           
Case Else     
           
'Do nothing           
End Select

'---------------------------------------------------------------
'
2. Save the match relationship in the array.
'
---------------------------------------------------------------
'
Find the process in the name list.
Set objWMIService = GetObject("winmgmts:" _
 
& "{impersonationLevel=impersonate}!\" & strComputer & " ootcimv2")
Set colProcesses = objWMIService.ExecQuery("SELECT * FROM Win32_Process")
Dim intI1, intI2, intI3
intI1 
= 0
intI2 
= 0
intI3 
= 0
For Each objProcess in colProcesses
  
For Each strTargetProc In arrTargetProcs
    
'
    Select Case intWhetherExist
           
Case 0    
                
If LCase(objProcess.Name) = LCase(strTargetProc) Then
                    
'Exist.
                    arrayProcessIDandExecutablePath(intI1, 0)= objProcess.ProcessId     
                    arrayProcessIDandExecutablePath(intI1, 
1)= objProcess.ExecutablePath     
                    intI1 
= intI1 + 1
                
End If    
           
Case 1 
                arrayProcessIDandExecutablePath(
00)= intExeID   
                arrayProcessIDandExecutablePath(
01)= strExePath   
                intI1 
= intI1 + 1  
           
Case Else     
           
'Do nothing           
    End Select
  
Next
Next 
intI1 
= 0

'-------------------------------------------------------
'
3. Track the process and write log
'
-------------------------------------------------------
Set objWMIService = GetObject("winmgmts:\" & strComputer & " ootcimv2")
Set colMonitorProcess = objWMIService.ExecNotificationQuery _
 (
"SELECT * FROM __InstanceDeletionEvent " _ 
 
& " Within 1 WHERE TargetInstance ISA 'Win32_Process'")
Do while intI3 < 2
   
Set objLatestEvent = colMonitorProcess.NextEvent
   
For Each strTargetProc In arrTargetProcs
      
'Check the process name.
      If LCase(objLatestEvent.TargetInstance.Name) = LCase(strTargetProc) Then
            
'Get the executablePath through the processID and the match relationship
            'between processID and executablePath.
            Do While intI2 < 2
                
If objLatestEvent.TargetInstance.ProcessId = arrayProcessIDandExecutablePath(intI2, 0Then
                    strProcDeleted 
= Now
                    strProcCreated 
= _
                    WMIDateToString(objLatestEvent.TargetInstance.CreationDate)
                    WriteToFile(
"Process Name: " & objLatestEvent.TargetInstance.Name)
                    WriteToFile(
"Process ID: " & objLatestEvent.TargetInstance.ProcessId)
                    WriteToFile(
"Process Path: " & arrayProcessIDandExecutablePath(intI2, 1))
                    WriteToFile(
"Time Created: " & strProcCreated)
                    WriteToFile(
"Time Deleted: " & strProcDeleted)
                    intSecs 
= DateDiff("s", strProcCreated, strProcDeleted)
                    WriteToFile(
"Duration: " & intSecs & " seconds")
                    WriteToFile(strInterval)                 
 
                
End If
            intI2 
= intI2 + 1
            
Loop 
            intI2 
= 0         
            intI3 
= intI3 + 1 
       
End If    
   
Next  
Loop
intI3 
= 0
'msgbox arrayProcessIDandExecutablePath(0, 0)
'
msgbox arrayProcessIDandExecutablePath(0, 1)
'
msgbox arrayProcessIDandExecutablePath(1, 0)
'
msgbox arrayProcessIDandExecutablePath(1, 1)

'----------------------------------------------------------------
'
Convert WMI DATETIME format to US-style date string.
'
----------------------------------------------------------------
Function WMIDateToString(dtmDate)
WMIDateToString 
= CDate(Mid(dtmDate, 52& "/" & _
                  
Mid(dtmDate, 72& "/" & _
                  
Left(dtmDate, 4& " " & _
                  
Mid(dtmDate, 92& ":" & _
                  
Mid(dtmDate, 112& ":" & _
                  
Mid(dtmDate, 132))
End Function

'----------------------------------------------------------
'
Write log
'
----------------------------------------------------------
Function WriteToFile(strInfo)

  
Const ForReading = 1, ForWriting = 2, ForAppending = 8
  
Dim fso, f, strOriginal
  
Set fso = CreateObject("Scripting.FileSystemObject")
  
  
'-----------------------------------------------------
  '1. Whether the file has existed.
  '-----------------------------------------------------
  If Not(fso.FileExists(strLogPath)) Then
     
Set f = fso.CreateTextFile(strLogPath, True)
  
End If

  
'Use ForWriting style of OpenTextFile, so we need to rewrite the log in this file.
  'We also can use ForAppending style.
  Set f = fso.OpenTextFile(strLogPath, ForAppending, True)
  f.Write VbCrLf 
& strInfo  
End Function

 

现在的问题是:
语句
Set objLatestEvent = colMonitorProcess.NextEvent
   执行的时候会等待来监测到Exe文件的Process被Delete时的时间,所以进程中会多一个Wscript.exe的进程。如果执行很多次的话,那么就会出现很多个相同的进程。一个大约占用7M内存。为了解决这个问题,我定义了

 

while intI3 < 2
 
因为我需要考虑运行两个Exe文件。但是当我运行了VBS程序一次(我叫它VBS1),会出现两个Notepad(如果你没有打开过代码中提到路径的Notepad的话),然后你关掉一个,这个时候VBS1仍然存在,等待另外一个Notepad被关掉以后才结束。(到目前为止了解我所提到的么?)
 OK, go on. 因为我们是Task Schedule来定时执行,如果这个时候又执行了一个VBS程序(我叫它VBS2),我希望是它启动一个Notepad,并且只监测这一个Notepad的情况。但是实际情况是,如果我关闭了VBS1所产生的剩余的那个Notepad的话,日志中会写入相同的两条信息,而VBS2产生的那个Notepad的变化将不会被记录(因为VBS2产生的Wscript已经结束了)。
   我怎么能让他们分工明确??非常感谢。
   自己第一次用VBScript,因为工作的需要。请大家不吝赐教。
   Email: dutguoyi@hotmail.com
posted on 2007-04-04 17:20  新鲜鱼排  阅读(763)  评论(0编辑  收藏  举报