VBScript监测进程进行情况。

    技术2022-05-11  60

    有C:/Document1和C:/Document2这样两个文件夹,里面分别有一个相同的Exe文件E1和E2,它的作用是一定被执行就处理该文件夹下的文件。 需求:不可以修改Exe文件,通过一个程序P1来完成: 定时运行(Exe文件中没有定时功能)。P1运行,保证E1和E2都要运行,即如果运行了就要保持,如果没有运行的话就要启动Exe。写入日志。需要写入如下内容: ------------------------------------------------ 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( 1 1 ) ' 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, intI3intI1  =   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( 0 0 ) =  intExeID                   arrayProcessIDandExecutablePath( 0 1 ) =  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,  0 Then                     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,  5 2 &   " / "   &  _                   Mid (dtmDate,  7 2 &   " / "   &  _                   Left (dtmDate,  4 &   "   "   &  _                   Mid (dtmDate,  9 2 &   " : "   &  _                   Mid (dtmDate,  11 2 &   " : "   &  _                   Mid (dtmDate,  13 2 )) 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

    最新回复(0)