2010-08-23 5 views
21

C'è un modo per un file batch (in questo caso, in esecuzione su Windows XP) per determinare se è stato avviato da una riga di comando (cioè all'interno di una finestra della console) o lanciato tramite la shell (ad esempio facendo doppio clic)?Mettere in pausa un file batch quando si fa doppio clic ma non quando si esegue da una finestra della console?

Ho uno script che mi piacerebbe avere una pausa in determinati punti quando viene eseguito tramite la shell, ma non quando viene eseguito su una riga di comando. Ho visto a similar question su SO, ma non sono in grado di utilizzare la stessa soluzione per due motivi: in primo luogo, se le pause debbano o meno dipendere da più fattori, solo uno dei quali è se è stato fatto doppio clic. Secondo, distribuirò questo script ad altri membri del mio team e non posso realisticamente chiedere a tutti loro di apportare modifiche al registro che influiranno su tutti gli script.

È possibile?

+0

L'altra risposta non ha suggerito una modifica del Registro. Solo cambiando la riga di comando che viene eseguita su una scorciatoia. Certo, questo non ti aiuterà molto se fai doppio clic sul file batch attuale. – Joey

+0

@ Joey - Hai ragione; Stavo confondendo la risposta e il suo primo commento. ;-) –

risposta

32

trovato uno :-) - Dopo disperatamente pensando a cosa cmd potrebbe fare quando viene eseguito in modo interattivo, ma non quando si lancia un file batch direttamente ... finalmente ho trovato uno.

La pseudo-variabile %cmdcmdline% contiene la riga di comando che è stata utilizzata per avviare cmd. Nel caso in cui cmd è stato avviato normalmente questo contiene qualcosa di simile al seguente:

"C:\Windows\System32\cmd.exe" 

Tuttavia, quando si avvia un file batch che appare così:

cmd /c ""C:\Users\Me\test.cmd" " 

piccola demo:

@echo off 
for %%x in (%cmdcmdline%) do if /i "%%~x"=="/c" set DOUBLECLICKED=1 
if defined DOUBLECLICKED pause 

Questo metodo di controllo potrebbe non essere il più efficace, tuttavia, ma /c dovrebbe essere presente come argomento solo se è stato avviato direttamente un file batch.

Works on my machine http://hypftier.de/dump/works_on_my_machine.png

Testato qui su Windows 7 x64. Può o non può funzionare, rompere, fare qualcosa di strano, mangiare bambini (potrebbe essere una buona cosa) o morderti nel naso.

+0

Bah. Stavo solo giocando con qualcosa di simile, ma stavo cercando di determinare se '% CMDCMDLINE%' conteneva '% 0'. Il controllo di '/ c' è * quindi * molto più facile, tuttavia, e non riesco a pensare a casi limite in cui il mio approccio avrebbe funzionato, ma non è così. Grazie! –

+2

@ Ben: ho pensato anche alla cosa '% 0', ma purtroppo si rompe. Quando esco '% cmdcmdline%' tramite 'for' il percorso e il nome del batch vengono suddivisi in due token poiché la mia home directory contiene spazi e la riga di comando ha doppi apici come si può vedere sopra che getta' for' off . Un'altra opzione potrebbe essere quella di usare 'echo.% Cmdcmdline% | findstr/i/c:"% ~ 0 "> nul 2> & 1 && set DOUBLECLICKED = 1' (o forse' || ', faccio sempre errori con' findstr '), che in realtà cercherebbe'% 0' invece di fare affidamento sulla tokenizzazione. Tuttavia, fallirebbe se il batch fosse chiamato da un altro batch. – Joey

+0

- In realtà stavo usando trucchi di sottostringa piuttosto che 'FOR', ma batch non è adatto alla manipolazione di stringhe. Il tuo trucco '/ c' è molto più semplice e semplice e dovrebbe funzionare a meno che l'utente non stia facendo qualcosa di veramente * bizzarro. –

2

Un approccio potrebbe essere quello di creare un file Autoexec.nt nella root di C: \ che sembra qualcosa di simile:

@set nested=%nested%Z 

Nel file batch, controllare se% nidificato% è "Z" - se è "Z", quindi hai fatto doppio clic, quindi metti in pausa. Se non è "Z" - sarà "ZZ" o "ZZZ" ecc. Poiché CMD eredita il blocco di ambiente del processo genitore.

-Oisin

+0

