Domanda

Ho una configurazione scenario in cui ho bisogno di testare per vedere se i risultati di un'esecuzione di file .bat restituito risultati. Il file bat richiama un altro exe e il file .bat ha una finestra CMD DOS che emette critica info error a quella finestra DOS dal exe. Se il .exe non si avvia correttamente, sono in grado di verificare i risultati nel nostro DB SQL. Ho bisogno di chiudere il file .bat corrente e ri-lanciarlo. Questo sembra abbastanza semplice, posso ottenere il ProcessID utilizzando la chiamata WMI. Posso terminare il processo con un comando Terminate (). Questo funziona per qualsiasi exe che uso per i test: il blocchetto per appunti, calc, IExplorer, ecc Quando eseguo il VBScript per uccidere il file .bat, si dice che termina il PID (che lo fa, dal momento che non riesco a vedere più il PID) , tuttavia, la finestra DOS è ancora aperto e l'exe chiamato dal file .bat è ancora in esecuzione. Se clicco sulla "X" sulla finestra DOS oppure fare clic destro sulla barra del titolo e selezionare "Chiudi", la finestra DOS e il file EXE sono entrambi uccisi. Come faccio ad avere questo script per funzionare correttamente. Il server è in esecuzione Windows Server 2003 (alcuni sono x32 e altri sono x64). Qualche idea? Ecco una versione del mio codice, ci sono stati diversi giri:

If colFiles.Count = 0 Then
Wscript.Echo "The file does not exist on the remote computer."
Else
Wscript.Echo "The file exists on the remote computer."
Set objWMIService = GetObject("winmgmts:" & "{impersonationLevel=impersonate}!\\" & strComputer & "\root\cimv2")
Set colProcessList = objWMIService.ExecQuery("Select * from Win32_Process")
For Each objItem in colProcessList
If InStr(objItem.CommandLine, "r15_A.bat") Then
    Wscript.Echo "Batch file: " & objItem.CommandLine  & "  Process ID: " & objItem.ProcessID & "  Parent ID: " & objItem.ParentProcessID
    Call TerminateProcess(objItem.ParentProcessID)
    Call TerminateProcess(objItem.ProcessID)
End If
Next
dim shell
set shell=createobject("wscript.shell")
shell.run BATDIR & BATFILE
'set shell=nothing
End If


Function TerminateProcess(PID)

Set objWMIService = GetObject("winmgmts:\\.\root\CIMV2")
Set colProcesses = objWMIService.ExecQuery("SELECT * FROM Win32_Process WHERE Handle = '" & PID & "'")
For Each objProcess in colProcesses
On Error Resume Next
return = objProcess.Terminate()
Set colProcesses = objWMIService.ExecQuery("SELECT * FROM Win32_Process WHERE Handle = '" & PID & "'")

If Error Then

TerminateProcess = FALSE
Else
TerminateProcess = TRUE
msgBox colProcesses.Count
End If
Next

End Function

Ho anche cercato di usare i SendKeys per inviare Alt-F4, X, C, ecc AppActivate fa portare la finestra DOS corretto verso la parte anteriore.

    Set WshShell = CreateObject("WScript.Shell")
    WshShell.AppActivate "r15_A"
    'WshShell.SendKeys("+{F10}")
    WshShell.SendKeys("C")   

Grazie in anticipo

EDIT -------------- Sì, sto andando ad avere per uccidere il processo che questo chiamate file .bat. L'unico lato negativo è questa finestra DOS rimane aperta. Fastidioso ma posso conviverci. Alla fine ho scritto uno script simile al mio primo ma controlla solo per l'istanza voglio uccidere controllando il parametro CommandLine: (Il primo bit di codice con test "-FAIL.txt" per vedere se un file è presente FAIL , se lo è, allora il resto delle scipts esegue)

Set colFiles = objWMIService. _
ExecQuery("Select * From CIM_DataFile Where Name = 'S:\\servers\\Logs\\" & LOGFILE & "-FAIL.txt'")

If colFiles.Count = 0 Then
'Wscript.Echo "The file does not exist on the remote computer."
Else
'Wscript.Echo "The file exists on the remote computer."
strComputer = "."
Set objWMIService = GetObject("winmgmts:" _
& "{impersonationLevel=impersonate}!\\" & strComputer & "\root\cimv2")
Set colProcessList = objWMIService.ExecQuery _
("Select * from Win32_Process Where Name = 'AppStart.exe'")
For Each objProcess in colProcessList
    IF instr(objProcess.CommandLine, "robo05-A") > 0 THEN 
        'msgBox "Found text"
        objProcess.Terminate()
        'This part restarts the failed .bat file.
        wscript.sleep (200) 
        dim shell
        set shell=createobject("wscript.shell")
        shell.run BATDIR & BATFILE
        'set shell=nothing
    ELSE
        'msgBox "Not found"
    END IF
Next
End If
È stato utile?

Soluzione

Il problema vostro avere è il file eseguibile che viene chiamata dall'interno del file batch è ancora in esecuzione. Ho cercato di ricreare la configurazione con una mazza il solo fatto un ping -t %computername%, e abbastanza sicuro il VBScript ucciso il cmd.exe, ma non il ping (Si prega di notare la Capogruppo PID era explorer.exe, quindi probabilmente non si vuole tentare di uccidere quello). Ora ho potuto facilmente uccidere ping.exe dal task manager che poi ha chiuso la finestra ... ma sapevo solo di farlo perché sapevo che cosa la mazza stava facendo e quello che era rimasto aperto. Si potrebbe fare una ricerca WMI per il processo che contiene "ping.exe", afferrare il PID e quindi chiudere questo e che sarebbe fondamentalmente facendo la stessa cosa. Naturalmente nella tua situazione "ping.exe" non è probabilmente lo stesso eseguibile come il mio. Se l'exe cambia ogni ora e poi allora si potrebbe prendere la riga di comando dal processo di trovare il parametro che contiene il percorso del file al file r15_A.bat, quindi utilizzare il FileSystemObject per aprire questo file bat, cercare eventuali eseguibili che si chiama che potrebbe eventualmente essere ancora in esecuzione e poi uccidere chi .... ma in realtà che può essere eccessivo per ciò che il vostro cercando di realizzare.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top