Reputation: 18847
I wanted to write a program that checks every 15 minutes if amount of programs is launched like (toto1.bat, toto2.bat,toto3.bat, iexplore.exe …) whether it finds nothing so it launch it.
This my draft script trying to reach my aim, but I have an "Invalid Request" error in line 31.
Option Explicit
Dim ProcessPath1,ProcessPath2,ProcessPath3,ProcessPath4
ProcessPath1 = "c:\toto1.bat"
ProcessPath2 = "c:\toto2.bat"
ProcessPath3 = "c:\toto3.bat"
ProcessPath4 = "%ProgramFiles%\Internet Explorer\iexplore.exe"
'Quitter si le script est déjà lancé
'If AppPrevInstance() = True Then WScript.Quit
'**************************************************************************
'Une boucle Do...Loop avec une pause de 15 minutes
Do
Call CheckProcess(DblQuote(ProcessPath4))
Call CheckProcess(DblQuote(ProcessPath1))
Call CheckProcess(DblQuote(ProcessPath2))
Call CheckProcess(DblQuote(ProcessPath3))
Call Pause(15) 'Pause de 15 minutes
Loop
'**************************************************************************
Sub CheckProcess(ProcessPath)
Dim strComputer,objWMIService,colProcesses,WshShell,Tab,ProcessName,MyCommandLine
strComputer = "."
Tab = Split(ProcessPath,"\")
ProcessName = Tab(UBound(Tab))
ProcessName = Replace(ProcessName,Chr(34),"")
MyCommandLine = "cmd /c "& DblQuote(ProcessPath) &""
MsgBox "ProcessName : " & ProcessName & vbCrLf & "CommandLine : " _
& MyCommandLine,vbInformation,"CheckProces"
Set objWMIService = GetObject("winmgmts:" _
& "{impersonationLevel=impersonate}!\\" & strComputer & "\root\cimv2")
Set colProcesses = objWMIService.ExecQuery _
("Select * from Win32_Process Where Name like '%" & ProcessName _
& "%' or CommandLine like '%" & MyCommandLine & "%'")
If colProcesses.Count = 0 Then
Set WshShell = CreateObject("WScript.Shell")
WshShell.Run ProcessPath
Else
Exit Sub
End if
End Sub
'**************************************************************************
'Fonction pour ajouter les doubles quotes dans une variable
Function DblQuote(Str)
DblQuote = Chr(34) & Str & Chr(34)
End Function
'**************************************************************************
Sub Pause(NMinutes)
Wscript.Sleep(NMinutes*1000*60)
End Sub
'**************************************************************************
Function AppPrevInstance()
'Vérifie si un script portant le même nom que le présent script est déjà
'lancé
Dim strComputer,objWMIService,colScript,objScript,RunningScriptName,Counter
strComputer = "."
Counter = 0
Set objWMIService = GetObject("winmgmts:" _
& "{impersonationLevel=impersonate}!\\" & strComputer & "\root\cimv2")
Set ColScript = objWMIService.ExecQuery _
("SELECT * FROM Win32_Process WHERE Name = 'Wscript.exe' OR Name = 'Cscript.exe'")
For Each objScript In colScript
RunningScriptName = Mid(objScript.CommandLine, _
InstrRev(objScript.CommandLine, "\", -1, 1) + 1, _
Len(objScript.CommandLine) - InstrRev(objScript.CommandLine, "\", -1, 1) - 2)
If WScript.ScriptName = RunningScriptName Then Counter = Counter + 1
Wscript.Sleep 10000
Next
If Counter > 1 Then
AppPrevInstance = True
Else
AppPrevInstance = False
End If
Set colScript = Nothing
Set objWMIService = Nothing
End Function
'**************************************************************************
Upvotes: 1
Views: 118
Reputation: 18847
I solved the problem like this :
Option Explicit
If AppPrevInstance() Then
MsgBox "Il y a une instance déjà en cours",VbExclamation,"Il y a une instance déjà en cours"
WScript.Quit
Else
Do
Call Main(Array("c:\toto1.bat","c:\toto2.bat","c:\toto3.bat","%ProgramFiles%\Internet Explorer\iexplore.exe"))
Call Pause(15) 'Pause de 15 minutes
Loop
End If
'**************************************************************************
Sub Main(colProcessPaths)
Dim ProcessPath
For Each ProcessPath In colProcessPaths
CheckProcess(ProcessPath)
Next
End Sub
'**************************************************************************
Sub CheckProcess(ProcessPath)
Dim ProcessName : ProcessName = StripProcPath(ProcessPath)
With GetObject("winmgmts:" & "{impersonationLevel=impersonate}!\\.\root\cimv2")
With .ExecQuery("SELECT * FROM Win32_Process WHERE Commandline LIKE " & CommandLineLike(ProcessName))
If .Count = 0 Then
With CreateObject("WScript.Shell")
.Run DblQuote(ProcessPath)
End With
Else
Exit Sub
End if
End With
End With
End Sub
'**************************************************************************
Function AppPrevInstance()
With GetObject("winmgmts:" & "{impersonationLevel=impersonate}!\\.\root\cimv2")
With .ExecQuery("SELECT * FROM Win32_Process WHERE CommandLine LIKE " & CommandLineLike(WScript.ScriptFullName) & _
" AND CommandLine LIKE '%WScript%' OR CommandLine LIKE '%cscript%'")
AppPrevInstance = (.Count > 1)
End With
End With
End Function
'**************************************************************************
Sub Pause(Minutes)
Wscript.Sleep(Minutes*1000*60)
End Sub
'**************************************************************************
Function StripProcPath(ProcessPath)
Dim arrStr : arrStr = Split(ProcessPath, "\")
StripProcPath = arrStr(UBound(arrStr))
End Function
'**************************************************************************
Function CommandLineLike(ProcessPath)
ProcessPath = Replace(ProcessPath, "\", "\\")
CommandLineLike = "'%" & ProcessPath & "%'"
End Function
'**************************************************************************
'Fonction pour ajouter les doubles quotes dans une variable
Function DblQuote(Str)
DblQuote = Chr(34) & Str & Chr(34)
End Function
'**************************************************************************
Upvotes: 1
Reputation: 200453
MyCommandLine
contains backslashes, which are escape characters in WMI queries. Unescaped backslashes in a path make the query invalid, thus resulting in the error you observed.
Replace
MyCommandLine = "cmd /c "& DblQuote(ProcessPath) &""
with
MyCommandLine = "cmd /c "& DblQuote(Replace(ProcessPath, "\", "\\")) &""
Upvotes: 2