Idea interessante, ma non sembra funzionare. 'AUTOEXEC.NT' sembra essere completamente ignorato,' AUTOEXEC.BAT' viene eseguito una sola volta (all'avvio del sistema) e la chiave del Registro di sistema AutoRun viene eseguita una volta per sessione 'CMD.EXE' indipendentemente da come è stata avviata. –

+1

I file batch non vengono avviati in un nuovo processo 'cmd'. Quindi, se accendo l'istanza di 'cmd' e avvio il file batch da lì,' nested' sarà 'Z'. Altrimenti è una buona idea per il rilevamento di shell annidate, ma non è adatto per i file batch. – Joey

+0

Un'altra nota: 'autoexec.nt' non risiede mai nella directory principale dell'unità ma in'% systemroot% \ system32'. Per quanto ne so, riguarda solo 'command.com', non' cmd', comunque. – Joey

0

Un po 'più di informazioni ...

comincio con un file batch (test.cmd) che contiene:

@echo %cmdcmdline% 

Se fa doppio clic il batch "test.cmd" file all'interno di Windows Explorer, la visualizzazione delle echo% CMDCMDLINE% è:

cmd /c ""D:\Path\test.cmd" " 

Quando si esegue il file batch "test.cmd" da all'interno di una finestra del prompt dei comandi, il display di
echo% cmdcmdline% dipende da come è stata avviata la finestra di comando ...

Se avvio "cmd.exe" facendo clic su "Start-Orb" e "Prompt dei comandi" o se faccio clic su "Start-Orb" ed eseguo "cmd.exe" dalla casella Cerca/Esegui. Poi eseguo il file batch "test.cmd", la visualizzazione delle echo% CMDCMDLINE% è:

"C:\Windows\system32\cmd.exe" 

Inoltre, per me, se faccio clic su "Prompt dei comandi" dal collegamento sul desktop, quindi eseguire il " test.cmd" batch di file, la visualizzazione delle echo% CMDCMDLINE% è anche:

"C:\Windows\system32\cmd.exe" 

Ma, se io 'tasto destro del mouse' all'interno di una finestra di Windows Explorer e selezionare 'Apri Prompt dei comandi Qui', quindi eseguire il file batch "test.cmd", la visualizzazione di echo% cmdcmdline% è:

"C:\Windows\System32\cmd.exe" /k ver 

Quindi, fai attenzione, se avvii "cmd.exe" da un collegamento che contiene un "/ c" nel campo "Target" (improbabile), allora il test nell'esempio precedente non riuscirà a testare correttamente questo caso .

3

Una risposta consolidata, derivata da gran parte delle informazioni trovate in questa pagina (e alcune altre pagine di overflow dello stack con domande simili). Questo non si basa sul rilevamento di/c, ma in realtà controlla il nome dello script nella riga di comando. Di conseguenza questa soluzione non metterà in pausa se hai fatto doppio clic su un altro batch e poi hai chiamato questo; hai dovuto fare doppio clic su questo particolare file batch.

:pauseIfDoubleClicked 
setlocal enabledelayedexpansion 
set testl=%cmdcmdline:"=% 
set testr=!testl:%~nx0=! 
if not "%testl%" == "%testr%" pause 
  1. La variabile "Testl" ottiene la linea completa della chiamata processore cmd, escludendo tutti gli virgolette fastidiosi.
  2. La variabile "testr" accetta "testl" e rimuove ulteriormente il nome del nome del file batch corrente se presente (che sarà se il file batch è stato richiamato con un doppio clic).
  3. L'istruzione if vede se "testl" e "testr" sono diversi. Se sì, batch è stato fatto doppio clic, quindi metti in pausa; se no, batch è stato digitato sulla riga di comando (o chiamato da un altro file batch), vai avanti.

Edit: Lo stesso può essere fatto in una sola riga:

echo %cmdcmdline% | findstr /i /c:"%~nx0" && set standalone=1 

In parole povere, questo

  • tubi del valore di %cmdcmdline%-findstr, che quindi cerca il nome dello script corrente
  • %0 contiene il nome dello script corrente, ovviamente solo se shift non è stato chiamato in anticipo
  • %~nx0 estratti nome del file e l'estensione da %0
  • >NUL 2>&1 mute findstr reindirizzando qualsiasi uscita per NUL
  • findstr imposta un errorlevel diverso da zero, se non riesce a trovare la stringa in questione
  • && esegue solo se il comando precedente restituito senza errori
  • di conseguenza, standalone non saranno definiti se lo script è stato avviato dalla riga di comando

Più tardi nello script che possiamo fare:

if defined standalone pause 
+0

Bello, mi piace l'unico- fodera! Funziona su Windows 7. Se non usi "shift" puoi anche chiamare direttamente 'ECHO% cmdcmdline% | findstr/i/c: "% ~ nx0"> NUL 2> & 1 && PAUSE' alla fine dello script - nessuna necessità di una variabile. – EM0

Problemi correlati