2013-11-28 15 views
7

Sto cercando di scrivere un file batch che fa due cose:Come si attende che un'attività Task Scheduler termini in un file batch o C#?

  1. In primo luogo si lancia un programma di installazione (install.exe) che installa un programma (program.exe).
  2. In secondo luogo, avvia un'istanza del programma installato (program.exe). Questo deve essere eseguito dopo il completamento dell'installazione.

Questo sarebbe relativamente semplice tranne che l'installatore ha bisogno di privilegi di amministratore e deve essere eseguito in un contesto utente. Anche con queste restrizioni questo sarebbe ancora relativamente semplice se non che io sono in esecuzione questo su un ruolo Azure Worker, il che significa due cose:

  1. Elevated batch files must be run from a startup task.
  2. There is no user context for startup tasks in Azure worker roles.

Sembra quindi che la soluzione è a run the installer as a Task Scheduler task in a real user context. Tuttavia, questo viene fornito con l'avvertenza che avrei quindi bisogno di aspettare che questa attività finisse prima che potessi lanciare program.exe.

Così, la mia domanda è: come faccio ad aspettare in un compito di pianificazione per finire in un file batch?

In alternativa, è possibile collegare a margherita le due chiamate nel mio file batch con un'unica attività dell'Utilità di pianificazione (l'Utilità di pianificazione supporta fino a 16 eventi sequenziali in una singola attività [Citazione necessaria]).

Tuttavia, se prendo questo approccio il mio file batch terminerà non appena l'operazione è pianificata , non appena si finiture. Sfortunatamente, devo aspettare che finisca prima di poter fare qualsiasi logica nel mio ruolo di lavoratore. Tuttavia, se riesco a verificare se l'attività dell'Utilità di pianificazione è terminata da C# (SENZA privilegi di amministratore), posso solo attendere lì.

Così una seconda risposta valida sarebbe alla domanda: Come posso controllare se un compito Utilità di pianificazione è stato completato da C#?

EDIT: ho pensato di chiarire la risposta qui sotto da MC ND un po ':

Da un livello elevato, questo comando controlla se l'attività è in esecuzione, e poi si dorme e loop se è.

:loop 
for /f "tokens=2 delims=: " %%f in ('schtasks /query /tn yourTaskName /fo list ^| find "Status:"') do (
    if "%%f"=="Running" (
     ping -n 6 localhost >nul 2>nul 
     goto loop 
    ) 
) 

La chiamata schtasks /query /tn yourTaskName /fo list uscite qualcosa quanto segue:

Folder: \ 
HostName:  1234567890 
TaskName:  \yourTaskName 
Next Run Time: 11/27/2030 11:40:00 PM 
Status:  Ready 
Logon Mode: Interactive/Background 

Il comando per i loop su ogni linea in uscita. Ogni riga è divisa in due token utilizzando il delimitatore ":". Se viene trovata una riga che inizia con "Status", il token dopo il delimitatore in quella riga viene memorizzato nella variabile f (che nell'output di esempio sopra sarebbe "Ready").

La variabile f viene quindi verificata per verificare se corrisponde allo stato "In esecuzione". Se lo stato non è "In esecuzione", si presume che l'attività sia completata o fallita e che il ciclo esca. Se lo stato è "In esecuzione", l'attività è ancora in esecuzione e lo script batch si interrompe per un breve periodo prima di eseguire nuovamente il controllo. Ciò si ottiene effettuando una chiamata ping, poiché batch non ha un comando di sospensione.Una volta che lo script ha terminato, riavvia questa sequenza.

risposta

8

Da file batch, interrogare lo stato di attività, e se è in esecuzione, tenere l'interrogazione

:loop 
for /f "tokens=2 delims=: " %%f in ('schtasks /query /tn yourTaskName /fo list ^| find "Status:"') do (
    if "%%f"=="Running" (
     ping -n 6 localhost >nul 2>nul 
     goto loop 
    ) 
) 
+0

Funziona come un fascino. Anche se ho scambiato: 'ping -n 1 -w 1000 192.0.2.2> nul 2> nul' come comando di pausa. Ho ritenuto che fosse un po 'più facile eseguire il debug in questo modo per assicurarsi che funzionasse. –

4

È inoltre possibile sbarazzarsi del comando hacky ping -n utilizzando timeout.

Ecco la risposta di MC ND con timeout. Lo 1 nel campione corrisponde a 1 secondo.

:loop 
for /f "tokens=2 delims=: " %%f in ('schtasks /query /tn yourTaskName /fo list ^| find "Status:"') do (
    if "%%f"=="Running" (
     timeout /T 1 /NOBREAK > nul 
     goto loop 
    ) 
) 
Problemi correlati